Due: 2:00pm, Monday, October 19. Value: 30 pts. Submit to Sauron.
We'll work with simulating the growth of mushrooms on a field of grass. We'll imagine a the field as a grid of squares, in which some mushroom spores have randomly dropped. Each grid square can potentially hold a mushroom, and each square potentially goes through the following cycle.
Except for a few random squares that start with spores, each grid square starts out empty. The empty square becomes a spore with a 50% probability if one or more of its four neighbors are mature. Once it becomes a spore, it remains a spore with 20% probability in each following cycle, until it becomes mature. It spends one simulation cycle in the mature state, then dies in the next cycle, then decays. Finally, after one cycle of decay, the grid square reverts back to its empty state.
The following illustrates the first three steps of one simulation.
![]() |
Initial state: All squares are empty except for a few random squares with spores. The black border squares are walls; they do not change over time. |
![]() |
The user clicks the mouse to advance the simulaion by one time step. In this case, some of the spores will mature into mushrooms. |
![]() |
After two steps: Some grid squares become spores due to a mushroom in an adjacent square. The mushrooms die, while some spores from the previous step mature into mushrooms. |
Represent the state of each grid square with the colors
shown in the above diagram: green, pink, red, light gray,
dark gray. The boundaries of the grid, where mushrooms can never
grow, are represented with black squares. In your program, you
can use each GObject's getColor method to
determine a square's state, and you can use its setColor
method to alter its state.
To determine whether a neighbor is mature,
you can use the getElementAt method to retrieve the
neighboring GObject, on which you would invoke the
getColor method to see whether it is mature.
GObject getElementAt(double x, double y)Returns the topmost object that contains the specified
coordinates. If no such object exists (which due to the black
squares probably won't come up), the method returns
null.
I've written starting code,
which sets up the initial grid and random spores. You should not
modify the run method. (To download, right-click
SimMushroom.java, select Save
Link As…
or Save Target As…
from the pop-up
menu, and save the file on your computer. Then select Open…
from Jigsaw's File menu and open the file you just saved.)
The most obvious approach is to have a loop for each time step, which goes through all grid squares and computes that square's new color for the next time step. But this approach is flawed: With such an implementation, a square that was pink at the time step's beginning could become mature (red); and then later in the same time step, when the computer reaches an empty square just below the now-mature square, that square may then gain a spore. But that's wrong, because the square above was really still a spore at the simulated time step's beginning.
The solution is to use a two-phase process. In the first phase,
you go through all squares to find the empty squares that gain
a spore, and you'd temporarily mark
them as ones that
ought to change to pink. A good way of marking a square is to color
it blue. And in the second step, you go through all
squares again, coloring the marked (blue) squares pink, deciding whether to
color the pink squares red, and so on.
The program I distribute has already structured things this
way, with a performSporePhase method for performing
the first phase and a performAdvancePhase for the
second.
This assignment specifies that an empty square becomes a spore with 50% probability whether it has one, two, three, or four mature neighbors. A common misinterpretation is that a mature neighbor drops a spore on each of its empty neighbors with 50% probability. This is not the same: With the latter misinterpretation, an empty square would gain a spore with more than 50% probability if it has multiple mature neighbors.
Although the program is written for a 15×15 grid of
10×10 squares, your program should work regardless of the
grid and square dimensions. That
is, you should be able to modify the gridSize and
squareSize parameters to, say, 60 and 5, and the
program will correctly simulate a larger 60×60 field.