The Jeroos of Santong Island

Move into basic Java programming in the context of a wildlife simulation on an exotic island.

Santong island is an uninhabited speck of land in the South Pacific Ocean. In the late 1980's, naturalist Jessica Tong discovered two previously unknown species that are unique to this island. One is the jeroo, a rare mammal similar to the wallabies of Australia. The other is the large winsum flower that is the jeroo's primary food source.

Like its distant Australian relative, the jeroo moves by hopping, but its movements are unique in all of nature. Each jeroo only moves in one of the four main compass directions, and only turns in 90 degree increments. This unusual behavior continues to mystify Jessica and the few other researchers who have observed jeroos in the wild. Some believe that this behavior is somehow related to geomagnetic forces, but others think that this is just a bizarre learned behavior.

Every jeroo has a pouch, but the male's pouch is somewhat smaller. While the female uses her pouch to protect and nuture her offspring, both sexes use their pouches to carry winsum flowers that they have picked.

During the rainy season, January through December, sudden storms can create temporary lakes and rivers, or even alter the shape of the island itself. Despite living on Santong island for uncounted millennia, the jeroos are extremely poor swimmers. While they are keenly aware of their immediate surroundings, jeroos can be careless. If one happens to hop into the ocean, its fur becomes waterlogged and it must rest in the sun for a few hours before resuming its normal activity. In what can only be described as a telepathic connection, all other jeroos also cease their activities until the wet jeroo has recovered.

Until recently, the jeroos were safe from human interference because they were only known to a handful of researchers and because Santong island is very small, very remote, and missing from most maps. The jeroo's idyllic world was interrupted in 2001, when Brian arrived at the island. Brian is a renowned collector who was hired to capture a jeroo for the extreme animal exhibit at Missouri's C. A. Baret zoo. Having studied the jeroos' unique patterns of movement, Brian periodically sets nets in the locations that a jeroo is likely to visit. Fortunately, the sensitive jeroos can detect his nets, and have learned that tossing a winsum flower onto a net will disable the net and make that location safe for future travel. Brian can only catch a careless jeroo that leaps before it looks.

After returning from a recent trip to Santong island, Jessica asked her colleague, Deanna, to develop a simulator that could be used to demonstrate the jeroos and their relationship with their island. The result of Deanna's work is a computer program written in Java to help Jessica with her research. The program provides a micro-world representation of Santong island and shows the behavior of one or more jeroos on the island. This program also works as an Android app so that Jessica can take it with her into the field easily.

When Deanna designed the simulator, she used the jeroo's unique movements to model the island as a grid, where the x-axis runs from West to East along lines of lattitude, and the y-axis runs from North to South along lines of longitude. Each element (cell) of this model corresponds to a location where a jeroo might land when it hops.

Deanna chose to number both the x-coordinates and y-coordinates by starting with zero at the northwest corner of the map containing the island (her maps included the water immediately surrounding the island). When asked why she started at zero, Deanna said that she was counting the number of safe hops from any location to the northwest corner. We will use the notation (x, y) to indicate a specific cell, where x represents the horizontal position of the cell and y represents the vertical position of the cell.

Two of the Java classes in Deanna's simulation are Island and Jeroo. The Island class is a world subclass that represents the island map, while the Jeroo class is an actor subclass. There are also Flower, Net and Water classes to represent other objects on the island.

There as seven action methods that a Jeroo understands (three of them require an argument value):

MethodPurposeExample
hop()Hop one space ahead. The program terminates with a logic error if the hopping Jeroo lands in the water, lands on another Jeroo, or hops onto a net. A Jeroo can hop onto a flower. jessica.hop();
hop(number)Hop number times in a row, where number is a positive integer. jessica.hop(3);
jessica.hop(12);
pick()Pick a flower from the current location. Nothing happens if there is no flower at the current location.jessica.pick();
plant()Plant a flower at the current location. Nothing happens if the jeroo does not have a flower to plant.jessica.plant();
toss()Toss a flower one space ahead. The tossed flower is lost forever. If the flower lands on a net, the net is disabled. jessica.toss();
turn(relativeDirection)Turn in the indicated direction [ turn(AHEAD) and turn(HERE) are meaningless ] jessica.turn(LEFT);
jessica.turn(RIGHT);
give(relativeDirection)Give a flower to a neighboring Jeroo in the indicated direction. Nothing happens if the giving Jeroo has no flowers, or if there is no neighboring Jeroo in the indicated direction. [ give(HERE) is meaningless ] jessica.give(LEFT);
jessica.give(RIGHT);
jessica.give(AHEAD);

Direction

Each Jeroo knows four relative directions and four compass directions as shown in the following table. Each direction must be written in UPPER CASE (In Java, constant values that never change are usually written this way). The relative direction HERE refers to the Jeroo's current location, so it isn't useful with the action methods in the previous section (we'll see other methods later where HERE makes sense).

Relative DirectionsCompass Directions
LEFTNORTH
RIGHTEAST
AHEADSOUTH
HEREWEST

Attributes

When designing an object to represent something, we must select facts about that thing that are relevant to the problem we are trying to solve. For example, the title of a book would be important to a bookstore, but not to the company that shipped the book from the publisher's warehouse. On the other hand, the weight of the book would be important to the shipper, but not to the bookstore. Facts such as the title or weight of a book are called attributes.

An attribute is a fact associated with a specific object.

The attributes of a Jeroo object include its location, the number of flowers in its pouch, and the direction it's facing. When we instantiate a class, the class' constructor is responsible for initializing the new object's attributes. So when we create a Jeroo object, its constructor is responsible for initializing its location, the number of flowers in its pouch, and the direction it's facing. If we do not specify a value for one (or more) of the attributes when we create the jeroo, the constructor provides defaults for us.

As a convenience, the Jeroo class provides multiple constructors so that we can omit (or provide) values we want for any of these attributes. All but one of the constructors allow us to provide values for just some of the attributes. The constructors are summarized in the following table:

ExampleAttributes
// Accept all defaults
Jeroo jessica = new Jeroo();
Location:(0, 0)
Direction:EAST
Flowers:0
// Specify just the flowers
Jeroo jessica = new Jeroo(8);
Location:(0, 0)
Direction:EAST
Flowers:8
// Specify just the location
Jeroo jessica = new Jeroo(3, 4);
Location:(3, 4)
Direction:EAST
Flowers:0
// Specify location and direction
Jeroo jessica = new Jeroo(3, 4, WEST);
Location:(3, 4)
Direction:WEST
Flowers:0
// Specify location and flowers
Jeroo jessica = new Jeroo(3, 4, 8);
Location:(3, 4)
Direction:EAST
Flowers:8
// Specify all attributes
Jeroo jessica = new Jeroo(3, 4, WEST, 8);
Location:(3, 4)
Direction:WEST
Flowers:8

The equal sign between the declaration and instantiation portions indicates that the newly created Jeroo object is to be associated with the identifier in the declaration portion.

An instance of the Island class is pretty plain:

An instance of the Island class.

This island is completely bare, with no jeroos, no flowers, and a pretty basic shape. But to change the behavior of a library class, we need to create our own version of the class. We do this by defining a subclass. A subclass inherits all the features of the class it is based on. That means it understands all of the methods of the original class, and may add more of its own. We create a subclass using this basic pattern:

public class NewClassName extends ExistingClassName
{
    ...
}

The keywords public class indicate that we are introducing a brand new class that can be used anywhere in our code (i.e., it is "public"ly available for use elsewhere). The NewClassName is the name of the new class we are defining, and the ExistingClassName is the name of the class we want to build on. The keyword extends is what indicates that our new class is a subclass. Whenever you use extends, you are saying that the class you are declaring inherits all the features from another existing class.

A subclass is a class that inherits all the methods and attributes of another class, called its superclass.
The termsderived class and child class are different names for subclass.
The termsbase class and parent class are different names for superclass.

In Greenfoot4Sofia, we can create a new subclass from the Island class by right-clicking on Island and choosing the "New subclass..." action:

Create a new subclass by right-clicking on an existing class and choosing 'New subclass...'.

In the resulting new subclass dialog, enter the name for your new subclass (you already indicated what the superclass was when you right-clicked). Greenfoot4Sofia will create a new class and an associated source file for you, and fill it with the required starting content (including some comments and placeholders).

In Java, the source code for a given class is stored in a plain text file that has the same name as the class with ".java" added on the end. The file name must be capitalized exactly the same way as the class name.

When you create a new subclass in Greenfoot4Sofia, the generated class will already have a constructor. a constructor is a special kind of method that is used only to initialize a brand new object.

A constructor is a special kind of method that is used to initialize a brand new object.

In the constructor for our island subclass, you can put any actions you would like to perform when the island is created--such as populating it with some flowers, or placing water in new locations.

We can also say what we wish to happen when the Run button is pressed by added a myProgram() method. You can add this to your island subclass:

public void myProgram()
{
    Jeroo jessica = new Jeroo(3, 4, 8);
    this.add(jessica);

    //  Give instructions to your jeroo to carry out here
}

Any actions you place in myProgram() will be executed when the Run (or the Act) button is pressed.

Exercise 1

Create an Island subclass and add the myProgram() method sketched above to it. Replace the comment in myProgram() with instructions to have the jeroo jessica plant a row of three flowers from (3, 4) to (5, 4).

In addition to creating subclasses of Island to provide different maps, we can also create our own subclass(es) of Jeroo. If you create a subclass of Jeroo, you can add new methods to it so that your personal jeroo understands a larger vocabulary of actions. You can then use these new methods to solve problems.

As an example, suppose we wanted our jeroo to know how to hop and plant flowers at the same time--that is, each time it takes a hop forward, it also plants a flower (if it has one). We can do this by adding a hopAndPlant() method of our own. But to add a method, we need to a class of our own to write it in.

Exercise 2

Create a Jeroo subclass with the name of your choice (remember to capitalize the first letter of the name). Write a method called hopAndPlant() that hops one square and then plants a flower.