Think Java: How to Think Like a Computer Scientist by Allen B. Downey - HTML preview

PLEASE NOTE: This is an HTML preview only and some elements such as links or page numbers may be incorrect.
Download the book in PDF, ePub, Kindle for a complete version.

Chapter 10

GridWorld: Part 2

Part 2 of the GridWorld case study uses some features we haven’t seen

yet, so you will get a preview now and more details later.

As a re-

minder, you can find the documentation for the GridWorld classes at http:

//www.greenteapress.com/thinkapjava/javadoc/gridworld/.

When

you

install

GridWorld,

you

should

have

a

folder

named

projects/boxBug, which contains BoxBug.java, BoxBugRunner.java and

BoxBug.gif.

Copy these files into your working folder and import them into

your development environment.

There are instructions here that

might help:

http://www.collegeboard.com/prod_downloads/student/

testing/ap/compsci_a/ap07_gridworld_installation_guide.pdf.

Here is the code from BoxBugRunner.java:

import info.gridworld.actor.ActorWorld;

import info.gridworld.grid.Location;

import java.awt.Color;

public class BoxBugRunner {

public static void main(String[] args) {

ActorWorld world = new ActorWorld();

BoxBug alice = new BoxBug(6);

124

Chapter 10. GridWorld: Part 2

alice.setColor(Color.ORANGE);

BoxBug bob = new BoxBug(3);

world.add(new Location(7, 8), alice);

world.add(new Location(5, 5), bob);

world.show();

}

}

Everything here should be familiar, with the possible exception of Location,

which is part of GridWorld, and similar to java.awt.Point.

BoxBug.java contains the class definition for BoxBug.

public class BoxBug extends Bug {

private int steps;

private int sideLength;

public BoxBug(int length) {

steps = 0;

sideLength = length;

}

}

The first line says that this class extends Bug, which means that a BoxBug is

a kind of Bug.

The next two lines are instance variables. Every Bug has variables named

sideLength, which determines the size of the box it draws, and steps, which

keeps track of how many steps the Bug has taken.

The next line defines a constructor, which is a special method that initial-

izes the instance variables. When you create a Bug by invoking new, Java

invokes this constructor.

The parameter of the constructor is the side length.

Bug behavior is controlled by the act method. Here is the act method for

BoxBug:

public void act() {

if (steps < sideLength && canMove()) {

move();

10.1. Termites

125

steps++;

}

else {

turn();

turn();

steps = 0;

}

}

If the BoxBug can move, and has not taken the required number of steps, it

moves and increments steps.

If it hits a wall or completes one side of the box, it turns 90 degrees to the

right and resets steps to 0.

Run the program and see what it does. Did you get the behavior you ex-

pected?

Exercise 10.1. Now you know enough to do the exercises in the Student

Manual, Part 2. Go do them, and then come back for more fun.

10.1

Termites

I wrote a class called Termite that extends Bug and adds the ability to

interact with flowers.

To run it, download these files and import them into your development en-

vironment:

http://thinkapjava.com/code/Termite.java

http://thinkapjava.com/code/Termite.gif

http://thinkapjava.com/code/TermiteRunner.java

Because Termite extends Bug, all Bug methods also work on Termites. But

Termites have additional methods that Bugs don’t have.

/**

* Returns true if the termite has a flower.

*/

public boolean hasFlower();

126

Chapter 10. GridWorld: Part 2

/**

* Returns true if the termite is facing a flower.

*/

public boolean seeFlower();

/**

* Creates a flower unless the termite already has one.

*/

public void createFlower();

/**

* Drops the flower in the termites current location.

*

* Note: only one Actor can occupy a grid cell, so the effect of

* dropping a flower is delayed until the termite moves.

*/

public void dropFlower();

/**

* Throws the flower into the location the termite is facing.

*

*/

public void throwFlower();

/**

* Picks up the flower the termite is facing, if there is one,

* and if the termite doesn✬t already have a flower.

*/

public void pickUpFlower();

For some methods Bug provides one definition and Termite provides another.

In that case, the Termite method overrides the Bug method.

For example, Bug.canMove returns true if there is a flower in the next loca-

tion, so Bugs can trample Flowers. Termite.canMove returns false if there

is any object in the next location, so Termite behavior is different.

As another example, Termites have a version of turn that takes an integer

number of degrees as a parameter. Finally, Termites have randomTurn, which

10.1. Termites

127

turns left or right 45 degrees at random.

Here is the code from TermiteRunner.java:

public class TermiteRunner

{

public static void main(String[] args)

{

ActorWorld world = new ActorWorld();

makeFlowers(world, 20);

Termite alice = new Termite();

world.add(alice);

Termite bob = new Termite();

bob.setColor(Color.blue);

world.add(bob);

world.show();

}

public static void makeFlowers(ActorWorld world, int n) {

for (int i=0; i<n; i++) {

world.add(new EternalFlower());

}

}

}

Everything here should be familiar. TermiteRunner creates an ActorWorld

with 20 EternalFlowers and two Termites.

An EternalFlower is a Flower that overrides act so the flowers don’t get

darker.

class EternalFlower extends Flower {

public void act() {}

}

If you run TermiteRunner.java you should see two termites moving at ran-

dom among the flowers.

128

Chapter 10. GridWorld: Part 2

MyTermite.java demonstrates the methods that interact with flowers. Here

is the class definition:

public class MyTermite extends Termite {

public void act() {

if (getGrid() == null)

return;

if (seeFlower()) {

pickUpFlower();

}

if (hasFlower()) {

dropFlower();

}

if (canMove()) {

move();

}

randomTurn();

}

}

MyTermite extends Termite and overrides act. If MyTermite sees a flower,

it picks it up. If it has a flower, it drops it.

Exercise 10.2. The purpose of this exercise is to explore the behavior of

Termites that interact with flowers.

Modify TermiteRunner.java to create MyTermites instead of Termites.

Then run it again. MyTermites should move around at random, moving the

flowers around. The total number of flowers should stay the same (including

the ones MyTermites are holding).

In Termites, Turtles and Traffic Jams, Mitchell Resnick describes a simple

model of termite behavior:

❼ If you see a flower, pick it up. Unless you already have a flower; in

that case, drop the one you have.

❼ Move forward, if you can.

10.2. Langton’s Termite

129

❼ Turn left or right at random.

Modify MyTermite.java to implement this model. What effect do you think

this change will have on the behavior of MyTermites?

Try it out. Again, the total number of flowers does not change, but over time

the flowers accumulate in a small number of piles, often just one.

This behavior is an an emergent property, which you can read about at

http: // en. wikipedia. org/ wiki/ Emergence . MyTermites follow sim-

ple rules using only small-scale information, but the result is large-scale or-

ganization.

Experiment with different rules and see what effect they have on the system.

Small changes can have unpredicable results!

10.2

Langton’s Termite

Langton’s Ant is a simple model of ant behavior that displays surprisingly

complex behavior. The Ant lives on a grid like GridWorld where each cell is

either white or black. The Ant moves according to these rules:

❼ If the Ant is on a white cell, it turns to the right, makes the cell black,

and moves forward.

❼ If the Ant is on a black cell, it turns to the left, makes the cell white,

and moves forward.

Because the rules are simple, you might expect the Ant to do something

simple like make a square or repeat a simple pattern. But starting on a grid

with all white cells, the Ant makes more than 10,000 steps in a seemingly

random pattern before it settles into a repeating loop of 104 steps.

You can read more about Langton’s Ant at http://en.wikipedia.org/

wiki/Langton_ant.

It is not easy to implement Langton’s Ant in GridWorld because we can’t

set the color of the cells. As an alternative, we can use Flowers to mark

130

Chapter 10. GridWorld: Part 2

cells, but we can’t have an Ant and a Flower in the same cell, so we can’t

implement the Ant rules exactly.

Instead we’ll create what I’ll call a LangtonTermite, which uses seeFlower

to check whether there is a flower in the next cell, pickUpFlower to pick it

up, and throwFlower to put a flower in the next cell. You might want to

read the code for these methods to be sure you know what they do.

Exercise 10.3.

1. Make a copy of Termite.java called LangtonTermite

and a copy of TermiteRunner.java called LangtonRunner.java. Mod-

ify them so the class definitions have the same name as the files, and

so LangtonRunner creates a LangtonTermite.

2. If you create a file named LangtonTermite.gif, GridWorld uses

it to represent your Termite.

You can download excellent pictures

of

insects

from

http: // www. cksinfo. com/ animals/ insects/

realisticdrawings/ index. html . To convert them to GIF format,

you can use an application like ImageMagick.

3. Modify act to implement rules similar to Langton’s Ant. Experiment

with different rules, and with both 45 and 90 degree turns. Find rules

that run the maximum number of steps before the Termite starts to

loop.

4. To give your Termite enough room, you can make the grid bigger or

switch to an UnboundedGrid.

5. Create more than one LangtonTermite and see how they interact.