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):
Method | Purpose | Example |
---|---|---|
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); |
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 Directions | Compass Directions |
---|---|
LEFT | NORTH |
RIGHT | EAST |
AHEAD | SOUTH |
HERE | WEST |
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.
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:
Example | Attributes | ||||||
---|---|---|---|---|---|---|---|
// Accept all defaults Jeroo jessica = new Jeroo(); |
| ||||||
// Specify just the flowers Jeroo jessica = new Jeroo(8); |
| ||||||
// Specify just the location Jeroo jessica = new Jeroo(3, 4); |
| ||||||
// Specify location and direction Jeroo jessica = new Jeroo(3, 4, WEST); |
| ||||||
// Specify location and flowers Jeroo jessica = new Jeroo(3, 4, 8); |
| ||||||
// Specify all attributes Jeroo jessica = new Jeroo(3, 4, WEST, 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:
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.
In Greenfoot4Sofia, we can create a new subclass from the
Island
class by right-clicking on Island
and choosing the "New subclass..." action:
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).
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.
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.
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.
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.