Python 生命游戏
生命游戏由细胞网格组成,其中每个细胞都可以是死的或活的,并且细胞的状态可以在每个时间步改变。单元格在时间步长 t 的状态取决于网格在时间 t-1 的状态,并且由一个非常简单的规则确定:
如果一个单元格已经活着并且有两个活着的邻居,或者如果它有三个活着的邻居,那么它就是活着的 。
我们称网格 宇宙 和活细胞 群 。在每个时间步,种群都在进化,我们有了 新一代 。人口的演变是一个令人着迷的观察过程,因为它可以产生令人难以置信的各种模式(以及 谜题 !)。
用 Python 实现生命游戏非常简单:
import numpy as np
def life(X, steps):
"""
Conway's Game of Life.
- X, matrix with the initial state of the game.
- steps, number of generations.
"""
def roll_it(x, y):
# rolls the matrix X in a given direction
# x=1, y=0 on the left; x=-1, y=0 right;
# x=0, y=1 top; x=0, y=-1 down; x=1, y=1 top left; ...
return np.roll(np.roll(X, y, axis=0), x, axis=1)
for _ in range(steps):
# count the number of neighbours
# the universe is considered toroidal
Y = roll_it(1, 0) + roll_it(0, 1) + roll_it(-1, 0) \
+ roll_it(0, -1) + roll_it(1, 1) + roll_it(-1, -1) \
+ roll_it(1, -1) + roll_it(-1, 1)
# game of life rules
X = np.logical_or(np.logical_and(X, Y ==2), Y==3)
X = X.astype(int)
yield X
life 函数接受一个矩阵 X 的 输入,它代表游戏的宇宙,其中每个单元格如果其对应元素的值为 1 则为活的,如果为 0 则为死的。该函数返回接下来的 几代 。在每个时间步,计算每个单元格的邻居数并应用游戏规则。现在我们可以创建一个具有初始状态的宇宙:
import numpy as np
def life(X, steps):
"""
Conway's Game of Life.
- X, matrix with the initial state of the game.
- steps, number of generations.
"""
def roll_it(x, y):
# rolls the matrix X in a given direction
# x=1, y=0 on the left; x=-1, y=0 right;
# x=0, y=1 top; x=0, y=-1 down; x=1, y=1 top left; ...
return np.roll(np.roll(X, y, axis=0), x, axis=1)
for _ in range(steps):
# count the number of neighbours
# the universe is considered toroidal
Y = roll_it(1, 0) + roll_it(0, 1) + roll_it(-1, 0) \
+ roll_it(0, -1) + roll_it(1, 1) + roll_it(-1, -1) \
+ roll_it(1, -1) + roll_it(-1, 1)
# game of life rules
X = np.logical_or(np.logical_and(X, Y ==2), Y==3)
X = X.astype(int)
yield X
这个初始状态被称为 R-pentomino。它由五个活细胞组成,如图所示(图片来自维基百科)
它是迄今为止最活跃的 多联骨牌 ,少于六个细胞,所有其他细胞最多在 10 代内稳定。让我们创建一个视频来可视化系统的演变:
import numpy as np
def life(X, steps):
"""
Conway's Game of Life.
- X, matrix with the initial state of the game.
- steps, number of generations.
"""
def roll_it(x, y):
# rolls the matrix X in a given direction
# x=1, y=0 on the left; x=-1, y=0 right;
# x=0, y=1 top; x=0, y=-1 down; x=1, y=1 top left; ...
return np.roll(np.roll(X, y, axis=0), x, axis=1)
for _ in range(steps):
# count the number of neighbours
# the universe is considered toroidal
Y = roll_it(1, 0) + roll_it(0, 1) + roll_it(-1, 0) \
+ roll_it(0, -1) + roll_it(1, 1) + roll_it(-1, -1) \
+ roll_it(1, -1) + roll_it(-1, 1)
# game of life rules
X = np.logical_or(np.logical_and(X, Y ==2), Y==3)
X = X.astype(int)
yield X
结果如下: