“Gremlins” is a cult movie from 1984. It’s about a small creature called “Mogwai” that a boy buys from an old Chinese man (don’t try this at home) and calls it “Gizmo”. He has to follow 3 certain rules: never feed Gizmo after midnight, don’t let him touch water and keep him away from direct sun light. Naturally, the boy breaks all the rules, and the comedy begins. In essence, when a Gizmo touches water, it clones itself to new Gizmos. If it feeds after midnight, it turns into a bad gremlin (called “White Stripe”), which melts under direct sunlight. We’ve adapted the movie plot a bit to fit into a Java project.

In this exercise you will write a (relatively) simple game based on “Gremlins”. The game builds a city (2-d array) with walls, water and food.  Gizmo enters the city from one of its corners, and wanders randomly around the city in order to find the exit (which is usually in the opposite corner). On its way, gizmo may touch the water (then duplicates itself) or find food. If he feeds after midnight, he turns into a white-stripe. For that, the game holds a clock object so you can track the time. A white stripe kills all the gizmos that are on the same city cell as he is. But don’t worry, when the sun comes up, all the white-stripes melt and die. Somewhat educational J

You will be required to practice your knowledge in flow control, 2-dimensional arrays and writing your own classes.  We provide you with a graphics engine which will display the game as it runs. The graphics engine was developed by Shlomi Babluki ©.

Important: some of the API you have to implement is given within this page. The entire API, however, is given here. You will have to read it completely, sooner or later, in order to understand the requirements.

The game has a single clock, which is a Clock object saved within the GremlinsGame instance. You will develop a very basic clock, which supports advancing minutes (advanceMinute), hours (advanceHour), whether it’s night or day time, and a method that builds a String which represents the time (toString).

Description: http://t2.gstatic.com/images?q=tbn:ANd9GcQzADNpy7XCFHyVHi3gMBi5-2cmq5Z-obavSY_KEPwpb4R8D3Q&t=1&usg=__tKfVUTeunbSDO7ZddskOk75hMN8=Write a class called Clock within a package called gremlins (recall how to do that). Implement the following API:

·         Constants:

o    public static final int MIDNIGHT = 0;

o    public static final int MORNING = 6;

o    public static final int EVENING = 18;

·         public Clock(int startingTimeInHours)

o   A constructor, initializing the clock with the given parameters.

o   See the API for details.

·         public void advanceHour()

o   Advances the clock one hour. Remember that there is no such hour as ‘30’!

·         public void advanceMinute()

o   Advances the clock one minute.

o   If the time is 14:08, after calling this method it will be 14:09.

o   If the time is 03:59, after calling this method it will be 04:00.

·         public int getHours()

o   Returns the hours part of the time (0-23).

·         public int getMinutes()

o   Returns the minutes part of the time (0-59).

·         public boolean isDaytime()

o   Returns if it’s between morning and evening (see constants).

·         public boolean isNightTime()

o   Returns if it’s between midnight and morning (see constants).

·         public String toString()

o   Returns a String representation of the time.

o   Examples: 04:35, 00:51, 23:00

o   Do not write code twice! If you write the same code in separate methods, maybe you should, instead, call one method from within the other.

o   Try to avoid writing literals. Go over each of your literals, and think if it has a special role in your class. If it does, make it a final constant instead. Description: http://t3.gstatic.com/images?q=tbn:ANd9GcS3tsoY2wpCutPDyY8aHW2yK6V5VIz7ZFwC-keucinUbHpNI6s&t=1&h=184&w=151&usg=__SPbyKji-873DBRnEkIUppoFlE5w=

·         To test your code, write a main method which creates a new Clock object, changes its time (by calling the advance methods), and prints both the output and what part of the day it is. Think of special cases that need special attention, and test them. Once completed, delete the main method (don’t submit it).

The Gremlin class represents a single Mogwai (Gremlin in out interpretation), which can be a good Gremlin (“Gizmo”) or a bad one (“White Stripe”). At any given moment, the Gremlin knows its location in the city (x, y). It supports choosing a new direction to face, transforming into a White Stripe and cloning itself, in case it touched water.

Write a class called Gremlin in package gremlins, and implement the API below:

o    public enum Direction {NORTH, SOUTH, EAST, WEST}

o    public Gremlin(boolean isGizmo)

·         This is the only constructor of this class, and it sets whether the gremlin is a good gremlin (gizmo) or a bad one (white stripe).

o    public boolean isGizmo()

·         This method is self-explanatory..

o    public Direction changeDirectionRandomly()

·         Selects a random direction out of all the possible direction enumerations. Description: http://t1.gstatic.com/images?q=tbn:ANd9GcRuOpBvGLpfqF_W6t_wlYUaGl8YwHUnL07AEW4-tB7VUX7rvPw&t=1&usg=__r3aRW4UfS_5QOSGuUwPOLp_z9wY=

·         You will have to look into the API (or tutorial) of Java’s Enum to understand how to do that. Use the tutorial in our Material forum to get ideas as to what you can use to implement this method.

o    public void walkToCell(int newX, int newY)

·         This method just changes the location of the gremlin, as far as he sees it.

·         Since the gremlin is unaware of the City, it can’t really validate the coordinates.

o    public int getXLocation()

o    public int getYLocation()

o    public void transformToWhiteStripe()

·         Transforms the gremlin to a white stripe (no matter what it was before)

o    public Gremlin clone()

·         This is a standard clone method. In this method you are required to create a new Gremlin object with the exact same state as this one. You then return a reference to that new object.

·         Except for the cloning method, this class is pretty easy and self-explanatory.

·         The clone method is standard. You will meet many classes that implement it, and you will have to implement it many times, so it’s not too early to get to know it.

·         You may write your own instance variables. In general, you can always add class members, as long as they don’t change the API. If you made them public, you changed the API. This should not be a problem in this case, since ALL instance variables HAVE to be PRIVATE. ALWAYS.

·         I suggest you create a main (needless to say to delete it before submission), in which you create a new Gremlin, or several ones, of different types, try to get random directions in a loop, make it walk do several coordinates, see if it got there (getX/YLocation), try to transform it once and twice, and check the results with the isGizmo.

·         The City class holds a two dimensional array, which represents the gremlins city.

·         It’s an array of references to Enum values. Each of these values represents what’s on the specific cell: wall, food, water, etc. An empty cell is represented by the enum value “EMPTY”.

·         The Gremlins themselves will be kept in a separate collection, and since each Gremlin knows its position, the City object doesn’t have to.

·         This class is probably the most complex one. If it’s taking you a lot of time, you’re in the right direction J

·         The class supports building a new city. You will have to create the array, place the entrance and exit points, and then find a path that leads from the entrance to the exit. We call that pass “a golden passage”, and we mark it, so that, when we place walls in the city, we make sure there’s always a path Gizmo can walk safely through. Then we place random obstacles in the city, such as walls, food and water (avoid the golden pass!).

·         The class should also support adding a Gremlin to the city. The main game algorithm will use this functionality to add the first Gremlin, and to add Gremlins in case they touch water and clone themselves. You should keep a collection (ArrayList) of gremlins to keep track of who’s in the city and where.

·         You will also have to support two of the main game features: melting (killing) all the bad gremlins (we call it “the daylight massacre”), and making sure that all the White-Stripes in the city kill the Gizmos, each White Stripe kills all the Gizmos that are on the same cell as he is. This is called “Darwin’s natural selection” J

Write a class called City within the gremlins package. Implement the following API:

o    public enum CellType {ENTRANCE, EXIT, GOLDEAN_PASSAGE, EMPTY, WALL, WATER, FOOD}

·         All the possible types a cell can be.

o    public static final int DEFAULT_CITY_SIZE

·         This can be used by external classes to initialize a city of recommended or different sizes.

o    public City(int citySize, int entranceCellX, int entranceCellY, int exitCellX, int exitCellY)

·         This is the only class constructor. It instantiates a new object with the given city size, and allows setting the city entrance and exit points. Read the API for more details.

·         Make sure the parameters are valid. If not, print an appropriate error message (or several), and end the method (return). We will learn assertion mechanisms in the future (Exceptions).

o    public void addGremlin(Gremlin gremlin)

·         A new gremlin has entered the city!

·         Just adds another gremlin to your internal collection.

·         If the reference given is null, print an error message of your choice, and don’t add it.

o    public CellType getCellType(int cellX, int cellY)

o    public ArrayList getGremlins(int cellX, int cellY)

·         Returns a list of all the gremlins that are on the given cell.

·         You will probably want to create a specially built collection just to return its reference.

·         Validate the parameters. If they are invalid, print an error message and return null.

o    public ArrayList getGremlins()

·         This is an overloaded method, which returns a list of all the gremlins currently in the city.

·         It’s ok to just return a reference to your internal variable.

o    public boolean isLocationGoodForGremlin(int cellX, int cellY)

·         This method can be used by clients to know if they can move a Gremlin to a specific location in the city.

·         A good location is one that is within the city range and does not have a wall in it.

o    public void daylightMassacre()

·         The sun is shining! All the white-stripes (non-gizmo gremlins) must die.

·         Kill a gremlin by removing it from the collection (the garbage collector will pick it up).

·         You will have to take into consideration concurrency issues. See guidance for, well, guidance.

o    public void feedTheWhiteStripes()

·         Let all the white stripes (bad gremlins) in the city eat all the gizmos that share the same city cell with them.

·         Here, again, you will have to avoid concurrency issues, the same way you did with the previous method.

o    public CellType[][] getCityArray()

·         This method is used by the graphics engine. Just return a reference to your instance variable.

o    Some more basic getters (figure out the method definition yourself):

o    getCitySize()

o    getEntranceX()

o    getEntranceY()

o    getExitX()

o    getExitY()

·         Choose your instance variables wisely. Use a 2-dimensional array for the city cells (CellType[][]) and an ArrayList for the gremlins collection. In the future, know that you get hints on how to implement your instance variables by looking into the constructor parameters and the different method return types.

·         You may want to write some private methods to better divide the code into logical parts. Think carefully which methods are needed, how to name them, which parameters they should accept and what each should do. Don’t forget to document them the same way you document your public methods.

Concurrency

When you iterate a collection, you move from one element to the next. Consider the following code:

Turtle[] turtles = new Turtle[10];

for (Turtle t : turtles)

     if (t.isTailUp()) turtles.remove(t);

There are 10 iterations in the above loop (meaning, the loop block runs 10 times). However, if, in one of the iterations, we remove a turtle from the collection, how many iterations will we have? What will be the next turtle t? Those are difficult questions and are generally fall under the “concurrency issue”. Java does not allow it. Although the code compiles, if Java realizes, during runtime, that the collection has been changed while the loop is still going, she will crash the program.

So how do we deal with it?

A best practice would be cloning the collection and iterating the clone, while removing elements from or adding elements to the original collection. The sample above would work great like this:

Turtle[] turtles = new Turtle[10];

Turtle[] clonedTurtles = (Turtle[])turtles.clone();

for (Turtle t : clonedTurtles)

     if (t.isTailUp()) turtles.remove(t);

·         You have studied the clone() method and what a shallow copy is.

·         Avoid concurrency within your code, where concurrency may happen. Since cloning a collection is a pretty heavy task, don’t do it when it’s unneeded.

Marking the golden path

If you have the X,Y coordinates of the entrance and exit points, you can easily find a path between them. Start with the entrance point, and look for the exit point. Compare the X,Y coordinates of the cell you’re currently marking with the exit points coordinates, and move to the closer cell accordingly. Hint: at any given cell ‘mycell’, if exit.x is smaller than mycell.x, then nextcell.x should be mycell.x – 1.

Placing obstacles

There are more than a few ways to place obstacles around the city. Be creative and write your own algorithm. Make sure it’s general enough for any city size and for many obstacles. That is, if someone builds a city of a different size, or another programmer adds more obstacles to the enum, your code still works without changing it (remember input-->algorithm-->output?). Your algorithm should be based on random placement of random obstacles.

Write yourself a main method which creates a city of various sizes, adds gremlins to it, moving them around, cloning them, transforming them and killing them when time has come. Since there are many special cases here, your test code should not be short. We also encourage you to add some methods which print the city as text, with different characters for the different cell types and different gremlin types.

Don’t forget to remove all that testing code before submitting the exercise.

This class runs the game, and is responsible for making sure the game complies with the game rules, according to order.

Write a class called GremlinsGame, also in the package gremlins. Implement the API as given in the API link at the beginning of the exercise (or here is a direct link to the GremlinGame API).

The game should keep one instance of a Clock and one instance of a City.

The game engine is based on steps. In each step, these things happen:

-          1 hour elapses on the clock.

-          If it’s daytime, all the white stripes melt.

-          Each gremlin is moved to a random adjacent cell.

-          Each white-stripe devours all the gizmos that reside in its own cell.

The method nextMove is used by the graphics engine and should include all the above steps.

It’s your responsibility to test your code, but we provide you with 2 ways of seeing the game in action (one of them requires your work):

Provided main

Below is a short main method which should run the game until won (a Gizmo at the exit) or lost (no more Gizmos). Copy this text and paste it into your GremlinsGame class. This main you should submit, after adding support for command line arguments.

Note: this main does not work. It expects you to handle command line arguments. Take the opportunity and add the implementation where appropriate. The documentation and the code provide all the needed information in order to implement it.

      public static void main(String[] args) {

           

            // local variables

            int citySize = 0;

            int startingTime = 0;

            int entranceX = 0;

            int entranceY = 0;

            int exitX = 0;

            int exitY = 0;

           

            //----------------------------------------------------------------

            // TODO: write your own code below, to change the game parameters

            // according to the command line arguments.

            //----------------------------------------------------------------

            // validate args

            if (?) {

                  System.out.println("Syntax: GremlinsGame <size> <time> "

                              + "<entrance x> <entrance y> <exit x> <exit y>");

                  return;

            }

 

            // set the game parameters

            citySize = ?;

            startingTime = ?;

            entranceX = ?;

            entranceY = ?;

            exitX = ?;

            exitY = ?;

            //----------------------------------------------------------------

           

            // start a new game

            GremlinsGame game = new GremlinsGame(citySize, startingTime,

                        entranceX, entranceY, exitX, exitY);

           

            // track moves

            int moves = 0;

           

            // run the moves step by step

            do {

                  moves++;

                  game.nextMove();

            } while (!game.gameLost() && !game.gameWon());

           

            // game over, print statistics

            System.out.println("You " + (game.gameLost()? "lost." : "won!!"));

            System.out.println("Time: " + game.getClock());

            System.out.println("Moves: " + moves);

            System.out.println("Total gremlins: "

                        + game.getCity().getGremlins().size());

      }

 

Graphics engine, courtesy of Shlomi Babluki

Once everything is finally working great and you’re satisfied with your work, it’s time to get to the fun part, and bring the game to life.

Follow these steps in order to use our graphics engine:

1.       Make sure your own code compiles completely.

2.       Decide on a separate folder that will be used for the game, we call it the ‘bin folder’. For example: “C:\Intro2CS\bin\”

3.       Download gremlins_grafx.jar and save it in that folder (according to the example: C:\Intro2CS\bin\gremlins_grafx.jar)

4.       Create a subfolder named ‘gremlins’ (C:\Intro2CS\bin\gremlins\)

5.       Copy all your .class files, which you created when compiling your different classes, to the \gremlins subfolder. Eventually, it should look like this (you can ignore the file sizes):

6.       Run a CMD window. Go to the ‘bin folder’ (C:\Intro2CS\bin), and run this line:

7.       Change the command line arguments and see how it affects the game.

Enjoy!

As always, read the submission instructions and make sure you follow the styling guidelines, both available on our website. Note that the styling guidelines document has changed (or will be soon).

Since you’re writing a package named gremlins, you will need to create a subfolder with that name.

Make sure only the 4 files below are in the subfolder, Zip the subfolder itself and email. A hard copy is, as usual, needed as well.

·         Ex06.zip (file to submit)

o   gremlins (folder)

§  Clock.java

§  Gremlin.java

§  City.java

§  GremlinsGame.java (including your modified main)

 

Good luck!                 Description: http://t3.gstatic.com/images?q=tbn:ANd9GcRHEwya1JnfbSGstualw1zM_8jw_snf4ggeM3XkjTMGKxp50bk&t=1&usg=__aHOFNXHOt3GExe00_8hy-mPNfNs=

Boaz.

 

 

 

© 2010 Boaz Kantor, IDC