University of Virginia, Department of Computer Science
CS201J: Engineering Software, Fall 2002

Problem Set 1: Game of Life Out: 29 August 2002
Due: Tuesday 3 September, beginning of class

Collaboration Policy - Read Carefully

For this problem set, you are encouraged to work with one other student but permitted to work alone if you prefer. If you do work with another student, your partner must be someone who took a different computer science course then you last year (that is, if you took CS101 your partner should have taken CS200 and vice versa). If you work with a partner, you and your partner should turn in one assignment with both of your names on it.

Regardless of whether you work alone or with a partner, you are encouraged to discuss this assignment with other students in the class and ask and provide help in useful ways. You may consult any outside resources you wish including books, papers, web sites and people. If you use resources other than the class materials, indicate what you used along with your answer.

Purpose

Background

Cellular automata are computer simulations inspired by biological cells. An automata simulation starts with a grid of cells, where each cell is initialized to a particular state. At each step in a simulation, the next state of each cell is determined based on simple rules that depend on its current state and the current states of its neighbors.

Despite their simplicity, cellular automata can produce complex and interesting patterns. We have provided you with code that implements a cellular automata simulator. You are encouraged to look over the code, but you do not need to understand this code now and should not be concerned if it doesn't all make sense yet as it uses concepts that we will not encounter until later in the course.

The cellular automata simulator takes a Java class that defines the rules for each step, and simulates a grid of cells. Each cell can be in one of two states: dead or alive. A dead cell is shown as a white square and a live cell is shown as a green square. Each cell has neighbors which are the eight cells that surround it.

The file ExtremeLifeCell.java defines an example cell class that implements the game of Extreme Life — in each step any cell with at least one alive neighbor will become alive. So, if we start with one live cell, after one step every sell touching it will be alive. This will continue until the entir grid is full of live cells.

Running Extreme Life

Downloads: You will need to download this file to your machine: life.zip

Create a cs201j sub-directory in your home directory, and a ps1 subdirectory in that directory. Unzip life.zip in that subdirectory by executing unzip life.zip in a command shell.

Compile the Java source files. You can get a command line by selecting "Run" from the "Start" menu and entering cmd for the program. At the command line, type:

javac CellAutomata.java
javac ExtremeLifeCell.java
Now start the cellular automata simulator, telling it to use the ExtremeLifeCell class to model each cell, by typing:
java CellAutomata ExtremeLifeCell
Then run the Java virtual machine, which starts by calling the main method of the CellAutomata class. The second command line argument is passed as a parameter to the main, which loads the ExtremeLifeCell class and initializes the grid to contain an ExtremeLifeCell object in each square.

When the simulator starts, click on a cell and wait for it to turn green. Then press start and observe how the game operates by the extreme life rules.

The Cellular Automata Simulator

The implementation of this cellular automata contains modules for providing the graphical user interface, maintaining a grid of cells, and implementing the rules for a given cell. Here we provide a description of some of the most important classes, but you do not need to understand the details of how these classes are implemented.

CellAutomata.java

This is the main class for the implementation of the cellular automata. It sets up the user interface using Swing. It can load any cellular automata cell class of your choosing and runs a thread that calls the cells every so often to update their state. To load a specific cell class, you will need to tell the code the name of the cell class you would like to run. You specify the cell class at the command line when starting the Java interpreter, like this:

java CellAutomata ExtremeLifeCell

Replace ExtremeLifeCell with the name of your cell class. Note that the .class extension should not be included.

Grid.java

This class keeps track of all the states of the cells on the board. The Grid class has an instance variable cells that is a two dimensional array for keeping track of the cells:

public class Grid {
    // OVERVIEW: A Grid is a 2-dimensional array of cells.
    Cell [][] cells;
    ...
}
The most important method of the Grid class is step which excutes one step in the simulation:
   void step ()
      // MODIFIES: this
      // EFFECTS: Executes one step for each cell in the grid.  Each cell first caluclates its next
      //    state based on the current state of itself and its neighbors.  Then, all cells advance
      //    to their next state.
    {
        CellState [][] nextStates = new CellState [rows][columns];
        
        // Because we need to update all cells synchronously, we first calculate the next state
        // for each cell, and store it in a temporary array.  Then, we update all the cells.

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                nextStates [i][j] = getCellAt (i, j).getNextState ();
            }
        }

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                if (getCellAt (i, j).setState (nextStates[i][j])) {
                    // Tells Swing that the data in a specific
                    // cell has changed.
                    table.fireTableCellUpdated (i, j);
                }
            }
        }
    }

CellState.java

This class implements a datatype for recording the state of a cell. It includes these methods:

   public class CellState
   {
      // OVERVIEW: A CellState is an immutable object that represents
      //           the state of a cell, either alive or dead.

      static public CellState createAlive()
       // EFFECTS: Returns an alive cell state. 
    
    static public CellState createDead ()
       // EFFECTS: Returns a dead cell state. 

    public boolean isAlive ()
       // EFFECTS: Returns true iff this is alive.
   }
The methods with static modifies are class methods. They are not invoked on an object (there is no this). Instead, call them with CellState.createAlive ().

Cell.java

This class provides a basic Cell implementation. It includes these methods:
    public boolean setState (CellState s) 
       // MODIFIES: this 
       // EFFECTS: Sets the cell's current state to s.  Returns true iff the new
       //    state is different from the current state.
       
   CellState getState ()
       // EFFECTS: Returns the cell's current state.

   boolean isAlive ()
       // EFFECTS: Returns true if the cell is alive, false otherwise.

   int countAliveNeighbors ()
       // EFFECTS: Returns a count of the cell's live neighbors.

   public CellState getNextState()
       // EFFECTS: Returns next state value for this.
       //    For the underlying Cell class, the next state is always the
       //    current state.
To produce cellular automata with interesting behavior, you will produce a subtype of the Cell class and override the getNextState method to do something more interesting.

ExtremeLifeCell.java

This class implements a cell that follows the Extreme Game of Life rules described above. We use extends Cell to indicate that the ExtremeLifeCell class is a subtype of Cell. This means it inherits the non-private methods from the Cell class. To implement a new cell behavior, we need to provide a new implementation of the getNextState method:
public class ExtremeLifeCell extends Cell 
{
    public CellState getNextState ()
       // EFFECTS: Returns the next state for this cell.
       //          The next state will be alive if this cell or any of its neighbors
       //          is currently alive.
    {
        if (countAliveNeighbors () > 0) { 
            // If the cell has at least one neighboring cell
            // that is alive, this cell should become alive.
            return CellState.createAlive (); 
        } else { 
            // Otherwise, the cell maintains its previous state.
            return getState ();
        }
    }
}

Conway's Game of Life

John Conway, a Cambridge mathemetician, invented the game of life with these simple rules:

Problem 1: Using the ExtremeLifeCell.java code as an example, produce a ConwayLifeCell.java file containing a class that implements the Conway's Game of Life cellular automaton. You will need to provide an implementation of the getNextState method that implements the Conway's Game of Life rules.

With these simple rules, it is possible to produce many interesting patters. For example, if you start with three cells in a row it should produce a blinker that alternates between three horizontal and three vertical live cells. Experiment with different initial conditions to see what happens.

Turn-in Checklist: Turn in your ConwayLifeCell.java code.


Related links:

Credits: This problem set was developed for UVA CS 201J Fall 2002 by Mike Peck, Tiffany Nichols and David Evans.


CS201J University of Virginia
Department of Computer Science
CS 201J: Engineering Software
Sponsored by the
National Science Foundation
cs201j-staff@cs.virginia.edu