The game of life is built on a grid of nine squares, each with eight adjacent cells.
The game has three rules:
1. If there are 3 cells living around a cell (there are 8 cells around a cell), the cell is living (that is, if the cell was originally dead, it will become living, if it was originally living, it will remain unchanged).
2. If there are two cells around a cell, the life and death state of the cell remains unchanged;
3. In other cases, the cell is dead (that is, if the cell was originally living, it will turn to dead, if it was originally dead, it will remain unchanged)
import sys, argparse
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
ON = 255
OFF = 0
vals = [ON, OFF]
#np's choice() method will select a value from the given list vals, with a probability from 0.2 to 0.8. n*n values are created, and reshape() method is used to make it a two-dimensional array
def randomGrid(N):
return np.random.choice(vals, N*N, p=[0.2, 0.8]).reshape(N, N)
#Define a pattern with numpy array and copy it to 2D mesh with slice operation
def addGlider(i, j, grid):
"""adds a glider with top left cell at (i, j)"""
glider = np.array([[0, 0, 255],
[255, 0, 255],
[0, 255, 255]])
grid[i:i+3, j:j+3] = glider
#Add a Gosper glider graphic
def addGosperGliderGun(i, j, grid):
gun = np.zeros(11*38).reshape(11, 38)
gun[5][1] = gun[5][2] = 255
gun[6][1] = gun[6][2] = 255
gun[3][13] = gun[3][14] = 255
gun[4][12] = gun[4][16] = 255
gun[5][11] = gun[5][17] = 255
gun[6][11] = gun[6][15] = gun[6][17] = gun[6][18] = 255
gun[7][11] = gun[7][17] = 255
gun[8][12] = gun[8][16] = 255
gun[9][13] = gun[9][14] = 255
gun[1][25] = 255
gun[2][23] = gun[2][25] = 255
gun[3][21] = gun[3][22] = 255
gun[4][21] = gun[4][22] = 255
gun[5][21] = gun[5][22] = 255
gun[6][23] = gun[6][25] = 255
gun[7][25] = 255
gun[3][35] = gun[3][36] = 255
gun[4][35] = gun[4][36] = 255
grid[i:i+11, j:j+38] = gun
def update(frameNum, img, grid, N):
# copy grid since we require 8 neighbors for calculation
# and we go line by line
newGrid = grid.copy()
for i in range(N):
for j in range(N):
#Calculate the values of eight neighboring neighbors and divide the sum by 255 to obtain the number of cells ON
total = int((grid[i, (j-1)%N] + grid[i, (j+1)%N] +
grid[(i-1)%N, j] + grid[(i+1)%N, j] +
grid[(i-1)%N, (j-1)%N] + grid[(i-1)%N, (j+1)%N] +
grid[(i+1)%N, (j-1)%N] + grid[(i+1)%N, (j+1)%N])/255)
# apply Conway's rules
if grid[i, j] == ON:
if (total < 2) or (total > 3):
newGrid[i, j] = OFF
else:
if total == 3:
newGrid[i, j] = ON
# update data
img.set_data(newGrid)
grid[:] = newGrid[:]
return img,
# main() function
def main():
# Command line args are in sys.argv[1], sys.argv[2] ..
# sys.argv[0] is the script name itself and can be ignored
# parse arguments
parser = argparse.ArgumentParser(description="Runs Conway's Game of Life simulation.")
# add arguments
#dest: parameter name
#Dest: if dest is provided, for example dest="a", the parameter can be accessed through args.a
parser.add_argument('--grid-size', dest='N', required=False)
parser.add_argument('--mov-file', dest='movfile', required=False)
parser.add_argument('--interval', dest='interval', required=False)
#Store? True and store? False: store values as true or false
parser.add_argument('--glider', action='store_true', required=False)
parser.add_argument('--gosper', action='store_true', required=False)
#The parse_args() method actually returns some data from our command line arguments
args = parser.parse_args()
#Set grid size
N = 100
if args.N and int(args.N) > 8:
N = int(args.N)
# set animation update interval
updateInterval = 50
if args.interval:
updateInterval = int(args.interval)
# declare grid
grid = np.array([])
# check if "glider" demo flag is specified
if args.glider:
grid = np.zeros(N*N).reshape(N, N)
addGlider(1, 1, grid)
elif args.gosper:
grid = np.zeros(N*N).reshape(N, N)
addGosperGliderGun(10, 10, grid)
else:
# populate grid with random on/off - more off than on
grid = randomGrid(N)
#Set animation
fig, ax = plt.subplots()
img = ax.imshow(grid, interpolation='nearest')
ani = animation.FuncAnimation(fig, update, fargs=(img, grid, N, ),
frames = 10,
interval=updateInterval,
save_count=50)
# # of frames?
# set output file
if args.movfile:
ani.save(args.movfile, fps=30, extra_args=['-vcodec', 'libx264'])
plt.show()
# call main
if __name__ == '__main__':
main()
The reference for argparse is as follows
https://blog.csdn.net/lis_12/article/details/54618868
https://www.cnblogs.com/zknublx/p/6106343.html
The main references for Matplotlib library are:
https://www.cnblogs.com/LHWorldBlog/p/7819331.html
http://python.jobbole.com/85106/