Overview · Rules · Files · Tasks · Simulation · Exploration · Testing · Report Format · Checklist
In Project 2 you will build Conway's Game of Life, a cellular automaton in which
a grid of cells changes from one generation to the next according to a small set
of rules. Each Cell is either alive or dead. A Landscape
stores a two-dimensional grid of Cells, and the state of each Cell in the next
generation depends on the Cells surrounding it.
int[][], your model will contain a
Cell[][].
The supplied LandscapeDisplay class provides the graphical window.
Your primary job is not to write graphics code. Your job is to build and update
the model correctly so that the display has the correct information to draw.
Cell ↓ Cell[][] inside Landscape ↓ neighbor relationships ↓ Game of Life rules ↓ next generation ↓ LandscapeDisplay
A Cell's next state depends on the number of its living neighbors. A Cell can have as many as eight neighbors: above, below, left, right, and the four diagonals. Cells on the boundary of the Landscape have fewer neighbors.
Every Cell's next state must be determined from the same current generation.
Imagine that you are processing the Landscape from left to right. If you calculate
the next state of the first Cell and immediately change it in the original Landscape,
then the next Cell may see that new state when it calls
getNeighbors(). It would be making its decision using a mixture of the
current generation and the next generation.
Instead, think of the update as having two separate grids:
CURRENT GENERATION NEXT GENERATION
(the grid you read) (the grid you build)
X ? ? ?
XXX ----> ? ? ?
? ? ?
For every location:
Only after you have calculated the next state of every Cell should the new grid replace the old one.
current generation
↓
calculate every Cell's next state
↓
build complete next generation
↓
replace the old generation
This guarantees that every Cell follows Conway's rules using exactly the same generation of neighbors. Think of the two arrays as the grid you read and the grid you build.
Internally, each Cell stores its state as a boolean: true means alive and
false means dead. Cell.toString() represents those states as
"1" and "0". When displaying an entire Landscape as text,
Landscape.toString() uses X for a living Cell and a blank space
for a dead Cell so that patterns are easier to see.
You should already have a Project2 folder in the
Projects folder of your personal Google Drive from Lab 2.
Your completed Grid.java should already be there. Download the
Project 2 files below into that same Project2 folder.
A Cell represents one location in the Game of Life. It stores one
piece of state: whether that Cell is currently alive.
Cell() constructs a dead Cell.Cell(boolean status) constructs a Cell with the supplied state.getAlive() returns whether the Cell is alive.setAlive(boolean status) changes the Cell's state.toString() returns "1" for a living Cell and "0" for a dead Cell.
Before running the tester, create several Cells in a main() method,
change their states, and print them. Make sure the behavior makes sense to you.
Then compile and run CellTester for the Cell basics.
A Landscape is the model for the simulation. Its central data
structure is a two-dimensional array of Cell references:
Cell[][] landscape
Complete the Landscape construction and access methods:
Landscape(int rows, int columns) creates a Landscape containing dead Cells.Landscape(int rows, int columns, double chance) creates a Landscape in which each Cell independently begins alive with probability chance.Landscape(boolean[][] grid) creates Cells whose initial states match a supplied boolean grid.reset() recreates the Landscape using the initial probability supplied when it was constructed.getRows() returns the number of rows.getCols() returns the number of columns.getCell(int row, int col) returns the Cell at the requested location.toString() returns a text representation of the Landscape, using X for living Cells and a space for dead Cells, with a newline after each row.boolean[][] lets you create
an exact starting configuration and know what should happen next.
Use main() to create small Landscapes such as 2×3 and 3×3 grids.
Print their dimensions, inspect individual Cells, and print the whole Landscape
before running LandscapeTester.
Complete getNeighbors(int row, int col). It returns an
ArrayList<Cell> containing references to all valid neighboring
Cells around the requested location. Use Java's built-in
java.util.ArrayList for this method.
For a location at (row, col), the possible surrounding locations are:
(row-1,col-1) (row-1,col) (row-1,col+1) (row, col-1) [row,col] (row, col+1) (row+1,col-1) (row+1,col) (row+1,col+1)
(row, col) itself.
Experiment with a small 3×3 Landscape. Check the neighbor list for a corner,
an edge, and the center. Then run the neighbor portion of
LandscapeTester.
Return to Cell.java and complete
updateState(ArrayList<Cell> neighbors). This method receives
the neighboring Cells from the current generation and changes this Cell's
alive/dead state according to the Game of Life rules.
neighbors are alive.
Test examples yourself: a living Cell with two living neighbors should survive;
a living Cell with four should die; a dead Cell with three should become alive.
Then run CellTester again and complete the state-rule tests.
Complete Landscape.advance(). This is where the Cell rules and
the 2D Landscape come together.
A useful design is:
Cell[][] with the same dimensions as the current Landscape.Cell based on the current state of the original Cell.The important rule is: read from the old generation while building the new generation. Do not change the old generation as you go.
Use a known pattern created with Landscape(boolean[][] grid) to
predict the next generation yourself. Then run the advance()
portion of LandscapeTester.
LandscapeDisplay.java is provided. Read through it, but you are
not expected to implement the Swing window machinery. The display stores a
Landscape and asks the Landscape to draw itself.
MODEL VIEW Landscape LandscapeDisplay Cell[][] landscape ----> graphical window
The draw(Graphics g, int scale) method is already provided in
Landscape.java. Once your model works, run
LandscapeDisplay and confirm that the graphical view agrees with
the states stored in your Landscape.
Then create LifeSimulation.java. Model its setup on
LandscapeDisplay.main(). Your simulation should create a Landscape
and LandscapeDisplay and repeatedly:
Thread.sleep(...),advance(), andrepaint() on the display.Start small. First display only the initial board. Then advance exactly one generation and stop. Compare the result with what you expected before running a long animation.
Once that works, use command-line arguments to make useful simulation settings easy to change, such as grid dimensions, initial chance, or number of generations.
After your simulation is working, use it to investigate how the initial conditions affect the long-term behavior of the Game of Life.
Investigate the relationship between initial probability of living Cells and the number of living Cells remaining after many generations. Develop a hypothesis, design an experiment, and gather enough data to evaluate your hypothesis.
The previous version of this project used 1000 generations as a useful long-run observation point and suggested testing initial probabilities across the range from 0 to 1. You may use that structure for your experiment. Run enough trials that your conclusions are supported by evidence rather than by one random run.
The provided testers are designed to help you make incremental progress. Work
through the project in order. Before using a tester, experiment with the method
yourself in main() using small inputs whose behavior you can predict.
javac *.java java CellTester java LandscapeTester
The graphical display is also useful evidence, but a picture that looks reasonable is not proof that the underlying algorithm is correct. Use both predictable small tests and the visualization.
Your intended audience is your peers who are not in this class but who have taken a computer science course. Your reader should be able to understand what you built, the important computer science ideas behind it, what experiment you performed, and what your results mean without having completed this assignment themselves.
Your project report should contain the following sections. Please include a header for each section.
Briefly summarize the project in your own words. Identify both the core computer science ideas and the application: a 2D array of objects, neighbor relationships, simultaneous state updates, and their use in Conway's Game of Life.
Explain why a 2D array is an appropriate structure for this problem and briefly identify the experiment you performed. Detailed results belong in the Results section.
Present evidence that your simulation is working and the evidence from your exploration. Include an image of a Landscape's initial state and an image of the following state after one update. Explain why the change is consistent with the Game of Life rules.
Then present the results of your experiment on initial conditions and long-term behavior. Organize numerical results clearly; a table or graph will often be more useful than a large block of raw output.
Your discussion should address questions such as:
Describe any work you completed beyond the required project. Focus on the design and behavior of the extension: what capability you added, what classes or methods changed, how the new logic works, and how you determined that it worked.
Useful extensions might involve new starting patterns, additional visualization, alternative rules, improved simulation controls, or additional experiments. If you did not complete an extension, simply state that no extension was completed.
List the people and outside resources that contributed to your work. Include people you worked with or received help from, including TAs and instructors, and acknowledge outside references that helped you understand an algorithm, library, or programming technique.
Grid.java from Lab 2 remains in the Project2 folder.Cell.java, Landscape.java, LandscapeDisplay.java, and LifeSimulation.java compile together.CellTester and LandscapeTester and reviewed any Expected/Generated differences.Extension1, Extension2, and so on. Each extension folder must contain ALL files necessary to compile and run that extension; do not rely on files located elsewhere in your Project2 folder.