# GridWorld User Guide

## Software Installation

### Prerequisites:

• Understanding files and directories
• Unzipping files
• Compiling Java programs
• Using JAR files
Download the GridWorld distribution. Unzip it in a directory of your choice. As always, it is best to avoid directories with spaces such as My Documents . I suggest you unzip into c:\GridWorld (Windows) or ~/GridWorld (Linux, Mac). Look inside the directory that you just created and populated with the GridWorld files. Locate the file gridworld.jar . It is the most important file of the GridWorld distribution. You use this file for two separate purposes:
• To launch the GridWorld graphical user interface (GUI)
You need to tell your compiler or development environment about the gridworld.jar file. Each development environment has its own user interface for this task; you will find information about popular environments at the end of this document. You need to know how to launch a Java program that is distributed as a JAR file. On some operating systems, you may be able to double-click on the gridworld.jar file. Alternatively, you can open a command shell and type java -jar   /path/to/ gridworld.jar Replace /path/to with the path such as c:\GridWorld\ or ~/GridWorld .  Try it out: Launch GridWorld now. You should see a "starter world" like this:

### Prerequisites:

• Objects and classes
• Constructors
• Method calls
• Parameters and return values.

### Activity 1: Step and Run

When you launch GridWorld, you see a "starter world" containing a critter and a rock . A critter is a simulated creature that moves in the grid. When it moves, it drops a flower at its old position, letting you watch the critter's path. A rock has no purpose other than to block the critter. Critters don't pretend to be useful. They don't simulate any real entities, and their behavior is of no interest to biologists or social scientists. They were simply invented to make programming more intuitive and enjoyable. To see the critter in action, click the Step button. Click it a few more times. What happens when the critter runs to an edge of the grid or the rock? Now click the Run button. The critter keeps moving, as if you had clicked Step many times. You can crank up the speed by moving the slider to the right. After a while, the critter will have settled into a fixed path. Click Stop to stop it.

### Activity 2: Constructing an Object

Click into one of the empty cells of the grid. You will see a menu that shows constructors of the Critter and the Rock class. The Critter class has two constructors. The default constructor makes a green critter, and the second constructor lets you specify a color. The Rock class only has one constructor. Select the Rock constructor. A rock is inserted at the cursor location. Add a few more rocks, run the simulation and watch the critter bump into the rocks. You can add another critter in the same way. Try adding a pink critter into another empty location. Choose the constructor labeled com.collegeboard.gridworld.actor.Critter(java.awt.Color) A color dialog pops up. The first entry signifies a random color. Move down until you see a hot pink bar and select it. Click Ok . A pink critter is added. Click Step , and both critters move. Note that the pink critter drops pink flowers.

### Activity 3: Calling a Method

Click on one of the critters. You will see a menu that shows the methods of the Critter class. The menu is divided into two parts. The top part contains the Critter methods
actcanMovemovesetTracingturn
The bottom part contains a number of methods that are inherited from the Actor class. We will not need these methods when working with critters. (However, you may find the removeFromGrid method useful to remove excess critters or rocks.) Select the act method. You will see the critter act as if you had clicked the Step button. In fact, the Step button simply calls act for all grid occupants. Flowers and rocks define act to do nothing, but the Critter class has a more sophisticated definition of acting. If the critter can move, it does. Otherwise, it turns. Call the turn method. You can see the critter making a half-turn to the right. Call turn and move a few times until you get a feel for these methods. You will use them a lot when programming critters. Some methods return values. For example, the canMove method returns true if the critter can move in the current direction. When you call canMove , a dialog displays the result. Some methods take inputs. For example, the setTracing method lets you turn tracing on or off. When you call setTracing(false) , the critter stops dropping flowers. Call setTracing and set the input to false . Now move the critter and see that it no longer leaves a trace.

### Prerequisites:

• Understanding directories
• Java syntax for defining classes and methods
• Compiling a Java class
The critter in the starter grid is pretty boring. In this section, you will learn how to modify the behavior of a critter. To make your own critter, follow these steps:
1. Make a new directory
2. In that directory, define a class that extends Critter
3. Implement the act method
4. Optionally, supply a GIF image
5. In GridWorld, select your project directory
Here is a typical example. Make a directory to hold your project. I suggest c:\GridWorld\projects\myFirstCritter (Windows) or ~/GridWorld/projects/ myFirstCritter (Linux, Mac), but any directory will do. Type in the following class:
import com.collegeboard.gridworld.actor.Critter;
public class MyCritter extends Critter
{

public void act()
{
move();
move();
turn();
turn();
}
}

Compile the class. You need to use your own compiler or development environment. GridWorld can not edit or compile Java source code.

NOTE:  If the compiler can't find the Critter class, you need to add the gridworld.jar file to your compiler's class path.

If you like, you can add a file MyCritter.gif into the same directory. Any GIF image will do. If you don't supply your own image, the basic critter image is used instead.

Start GridWorld, select the World -> Load Project menu option, and select the directory that you created. A MyCritter object is automatically inserted. Click on Step a few times to see it act.

That's all there is to it. To get more sophisticated critters, you need to put more sophisticated code into the act method.

NOTE: You use two separate tools for your programming:
2. The GridWorld GUI, to run your program
Some people prefer to launch the GridWorld GUI from their development environment. That is easily done with a small launcher class, such as the following.
import com.collegeboard.gridworld.actor.ActorWorld;public
class MyWorld extends ActorWorld{ public MyWorld()
{ // configure my world add(new MyCritter()); }
public static void main(String[] args) { // construct
and show my world new MyWorld().show(); }}

## Exploring Object State

### Prerequisites:

• Instance fields
• The if statement

### Activity 1: Tracing a Square

In this section, we want to make a critter that carries out a specific task: to trace out a square of a given size.

In each step, the critter should either move (and drop a flower) or turn. If the square has sides of length n , then the critter needs to turn every n steps. Therefore, the critter needs to keep track of the number of steps that it has already taken.

An instance field is used for this purpose:
import com.collegeboard.gridworld.actor.Critter;
public class SquareDancer extends Critter
{

public void act()
{
. . .
}

private int steps;
}

If the number of steps is less than the side length, then the critter should move. Otherwise it should make a quarter turn.


public void act()
{      if (steps < SIDE_LENGTH)
{ move(); steps++; } else {
turn(); turn(); steps = 0; }
}


Note that we reset the step count to zero at each corner.

Here, we define SIDE_LENGTH as a constant:

public class SquareDancer extends Critter
{

public void act()
{
. . .
}

private int steps;
private static final int SIDE_LENGTH = 5;
}

### Activity 2: Supplying a Construction Parameter

How can we draw a square with a different side length? We'll add a second instance field to the  SquareDancer and supply a constructor that sets it.
import com.collegeboard.gridworld.actor.Critter;
public class SquareDancer extends Critter
{
public SquareDancer(int n)
{
sideLength = n;
}

public void act()
{
. . .
}

private int steps;
private int sideLength;
}

When you compile this class and select World -> Load Project, you don't get a SquareDancer object. The GridWorld doesn't know how to construct one since it doesn't know which value of n you might want.

This is not a major obstacle. Simply click on an empty cell and select the SquareDancer(int) constructor. Then specify a value.

Here we constructed two square dancers and changed the color of one of them. Then we ran them until they traced out their squares.

### Activity 3: Making a World

When you design new actor classes, you may want to specify a world for them to live in. Extend the ActorWorld class. In the constructor of your class, add actors at the desired locations.

import com.collegeboard.gridworld.actor.ActorWorld;import
com.collegeboard.gridworld.grid.Location;import
java.awt.Color;public class SquareDancerWorld extends
ActorWorld{ public SquareDancerWorld() {
SquareDancer alice = new SquareDancer(6);
alice.setColor(Color.ORANGE); SquareDancer bob = new
Location(5, 5), bob); }}

If you like, you can select a different grid. For example,
import com.collegeboard.grid.BoundedGrid;import
com.collegeboard.gridworld.actor.ActorWorld;public class
SquareDancerWorld extends ActorWorld{ public
SquareDancerWorld() { setGrid(new BoundedGrid(20,
20)); . . . }}
You can also set an UnboundedGrid ; then your critters never bump against an edge.

import com.collegeboard.grid.UnboundedGrid;import
com.collegeboard.gridworld.actor.ActorWorld;public class
SquareDancerWorld extends ActorWorld{ public
SquareDancerWorld() { setGrid(new
UnboundedGrid()); . . . }}

## Exploring Loops

### Prerequisites:

• The for statement
You can use GridWorld to visualize the actions of certain for loops. Many students find this visualization helpful for practicing their loop authoring skills.

### Activity 1: Placing Rocks

Consider this typical loop exercise. You are supposed to display a triangle with n rows, like this:

You need two nested loops. The outer loop traverses the n rows:

for (int i = 1; i <= n; i++)

For each row, you place 2n + 1 rocks.

for (int i = 1; i <= n; i++) for (int j = 1; j <= 2 * n +
1; j++)
Now you need to place the rocks. There is no need for a critter in this example. Simply extend ActorWorld :
public class TriangleWorld extends ActorWorld{ public
TriangleWorld() {  for (int i = 1; i <= n; i++) for
(int j = 1; j <= 2 * n + 1; j++) } { int row = i; int
col = n - i + j; add(new Location(row, col), new Rock());
} }}
When you load this project, the world constructor is executed, and you immediately see a pile of rocks. You can mouse over the rocks to check their locations.

### Activity 2: Stepping through a Loop

Maybe you want to see how the rocks are added, a step at a time? If so, extend a different world, the StepWorld . Place your code in the run method and call pause whenever you want the action to pause.
public class TriangleWorld extends StepWorld{
public void run() {  for (int i = 1; i <= n;
i++) for (int j = 1; j <= 2 * n + 1; j++) } { int row
= i; int col = n - i + j; add(new Location(row, col), new
Rock()); pause(); } }}
When you load the world, its run method executes until the first call to pause . Then it waits for you to click the Step button. Each time you click Step , the run method runs up to the next pause call. You can also click the Run button and see the program run in slow motion.

If you like, you can also add a message to the pause method. The message is displayed above the grid. For example,
pause("i=" + i + ",j=" + j);
displays the current values of i and j .

## Exploring Inheritance

### Prerequisites:

• The ArrayList class
• Java syntax for inheritance

### Activity 1: Eaters

In this section, we build up an inheritance hierachy of actors that look for food in the grid. We start with a class Eater that defines trivial methods eat and move . These methods will be redefined in subclasses:

public class Eater extends Actor
{
public boolean eat() { return false; }
public void move() {}
. . .
}

We expect eat to return true whenever the eater was successful in consuming a food item.

The act method is defined as follows:

public void act()
{
if (eat())
count++;
else
move();
}

private int count;

As you can see, a basic Eater isn't very successful. It neither eats nor moves. We will define subclasses that do a better job consuming the food that is available in the grid.

When you form subclasses, you should follow these rules. (These are not rules of Java, but merely rules of the eater game.)
• You may override eat and move, but don't override act.
• In eat, don't be greedy. You may remove at most one edible object from the grid.
• In eat, don't move. Stay where you are, look around you, and eat if you find something edible.
• In move, don't eat. Just move to another location.
• In eat and move, look at your neighboring locations only. No peeking elsewhere . . .
The Eater class has two convenience methods that get the neighboring actors (for eating) and the empty neighbor locations (for moving).

We provide a simple implementation of the Eater class, RockHound . A RockHound likes to eat rocks. In its eat method, it looks at its neighbors and consumes the first one that is a Rock . In its move method, it moves to a random empty neighbor location.

The EaterWorld is populated with some rocks and a RockHound . Load it and see the RockHound randomly move about and consume the rocks.

### Activity 2: Smart Eaters

How can a rock hound to a better job without cheating? (Cheating is easy--just get the whole grid and remove all rocks. We discuss measures against cheating in the next activity.)

The key is to explore the grid more systematically. A SmartRockHound remembers the locations that it has already visited, and it doesn't visit them again if it has a choice.
public class SmartRockHound extends RockHound{ public
SmartRockHound(Color color) { super(color);
visitedLocations = new ArrayList<Location>();  }
public void move() {
getEmptyNeighborLocations()) { if
(!visitedLocations.contains(loc)) { moveTo(loc);
return; } } super.move(); }  private
ArrayList<Location> visitedLocations;}
Try it out: Add a SmartRockHound to the EaterWorld and see how it out-eats the RockHound .

Food for thought: The SmartRockHound does rather well in a BoundedGrid . Try putting it into an UnboundedGrid . What goes wrong? How can you fix it?

### Activity 3: Cheaters and Honest Eaters

Food for thought: Can you design an eater that is even more efficient than a SmartRockHound ? Can you do it without cheating?

When faced with this problem, the temptation to cheat can be overwhelming. Let's try to prevent cheating. The HonestEater class contains anti-cheating measures. To prevent cheating, we require all students to extend HonestEater rather than Eater .

The act method of the HonestEater class calls the act method of Eater , but it first records
• the number of objects in the grid before the call
• the position of this actor before the call
After the act method returns (which, as you recall, invokes eat and move ), the following checks are carried out:
• If the number of objects in the grid has decreased by more than one, this actor was too greedy.
• If the number of objects in the grid has decreased by one, and the position has changed, this actor has both eaten and moved--a crime.
• If the actor has moved beyond the neighbors of the old location, it went too far.
If any of the checks show cheating, the penalty is cruel: this actor is removed from the grid.

The act method has been defined as final so that a dishonest eater can't override it.

There is another check, to prevent eaters from peeking beyond their neighbors: The getGrid method returns null . This way, an eater can't map out an optimal path to all food sources.

Food for thought: Can a subclass of HonestEater defeat the greediness check by adding worthless trinkets into the grid after consuming multiple rocks?

Food for thought: There is one nefarious practice that the HonestEater does not detect. An eater can move to multiple locations and peek, thereby gaining an unfair advantage. How can you prevent that?

## Exploring Recursion

### Activity 1: A triangle of rocks

We want to create an actor that drops rocks in a triangle shape, like this:

One rock should be dropped in each call to act .

The size of the triangle (number of rocks at the bottom) is passed as a construction parameter:
TriangleWalker(int size)
But we don't want to work very hard. Here is an interesting approach.

Make the triangle walker lay a row of rocks. That's easy:
public void act() { if (steps > 0)  {
Grid<Actor> gr = getGrid(); Location loc =
getLocation(); moveTo(gr.getNeighborLocation(loc, Grid.EAST));
new Rock().putInGrid(gr, loc); steps--;  }
}
TODO: This would be easier if the actor didn't store the grid, or if there was a convenience method moveInDirection(Grid.EAST)

Now the triangle walker could go back up and lay a shorter row of rocks and a shorter one again. But that's tedious. Instead, it will just construct a buddy:
buddy = new TriangleWalker(size - 1);
When it is done laying a row of rocks, it adds the buddy to the grid and removes itself.

public void act()
{
if (steps > 0)
{
. . .
}
else
{
if (buddy != null) buddy.putInGrid(gr, buddyLocation);
removeFromGrid();
}

}

This is a recursive solution. To do its job, the TriangleWalker asks another TriangleWalker to carry out a simpler instance of the job.

Here is the complete class: TriangleWalker.java

Exercise: Implement a triangle walker that makes a triangle like this:

* ********

### Activity 2: One-eyed pyramids

One-eyed pyramids (like the one on the dollar bill ) want to know where rocks are, but they can only see their direct neighbors, and they can't move.

Recursion to the rescue: If a pyramid doesn't see a rock, it creates a buddy pyramid in a neighboring location. In each call to act , it asks its buddies if they have seen a rock. Once a pyramid has been enlightened, it turns yellow.

Here is the complete class: RockFinder.java

Exercise: In this solution, a RockFinder keeps making buddies. What would happen if each RockFinder makes just one buddy? Try it out.

## Other Worlds

### Prerequisites:

• Inheritance
• Interfaces
It is easy to build other worlds, for example board games that live as a grid. Here is an example: a tile game to practice one's memory.

The game board contains covered tiles. The player's job is to uncover matching pairs. Click on a tile to flip it. Then click on another. If both tiles have the same color, they both stay exposed. If not, they are both covered again.

To implement this game, we don't need to subclass Actor . Simply provide a Tile class with a getColor and a flip method. The getColor method is called by the GridWorld framework to apply the correct color. Return black if the tile is covered and the actual color when it is exposed.
public class Tile{ private Color color; private
boolean up;  public Tile(Color color) { up =
false; this.color = color; } public Color
getColor() { if (up) return color; else
return Color.BLACK; } public void setColor(Color
color) { this.color = color; }  public void
flip() { up = !up; }}

The game class extends AbstractWorld<Tile> since the world contains a grid of tiles. The constructor populates the grid, and the locationClicked method is called whenever the user clicks on a location.

public class TileGame extends AbstractWorld<Tile>{
public TileGame() { Color[] colors =  {
Color.RED, Color.BLUE, Color.GREEN, Color.CYAN, Color.PINK,
Color.ORANGE, Color.GRAY, Color.MAGENTA, Color.WHITE,
Color.YELLOW }; for (Color color : colors) {
setMessage("Click on the first tile"); } public boolean
locationClicked(Location loc) { Grid<Tile> gr =
getGrid(); Tile t = gr.get(loc); if (t != null)  {
t.flip();  if (up == null) { setMessage("Click on
the second tile"); up = loc; } else { Tile
first = gr.get(up); if
(!first.getColor().equals(t.getColor())) { first.flip();
t.flip(); } setMessage("Click on the first tile"); up =
null; }   } return true;  }
private Location up; }
The locationClicked method returns true to indicate to the framework that the game itself handles clicks. (Otherwise the framework would try to manipulate or add tiles.)

Note that the Step and Run buttons don't do anything in this game.

## Appendix: Installing the JAR file

### Eclipse

You need to do the following for every project.
1. Start a project as usual
2. Select the project in the "Package explorer" window
3. Select Project -> Properties from the menu
4. Click on Java Build Path and select the Libraries tab
5. Click the Add External JARs... button
6. Navigate to the directory containing gridworld.jar. Select gridworld.jar.

### BlueJ

You need to do the following once .
1. Select the menu option Tools -> Preferences
2. In the resulting dialog, click on the Libraries tab
4. Navigate to the directory containing gridworld.jar. Select gridworld.jar.
5. Restart BlueJ

### Command-line Compiler

When you compile or run programs, add both the current directory and gridworld.jar to the class path. On Windows, use a semicolon to separate . (i.e. the current directory) from the path to the JAR file:

javac -classpath .;\path\to\gridworld.jar
*.java Replace \path\to\ with the path such as
c:\GridWorld\

On Linux/Unix/Mac OS X, use a colon as a separator instead:

javac -classpath .: /path/to/ gridworld.jar *.java
Replace /path/to with the path such as  ~/GridWorld