See still life, glider and spaceship, oscillators, etc. Also see A New Kind of Science.
""" life.py J. H. Conway's Game of Life. The number of rows that you see is self.nrows. Their index numbers run from 0 to self.nrows - 1 inclusive. In addition, there are extra additional rows that are not displayed. Their index numbers run from self.nrows to self.nrows + Life.extra - 1 inclusive. Finally, there is one more row, at index number self.nrows + Life.extra, that is always empty. Ditto for the columns. """ import tkinter import time class Life(object): extra = 5 #how many extra rows or columns of boxes along each edge def __init__(self, picture): picture = picture.splitlines() self.nrows = len(picture) self.ncols = len(picture[0]) self.b = self.emptyBoard() for row in range(self.nrows): self.b[Life.extra + row][Life.extra:Life.extra + self.ncols] = \ [picture[row][col] == "X" for col in range(self.ncols)] def get(self, x, y): "Return the value at row y, column x." assert 0 <= x < self.ncols and 0 <= y < self.nrows return self.b[Life.extra + y][Life.extra + x] def emptyBoard(self): "Return a two-dimensional list of Bools (all False)." return [(self.ncols + 2 * Life.extra) * [False] for i in range(self.nrows + 2 * Life.extra)] def next(self): b1 = self.emptyBoard() for y in range(1, 2 * Life.extra + self.nrows - 1): for x in range(1, 2 * Life.extra + self.ncols - 1): #How many of the 8 neighbors of (x, y) are occupied? listOf8Neighbors = [ self.b[y1][x1] for y1 in range(y - 1, y + 2) for x1 in range(x - 1, x + 2) if x1 != x or y1 != y ] count = listOf8Neighbors.count(True) if count == 2: b1[y][x] = self.b[y][x] #Law of Survival else: b1[y][x] = count == 3 #Laws of Birth and Death self.b = b1 def _test(): import tkinter picture = """\ ........... .X......X.. ..XX....X.. .XX.....X.. ........... ........... ........... ........... .XX........ .XX........ ........... """ life = Life(picture) boxSide = 12 #pixels root = tkinter.Tk() root.title("Conway's Game of Life") #dimensions in pixels root.geometry(f"{life.ncols * boxSide}x{life.nrows * boxSide}") canvas = tkinter.Canvas(root, highlightthickness = 0) canvas.pack(expand = tkinter.YES, fill = "both") while True: draw(life, canvas, boxSide) life.next() root.update() time.sleep(0.5) def draw(life, canvas, boxSide): canvas.delete(tkinter.ALL) for y, row in enumerate(life.b[Life.extra:Life.extra + life.nrows]): for x, box in enumerate(row[Life.extra:Life.extra + life.ncols]): left = x * boxSide top = y * boxSide canvas.create_rectangle( left, top, left + boxSide, top + boxSide, width = 1, #width of border outline = "white", #color of border fill = "black" if box else "gray" ) if __name__ == '__main__': _test()
Test the module:
python3 -m life
This program imports the above module.
""" lifeimporter.py Run J. H. Conway's Game of Life on a tkinter Canvas widget. """ import tkinter import time import life #the module life.py that we wrote #Gosper glider gun. picture = """\ ...................................... .........................X............ .......................X.X............ .............XX......XX............XX. ............X...X....XX............XX. .XX........X.....X...XX............... .XX........X...X.XX....X.X............ ...........X.....X.......X............ ............X...X..................... .............XX....................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... ...................................... """ game = life.Life(picture) boxSize = 12 #in pixels def draw(game, canvas): canvas.delete(tkinter.ALL) for y in range(game.nrows): for x in range(game.ncols): left = x * boxSize top = y * boxSize canvas.create_rectangle( left, top, left + boxSize, top + boxSize, width = 1, #width of border outline = "white", #color of border fill = "black" if game.get(x, y) else "gray" ) root = tkinter.Tk() root.title("Conway's Game of Life") #dimensions in pixels root.geometry(f"{boxSize * game.ncols}x{boxSize * game.nrows}") canvas = tkinter.Canvas(root, highlightthickness = 0) canvas.pack(expand = tkinter.YES, fill = "both") while True: draw(game, canvas) game.next() root.update() time.sleep(0.25)