康威生命游戏是由英国教授John Horton Conway提出的一种生命仿真游戏。其具体的形式是,所有的细胞生活在一个二维平面上,一个细胞在下一个时刻的生存状态取决于当前时刻周围的各个细胞的生存状态,如果相邻方块的存活细胞过多,则该细胞则会因为物资过于匮乏在下一时刻死去,如果相邻方块的存活细胞过少,则该细胞则会因为孤单而在下一时刻死亡。康威生命游戏在一定的给定初始条件以及存活条件下,会呈现出不同的生命发展趋势,最终可能会趋于一个收敛的稳定状态,也可能永不停止。这也是元胞自动机的雏形。
在游戏开始时,我们随机地设定每一个细胞的生存状态,并且规定规则如下:
1、如果该细胞周围的八个细胞在当前时刻恰好有三个生存,则该细胞在下一时刻仍然存活;
2、其他情况下,该细胞的下一时刻状态将变成死亡;
3、用1表示存活,用0表示死亡;
4、对于边界上的细胞,我们将模型考虑成一个首尾相接的平面,即对于右侧边界的点,其再右侧的点为左边界的点,对于上下边界以及四个角落的点采用相同的考虑方式。
在这个实例中,我们采用matplotlib.pyplot的散点图的方式来表示细胞的存活状态。
以下是具体代码内容:
首先,引入相关的需要使用的库:
import matplotlib.pyplot as plt
import numpy as np
import random
初始化二维网格以及所有细胞的存活状态:
class GameOfLife:
cells = []
def __init__(self, size):
self.size = size
def cells_ini(self):
self.cells = [[1 if random.random() > 0.5 else 0 for i in range(self.size)] for j in range(self.size)]
此处size接收二维网格的长度和宽度,我们默认其为一个正方形。通过random.random()方法,以0.5的概率赋予每个网格点存活/死亡的初始状态。
尔后,对每个点的周围相邻点的细胞当前存活状态进行计算,并据此确定下一时刻的生存状态:
def count_nearby_alive(self, x, y):
near = [-1, 0, 1]
nearby = 0
for dx in near:
for dy in near:
if dx + x == self.size:
new_x = 0
if dy + y == self.size:
new_y = 0
if dx + x != self.size and dy + y != self.size:
new_x = dx + x
new_y = dy + y
nearby += self.cells[new_x][new_y]
nearby = nearby - self.cells[x][y]
return nearby
def change_status(self, x, y):
count = self.count_nearby_alive(x,y)
return 1 if count == 3 else (0 if count < 2 or count > 3 else self.cells[x][y])
此处,读者可以通过修改change_status方法中的return结果来修改生存规则。
最后,反复更新每个时刻的二维网格生存状态,并且用ax.cla()方法不断更新打印图像的幕布,实现图像的动态显示:
def update_whole_cells(self):
self.cells = [[self.change_status(x,y) for y in range(self.size)] for x in range(self.size)]
def plot_it(self):
time = 0
more = 0.8
ax.axis([-more,1+more,-more,1+more])
while True:
time = time + 1
ax.cla()
ax.axis('square')
ax.axis('off')
plt.title('Game of Life (Time step '+str(time)+')')
self.update_whole_cells()
plot_list = (np.array([(i,j) for i in range(self.size) for j in range(self.size) if self.cells[i][j] == 1]) / self.size).transpose()
ax.scatter(plot_list[0], plot_list[1], s=1300 / self.size, c='b', marker='s', edgecolors='none')
plt.pause(0.01)
执行主程序:
def run_life_game():
global fig, ax
fig, ax = plt.subplots()
Life = GameOfLife(100)
Life.cells_ini()
Life.plot_it()
plt.grid()
plt.show()
return None
if __name__ == '__main__':
run_life_game()
该代码纯属个人兴趣由来编写,如有不当之处或可精进修改之处敬请指正。
完整代码如下:
import matplotlib.pyplot as plt
import numpy as np
import random
class GameOfLife:
cells = []
def __init__(self, size):
self.size = size
def cells_ini(self):
self.cells = [[1 if random.random() > 0.5 else 0 for i in range(self.size)] for j in range(self.size)]
def count_nearby_alive(self, x, y):
near = [-1, 0, 1]
nearby = 0
for dx in near:
for dy in near:
if dx + x == self.size:
new_x = 0
if dy + y == self.size:
new_y = 0
if dx + x != self.size and dy + y != self.size:
new_x = dx + x
new_y = dy + y
nearby += self.cells[new_x][new_y]
nearby = nearby - self.cells[x][y]
return nearby
def change_status(self, x, y):
count = self.count_nearby_alive(x,y)
return 1 if count == 3 else (0 if count < 2 or count > 3 else self.cells[x][y])
def update_whole_cells(self):
self.cells = [[self.change_status(x,y) for y in range(self.size)] for x in range(self.size)]
def plot_it(self):
time = 0
more = 0.8
ax.axis([-more,1+more,-more,1+more])
while True:
time = time + 1
ax.cla()
ax.axis('square')
ax.axis('off')
plt.title('Game of Life (Time step '+str(time)+')')
self.update_whole_cells()
plot_list = (np.array([(i,j) for i in range(self.size) for j in range(self.size) if self.cells[i][j] == 1]) / self.size).transpose()
ax.scatter(plot_list[0], plot_list[1], s=1300 / self.size, c='b', marker='s', edgecolors='none')
plt.pause(0.01)
def run_life_game():
global fig, ax
fig, ax = plt.subplots()
Life = GameOfLife(100)
Life.cells_ini()
Life.plot_it()
plt.grid()
plt.show()
return None
if __name__ == '__main__':
run_life_game()