You may work with a partner on this assignment
Run update21, if you haven't already, to create the
cs21/labs/12 directory. Then cd into your cs21/labs/12
directory and create the python programs for lab 12 in this directory
(handin21 looks for your lab 12 assignments in your cs21/labs/12 directory):
$ update21
$ cd cs21/labs/12
$ ls
grid.pyc
$ vim gameoflife.py
With update21 you received a file, grid.pyc, that is our solution to
lab 11. You may use our solution if you did not completely solve lab 11.
If you did solve lab 11, it is likely better to use your own solution to
it. Copy your grid.py solution from your labs/11 directory into your
labs/12 directory and remove our grid.pyc file:
$ rm grid.pyc
$ cp ../11/grid.py .
$ ls
gameoflife.py grid.py
Introduction
For this assignment, you will implement a class, 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 lab 11.
The Game of Life simulates evolution of a cellular automata in a 2-D world.
At each time step in the simulation, a cells either lives or dies based
on its state and the state of its neighbors.
In this game after an initial configuration of the world'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' or 'populated':
- 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 lives
- For a cell that is 'dead' or 'unpopulated'
- if three of its neighbors are alive, it becomes populated
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__(row, cols): will create a new GameOfLife object and create
its Grid object data member with the passed number of rows and cols.
- close(): will invoke the Grid's close method that will not close the
graphics window until the user clicks on it.
- startRandomGame(): creates a starting point world where Cells are randomly
selected to be live or dead
- 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))
- startExpanderGame(): creates a starting point world of the expander
pattern such that it is drawn CENTERED in the world grid (see the Sample
output section for what this pattern should look like)
- playGame(num_steps): play the game of life on the current world state
for num_steps time steps (see the rule of the game of life above). Use the
sleep function to sleep some number of tenths of a second between each
time step
- The constructor to the GameOfLife class should take the number of rows
and columns in the world
- You should write a main program that prompts the user to enter the
number of rows and columns in the world, then creates a GameOfLife object
of the given dimensions. For each of the game starting points
(random, walker and expander) in turn your program should:
- call the startX method to initialize initialize the world for
the appropriate game of life
- prompt the user to enter the number of time steps to simulate this
game
- play the game of life
Getting Started
If you are using your grid.py solution, then to the bottom of
your grid.py file
remove the call to main() you can
replace it with the following instead (this is used when you import
classes from grid.py into another file to ensure that any main function
in grid.py will not be called):
if __name__ == '__main__':
main()
To the top of your gameoflife.py file, import classes from grid.py:
from grid import *
or to just import the Grid and Cell class definitions:
from grid import Grid
from grid import Cell
If you use our starting point solution to grid (in grid.pyc that you
grabbed with update21), then you can see the interface to it by
doing the following:
$python
>>> from grid import Grid
>>> from grid import Cell
>>> help(Cell)
>>> help(Grid)
Sample output
$ python gameoflife.py
This program plays Conway's Game of Life
Enter number of rows in the grid: 21
Enter number of cols in the grid: 21
Enter the number of steps to run the random game: 30
Enter the number of steps to run the walker game: 50
Enter the number of steps to run the expander game: 20
Click to exit
Test Patterns
One way to test for correctness is to try a pattern that repeats in
a well known way. For example, if you initialize 3 cells in a column
to Cell.ON, then in the next time step the ON cells will flip to be
3 cells in a row with the same middle Cell as the column. This pattern
repeats forever (alternating between 3 cells in a row and 3 cells in
a column). Here is a pattern based on this:
Optional Extensions
As always, do not even think of trying any of these until you have the
basic assignment implemented and tested.
Here are some ideas for extensions:
- Add other starting point methods that initialize the world
to different configurations. There are many that will lead to
interesting patterns that move across the space in some way that
converge to a static pattern in some way. Look on-line for some
examples.
- Modify the Grid and Cell class so that a user can use mouse clicks
to turn cells ON or OFF to set a starting pattern for each game.
If you do this extension, submit two solutions: gameoflife.py with the
basic assignment; and gameoflife_ex2.py with this version.
I have not done this extension, so I don't have an idea of how difficult
it is, but I suspect that it will require a significant amount of
effort. I think the best way to try this is to add another row of
buttons to the graphics window that have functionality such as start,
stop, clear and quit. The user would then choose clear to clear the grid,
click on individual grid cells to turn them ON or OFF, and then choose
start to start the game of life simulation, and stop to stop it. The
quit button could close the game.
Submit
Once you are satisfied with your program, hand it in by typing
handin21 in a terminal window.