文章目录
一、生命游戏是什么
生命游戏(Game of Life)是由英国数学家约翰·何顿·康威在1970年发明的一种细胞自动机(Cellular Automaton),也可以称为生命棋或零玩家游戏。生命游戏的特点主要体现在以下几个方面:
- 游戏背景
生命游戏在一个二维的网格上进行,每个网格(或称为格子、细胞)都可以处于"生"或"死"的状态。网格可以是无穷大的,也可以是一个有限大的矩形。 - 游戏规则
一个细胞的生死状态完全取决于它周围八个相邻细胞的状态。具体规则如下:
当前状态 | 下一代状态 |
---|---|
存活 | 如果周围恰好有2个或3个活细胞,则它在下一代仍然存活;如果周围有0个、1个或超过3个的活细胞,则它在下一代死去(因孤独或过度拥挤) |
死去 | 如果周围有恰好3个活细胞,则它在下一代复活(模拟繁殖) |
- 游戏特性
生命游戏是一个零玩家游戏,即没有玩家的干预或输入,所有变化都遵循预设的规则。
随着游戏的进行,杂乱无序的细胞会逐渐演化出各种精致、有形的结构,有时这些结构会保持稳定,有时会因为无序细胞的"入侵"而被破坏。生命游戏的规则简单,但能够产生出复杂且富有变化的模式,这体现了从简单规则中产生复杂性的原理。 - 应用场景
生命游戏不仅在数学和计算机科学领域具有研究价值,也常被用于演示元胞自动机的原理和特性。在艺术和设计领域,生命游戏也被用于生成独特的纹理和图案。生命游戏是一个简单但强大的模型,它展示了从简单规则中涌现出复杂性和多样性的能力,对理解自然界和社会现象提供了有趣的视角。
二、生命游戏规则解释
1.相邻细胞
对于如下3×3的9宫格, i i i号细胞的周围八个相邻细胞分别是 a 、 b 、 c 、 d 、 e 、 f 、 g 、 h a、b、c、d、e、f、g、h a、b、c、d、e、f、g、h
a b c d i e f g h \] \\left\[ \\begin{matrix} a \& b \& c \\\\ d \& i \& e \\\\ f \& g \& h \\\\ \\end{matrix} \\right\] adfbigceh ### 2.细胞状态 > **1表示细胞存活状态,0表示细胞死去状态。** * 当前状态为存活,下一代继续存活 假设当前细胞 i i i为存活状态,如果相邻细胞的状态如下所示,则细胞 i i i下一代继续存活,因为其周围有3个活细胞。 \[ 0 0 1 0 1 1 1 0 0 \] \\left\[ \\begin{matrix} 0 \& 0 \& 1 \\\\ 0 \& 1 \& 1 \\\\ 1 \& 0 \& 0 \\\\ \\end{matrix} \\right\] 001010110 * 当前状态为存活,下一代不能存活 假设当前细胞 i i i为存活状态,如果相邻细胞的状态如下所示,则细胞 i i i下一代不能存活,因为其周围有4个活细胞,拥挤死去。 \[ 0 0 1 1 1 1 1 0 0 \] \\left\[ \\begin{matrix} 0 \& 0 \& 1 \\\\ 1 \& 1 \& 1 \\\\ 1 \& 0 \& 0 \\\\ \\end{matrix} \\right\] 011010110 * 当前状态为死去,下一代复活 假设当前细胞 i i i为死去状态,如果相邻细胞的状态如下所示,则细胞 i i i复活,因为其周围恰有3个活细胞。 \[ 1 0 0 1 0 0 0 0 1 \] \\left\[ \\begin{matrix} 1 \& 0 \& 0 \\\\ 1 \& 0 \& 0 \\\\ 0\& 0 \& 1 \\\\ \\end{matrix} \\right\] 110000001 * 当前状态为死去,下一代继续为死去状态 假设细胞 i i i为死去状态, 如果相邻细胞的状态如下所示,则细胞 i i i继续为死去状态,因为其周围有1个活细胞。 \[ 0 0 0 1 0 0 0 0 0 \] \\left\[ \\begin{matrix} 0 \& 0 \& 0 \\\\ 1 \& 0 \& 0 \\\\ 0\& 0 \& 0 \\\\ \\end{matrix} \\right\] 010000000 ## 三、代码实现 ### 1.邻居细胞 针对邻居8个细胞,分别进行判断,这里采用的是一个有限大的矩形。 ```python #判断每一代邻居生存状态 def cal(i, j): count = 0 if i-1 >= 0 and j-1>= 0: count = count + earth_init[i-1][j-1] if i-1 >= 0: count = count + earth_init[i-1][j] if i-1 >= 0 and j+1< grid_size: count = count + earth_init[i-1][j+1] if j-1>= 0: count = count + earth_init[i][j-1] if j+1< grid_size: count = count + earth_init[i][j+1] if i+1 < grid_size and j-1>= 0: count = count + earth_init[i+1][j-1] if i+1 < grid_size: count = count + earth_init[i+1][j] if i+1 < grid_size and j+1< grid_size: count = count + earth_init[i+1][j+1] return count ``` ### 2.更新状态 根据细胞的存活、死去状态进行更新。 ```python #更新新一代earth def new_earth(earth_init): earth = copy.deepcopy(earth_init) for i in range(grid_size): for j in range(grid_size): #活细胞 if earth[i][j] == 1: if cal(i, j) <= 1 or cal(i, j) >= 4: earth[i][j] = 0 #死细胞 else: if cal(i, j) == 3: earth[i][j] = 1 return earth ``` ## 四、整体代码 完整代码如下所示。 ```python import copy import matplotlib.pyplot as plt import numpy as np import random #生命游戏二维空间大小 grid_size = 30 #init生命数量 counts = 100 def grid_init(input): #手动输入关注型态 care_init = [[10,10], [11,10], [12,10],[13,10]] #随机生成 labels = [] random.randint(0,grid_size-1) for i in range(counts): labels.append([random.randint(0,grid_size-1), random.randint(0,grid_size-1)]) #初始化 earth_init = np.zeros((grid_size, grid_size)) if input != 'random': labels = care_init for label in labels: earth_init[label[0]][label[1]] = 1 return earth_init #判断每一代邻居生存状态 def cal(i, j): count = 0 if i-1 >= 0 and j-1>= 0: count = count + earth_init[i-1][j-1] if i-1 >= 0: count = count + earth_init[i-1][j] if i-1 >= 0 and j+1< grid_size: count = count + earth_init[i-1][j+1] if j-1>= 0: count = count + earth_init[i][j-1] if j+1< grid_size: count = count + earth_init[i][j+1] if i+1 < grid_size and j-1>= 0: count = count + earth_init[i+1][j-1] if i+1 < grid_size: count = count + earth_init[i+1][j] if i+1 < grid_size and j+1< grid_size: count = count + earth_init[i+1][j+1] return count #更新新一代earth def new_earth(earth_init): earth = copy.deepcopy(earth_init) for i in range(grid_size): for j in range(grid_size): if earth[i][j] == 1: if cal(i, j) <= 1 or cal(i, j) >= 4: earth[i][j] = 0 else: if cal(i, j) == 3: earth[i][j] = 1 return earth #作图 def pplot(earth): # 创建一个grid_size x grid_size的网格 x = np.linspace(0, 1, grid_size) y = np.linspace(0, 1, grid_size) X, Y = np.meshgrid(x, y) # 绘制九宫格 fig, ax = plt.subplots() for i in range(grid_size): for j in range(grid_size): if earth[i][j] == 1: #白色 color = [1, 1, 1] else: #黑色 color = [0, 0, 0] # 绘制每个格子,使用颜色数组中的对应颜色 ax.add_patch(plt.Rectangle( (x[i], y[j]), # 左下角坐标 x[1] - x[0], # 宽度 y[1] - y[0], # 高度 #color=colors[i, j], # 颜色 color=color, edgecolor='black' # 边框颜色 )) # 设置坐标轴范围 ax.set_xlim(0, 1) ax.set_ylim(0, 1) # 关闭坐标轴的刻度显示 ax.set_xticks([]) ax.set_yticks([]) ax.set_aspect('equal', adjustable='box') # 显示图形 plt.show(block=False) plt.pause(1) plt.close() earth_init = grid_init('random') pplot(earth_init) #迭代代数 iters = 100 for i in range(iters): earth = new_earth(earth_init) #没有生命存活则停止 if sum(sum(earth)) == 0: break pplot(earth) plt.close('all') print('='*20, i) print(sum(sum(earth))) earth_init = copy.deepcopy(earth) ``` 附上一张实验图。 