The Game of Life
The Game of Life was invented by the mathematician John Horton Conway in 1970. Nobody plays it: you set up a pattern of cells and watch what happens to it. The board is a grid of cells, and each cell is either alive or dead. Every cell has eight neighbors, the cells that touch it: above, below, left, right and the four diagonals. From one generation to the next, every cell follows the same rules, all at the same time:
- A live cell with 2 or 3 live neighbors stays alive.
- A live cell with fewer than 2 live neighbors dies, as if of loneliness, and one with more than 3 dies of overcrowding.
- A dead cell with exactly 3 live neighbors comes alive.
- Any other dead cell stays dead.
That's all. Yet some patterns blink forever, some freeze, some die out, and some even crawl across the board.
In this project the grid is a list of lists, as in module 19: one list per row, with 1 for a live cell and 0 for a dead one. On the screen, a live cell is # and a dead one is ..
When it's finished, the program asks for a starting pattern, typed one row at a time and ended with an empty line, and for the number of generations to show. With this input:
......
.###..
.#....
......
......
9
it prints:
Type the grid, one row per line, and an empty line at the end:
......
.###..
.#....
......
......
Generations: 9
Generation 0: 4 alive
......
.###..
.#....
......
......
Generation 1: 4 alive
..#...
.##...
.#....
......
......
Generation 2: 6 alive
.##...
.##...
.##...
......
......
Generation 3: 6 alive
.##...
#..#..
.##...
......
......
Nothing changes any more.
Nine generations were asked for, but after the third one the pattern has settled into a shape that never changes, so the program stops there.
What you need
Everything up to module 19: functions that return values, with the program's own code under if __name__ == "__main__": (modules 13 and 14), lists and for loops with range (modules 15 and 16), f-strings (module 17), and above all lists of lists, read with two indexes such as grid[row][column] (module 19).
How you build it
Each milestone starts from your own code of the milestone before, and adds a function or two:
- The grid: print it, and count its live cells.
- Neighbors: count the live cells around a cell, and decide whether it lives on.
- The next generation: a whole new grid, worked out from the old one.
- A start from input: read the starting pattern that the user types.
- Several generations: run as many generations as the user asks for.
- Stopping early: stop when everything is dead or nothing changes any more.
The checks of the first milestones call your functions directly, as in the lessons. From milestone 4 on, others type into the whole program and compare everything it prints.
Milestones
- The grid
- Neighbors
- The next generation
- A start from input
- Several generations
- Stopping early