BSE August 2014, Computer Science

The Game of Life (II) 

In this second part of the BSE computer science experience you will do the evolution process that you did yesterday by hand automatically with a computer.  You will express the computation of the next generation as a computation or an algorithm,  and (with help) you will translate it into Java. To see whether your thinking is right, you will simply let the computer run your code and see if it does what you expect it to do. 

The beginning

Log onto a machine in the lab using your  Bowdoin login and password.    I will come and help you download the  files that you'll need for this lab and open BlueJ, the software that you'll use to edit the files, compile them in Java and run them. 

You will need 3 files: CellGrid, LifeGUI, and GameOfLife.   The file to run is LifeGui.  When  you want to check what your  code is doing, first compile in BlueJ, then run the method called main() in LIfeGui. 

First, get familiar with BlueJ and with compiling and running. I'll come and help you individually.  The only file that you'll modify is GameOfLife.  This is where the core of the game takes place. The other files handle drawing the grid on the screen. 

Scroll  to the end of the file GameOfLife and look for the methods at the end where you see "FILL IN YOUR CODE".   Here is where you'll write your computation. 

Try compiling the code. The code should compile successfully as is.  To run,  run the method called main() in LIfeGui.  Check what the code is doing. Try to set various patterns on the screen, and see how they evolve by pressing either Next or Start.  What happens?  Try pressing the various seeds under Clear, and then Next or Start. What happens? 

You'll discover that none of the seeds work, and also Next and Start do not work. This is because the code that is telling the computer what to do is missing ---- this is your task for today!

The seeds

The first method that you'll fill in is called blinker. You'll see this: 

 // sets the grid to the blinker pattern
    public void blinker() {

	/* you first need to clear the grid by calling clear(), then
	 * you need to set some indivuduals in the grid as LIVE. The
	 * individuals that you set LIVE need to form a blinker.
	 * You can locate the blinker anywhere you want in the
	 * grid */

	// FILL IN 

    }

How do you set the grid to a blinker?  You probably want to start by clearing the grid, that is, by setting all cells (individuals) in the grid as DEAD.  To do that, you'll write: 

clear();

This calls a routine that clears the grid. Note that every instruction in Java has to be finished with a semicolon. If you forget it, the compiler will complain. 

Once the grid is clear, you want to set some individuals alive.   Think of the grid as consisting of row and columns. The top most row is row number 0.  The left most column is column number 0.  The name of an individual in row i and column number j  is grid[i][j], and we'll refer to it as the cell (individual) at location (i,j).   The neighbor above a cell at location (i,j) is (i-1),j)--- that is, it is at the same column j,  but one row above. 

For example:

grid[0][0] = LIVE; 
grid[1][0] = LIVE; 
grid[2][0] = LIVE; 

This code would place the blinker in the very top left corner.  You  want to change it to place it somewhere a bit further from the edge. 

After you write the code for the blinker, compile your code, and then run it using BlueJ.  Test it. 

Once your blinker works, continue with the other seeds:  block, toad, beehive, beacon,  acorn,  ggGun and fpentomino.  The file is clearly marked where you need to fill in your  code. 

Computing the next generation

Now that all the seeds are done, you'll write code to compute the next generation in the grid.  This is the last function  that needs to be filled in for the program to work.  Once  this function is complete, the Next and Start buttons will work as expected; or better said, they will do exactly what you tell them to do in your code. 

Remember the process you went through yesterday to compute the next  generation based on the current one. You want to write down a set of detailed instructions  so that the computer is able to do the same thing that you did. 

What are the basic steps that you did?  

1. you need to set an individual in the next generation to be   live or dead based on the rules. 
2.  you need to do this for each individual in the grid 

We'll take each of these, in turn.  

Setting a cell in nextGrid based on the rules

To set a cell at location (i,j) to be alive, use 

nextGrid[i][j]=LIVE;

To set a cell at location (i,j) to be dead, use 

nextGrid[i][j]=DEAD;

The question is, how do you know  whether to set a cell  to live or dead?  You need to apply the rules. The next state of a cell depends on two things: whether the cell is live for dead, and how many live neighbors it has. 

To count the number of neighbors  of a cell at location (i,j),  use the method numLiveNeighbors(i,j).  For example, you could say something like this: 

if (grid[i][j] == LIVE && numLiveNeighbors(i,j) == 2) {
  
	nextGrid[i][j] = LIVE;	
} ; 

Ignoring all the parenthesis and curly brackets, which are just a matter of Java syntax,   what this does is essentially the following:  if the grid cell  at position (i,j) is alive and if the number of live neighbors of the cell at position (i,j) is equal to 2, then  it sets the  cell (i,j) in the next grid to be alive.  This is one of the rules of the game. 

Can  you come up with a set of similar instructions that take care of all the cases , for a cell (i,j)? 

Repeating this for every cell in the next grid 

Now, you need to do this for every single cell  in the grid.   So far we talked about a cell at position (i,j).  Think of i and j as variables,  which can take any values:  i is the row number, so it starts at 0 and it goes up to the size of the grid; and j is the column number,  so it starts at 0 and goes to the size of the grid. 

Whatever the set of instructions you were doing  above for cell (i,), you'll need to  repeat them for every single cell (i,j) in the grid. 

To loop to every single cell in the grid, you will do something like this: 

	for (int i = 0; i < GAME_SIZE; i++){
	    for (int j = 0; j < GAME_SIZE; j++) {

		 set of instructions

	    }
	}

What this does is the following:  i takes all values from 0 to  the size of the grid, and j takes all values from 0 to the size of the grid, and for every such pair, the set of instructions is executed.  In other words, if you replace the set of instructions with the instructions that you wrote above  to apply the rules for a cell (i,j),  then you are done!