You may work with a partner on this assignment.
Run update21, to create the cs21/labs/11
directory. This week's lab depends on last week's lab. If you are
still having issues with your Grid and Cell classes,
you'll need to correct them first. Once your previous lab is working
correctly, copy your grid.py solution from your
labs/10 directory into your labs/11 directory. You
will add the new code for this week's lab to the file called
gameoflife.py.
Read through this entire lab description before you begin coding
your solution. Then go to the section on getting started and
follow the directions given there to begin.
Introduction
For this assignment, you will implement a class called
GameOfLife that can be used to play John Conway's Game of
Life. The GameOfLife class will use the Grid
and Cell classes you wrote for the previous lab.
The Game of Life simulates the evolution of a cellular automata in
a two dimensional grid world. During the simulation, a cell either
lives or dies based on its state and the state of its neighbors. The
neighbors of a cell are the eight cells that directly surround it. If
a cell is on the edge of the grid, it will only have five neighboring
cells. If a cell is in the corner of the grid, it will only have
three neighboring cells. To play the game of life first, an initial
configuration of the grid's cells are set. Then, at each time step, a
cell's state changes according to the following rules:
- For a cell that is 'alive':
- if it has only one or no live neighbors, it dies from loneliness
- if it has four or more live neighbors, it dies due to overpopulation
- if it has two or three live neighbors, it stays alive
- For a cell that is 'dead':
- if exactly three of its neighbors are alive, it comes alive
Requirements
- You must implement a GameOfLife class that has a
Grid data member. You may add additional data members as you
like.
- Your GameOfLife class should have at least these methods
(you may add more if you'd like):
- __init__: the constructor takes the desired width and
height of the grid as parameters and creates the Grid object data
member.
- close: will invoke the grid's close method that will
wait for a mouse click and then close the graphics window.
- startWalkerGame: creates a starting point world of the
walker pattern in the lower left corner (see the sample output section
for what this pattern should look like). The walker pattern should
cause a set of live cells to move diagonally toward the upper right
corner of the screen.
- startExpanderGame: creates a starting point world of the
expander pattern such that it is drawn centered in the grid (see
the sample output section for what this pattern should look like). The
expander game should cause the initial pattern to expand outward and
then end with four stable structures on the grid.
- startToggleGame: a starting point world that the user
can specify by toggling cells in the grid using the mouse.
Use cell[0][0] as the special "stop clicking" cell.
- playGame: takes the number of steps to simulate as a
parameter, and plays the game of life using the rules given above on
the current world state for that many steps. Use the sleep
function from the time library to delay 0.2 seconds between
each step.
- The final version of your main program should prompt the user
to enter the width and height of the grid, create a
GameOfLife object of the given dimensions. For each of the
game starting points (walker, expander and toggle) in turn your
program should:
- call the appropriate start method to initialize the world for
that game
- prompt the user to enter the number of time steps to simulate the
game
- play the game of life
- clear the grid prior to starting the next game
You should follow the directions in the next section to implement and
test your program incrementally.
Getting Started
- At the bottom of your grid.py file, add the following line
before your call to the main program:
if __name__ == '__main__':
main()
This ensures that when you import this file into another program that
the main program inside this file will not be called.
- At the top of your gameoflife.py file, import the classes
and functions that you'll need:
from grid import *
from time import sleep
- Create the GameOfLife class incrementally. First
implement the __init__, close and playGame
methods.
- Next test that you've implemented the rules correctly. One way
to test for correctness is to try a pattern that repeats in a well
known way. For example, if you initialize three cells in a column to
be alive, then in the next time step the live cells will flip to be
three cells in a row with the same middle cell. This pattern repeats
forever (alternating between three cells in a row and three cells in a
column). Here is a pattern on a 5 by 5 grid based on this:
- Once the above test pattern successfully flips between a
vertical and a horizontal line, you can implement each of the games,
testing after adding each one.
Sample output
In the sample output given below, only the initial starting
conditions of each game are shown.
$ python gameoflife.py
This program plays Conway's Game of Life
Enter width of the grid: 21
Enter height of the grid: 21
Try the walker game.
Enter the number of steps: 50
Try the expander game.
Enter the number of steps: 20
Try the toggle game.
Enter the number of steps: 30
In this game create your own starting point by clicking
on cells to make them alive. Clicking on the cell in
the lower left corner (0,0) will start the game.
Click one last time to end the Game of Life.
Optional Extensions
Do not try these extensions until you have the basic assignment
implemented, tested, and working correctly.
Add other starting point methods that initialize the world to
different configurations. There are many that will lead to
interesting patterns that repeat forever or that converge to a static
pattern. Look online for some examples.
Submit
Once you are satisfied with your program, hand it in by typing
handin21 in a terminal window.