Python 实现基于元胞自动机的生命游戏

作者: Python高效编程 | 来源:发表于2019-06-06 11:19 被阅读5次

这次我们使用 Python 来实现生命游戏,这是一种简单的元胞自动机。基于一定规则,程序可以自动从当前状态推演到下一状态。制作的成品如下:

在这里插入图片描述

先来说说生命游戏的规则:

在生命游戏中,每个单元格有两种状态,生与死。在我们的实现中,黄色的单元格代表活着的细胞,红色单元格表示死亡的细胞。而每一个细胞的下一状态,是由该细胞及周围的八个细胞的当前状态决定的。

具体而言:

当前细胞为活细胞

  1. 周围有两个或者三个活细胞,下一世代,该细胞仍然活着。
  2. 周围少于两个活细胞,该细胞死于孤立。
  3. 周围多于三个活细胞,该细胞死于拥挤。

当前细胞为死细胞

  • 周围恰好三个活细胞,下一世代,活细胞将繁殖到该单元格。
在这里插入图片描述

所需模块

无需安装的标准库:

  • argparse(命令行参数)
  • enum(枚举)

第三方库:

  • numpy
  • matplotlib

导入模块:

# 关注微信公众号:Python高效编程,后台回复`2019527`,获取源代码。
import argparse
from enum import IntEnum
import matplotlib.pyplot as plt
import matplotlib.animation as animation  # 制作动图
import numpy as np

编程要点

首先,我们要知道细胞的生存空间是 N * N 的方阵,每个细胞都有两种状态:on, off。on 为 255,off 为 0。我们使用 numpy 产生 N * N 的方阵。np.random.choice 是在 State.on 和 State.off ,等概率随机抽取一个元素构造 N * N 的方阵。

class State(IntEnum):
    on = 255
    off = 0

def random_data(length = 4, seed = 420) -> np.array:
    np.random.seed(seed)
    return np.random.choice([State.off, State.on], size=(length, length), p=[0.5, 0.5])

其次我们要明白如何计算细胞周围活细胞的个数,尤其是边界一圈的细胞。我们可以采用余数的方式,假设棋盘大小为 9 * 9,那么对于左右边界而言,左边界的左边一个元素的计算方式: - 1 % 9 = 8,自动折到右边界上。将细胞周围八个单元格的数值加起来,除以 255,就可以得到细胞周围活细胞的个数。

def _count(data, row, col):
    shape = data.shape[0]
    up = (row - 1) % shape
    down = (row + 1) % shape
    right = (col + 1) % shape
    left = (col - 1) % shape
    return (data[up, right] + data[up, left] +
            data[down, right] + data[down, left] +
            data[row, right] + data[row, left] +
            data[up, col] + data[down, col]) // 255

接下来是对规则的翻译,即根据当前世代的状态,推演出下一世代,细胞的状态。initial 为当前世代的矩阵,data为下一世代的矩阵,我们根据 initial 的数值,计算出 data 的数值。total 为周围活细胞的个数,如果当前为活细胞,total 大于三或者小于二,下一世代就会死去。如果当前为死细胞,total 等于三,下一世代活细胞就会繁殖到该单元格上。

def count(initial, data, row, col):
    total = _count(initial, row, col)
    if initial[row, col]:
        if (total < 2) or (total > 3):
            data[row, col] = State.off
    else:
        if total == 3:
            data[row, col] = State.on

接下来是制作动图的过程,前面几行是绘图的基本操作。之后,我们使用到了 matplotlib.animation 的方法。其中,FuncAnimation 接受的参数含义:fig 为图像句柄,generate 函数是我们更新每一帧图像所需数据的函数,下面会有介绍,fargs 为 genrate 函数的除去第一个参数的其他参数,第一个参数由 FuncAnimation 指定 framenum(帧数) 传给 generate 函数。frames 是帧数,interval 是更新图像间隔,save_count 为从帧到缓存的值的数量。

如果指定保存路径(html),则保存为 html 动画。

# 关注微信公众号:Python高效编程,后台回复`2019527`,获取源代码。
def update(data, save_name):
    update_interval = 50
    fig, ax = plt.subplots()
    ax.set_xticks([])
    ax.set_yticks([])
    img = ax.imshow(data, cmap='autumn', interpolation='nearest')
    ani = animation.FuncAnimation(fig, generate, fargs=(img, plt, data),
                                  frames=20,
                                  interval=update_interval,
                                  save_count=50)
    if save_name:
        ani.save(save_name, fps=30, extra_args=['-vcodec', 'libx264'])
    plt.show()

下面我们来看 generate 函数,NUM 为当迭代次数,frame_num 接收来自 FuncAnimation 的帧数。通过嵌套的 for 循环,我们逐个地更新方阵中各元素的状态。

NUM = 0
# 关注微信公众号:Python高效编程,后台回复`2019527`,获取源代码。
def generate(frame_num, img, plt, initial):
    global NUM
    NUM += 1
    plt.title(f'{NUM} generation')
    data = initial.copy()
    rows, cols = data.shape
    for row in range(rows):
        for col in range(cols):
            count(initial, data, row, col)
    img.set_data(data)
    initial[:] = data[:]
    return img

最后,我们可以通过命令行参数,运行我们的程序:

-- size 参数为棋盘大小,--seed 为随机种子,用于产生不同的随机方阵。

python conway.py --size 50 --seed 18
在这里插入图片描述

高斯帕滑翔机枪(Gosper Glider Gun)

可将 --gosper 更改为 --glider 滑翔机。--save 为动图保存的地址。

python conway.py --size 80 --gosper --save gosper.html
在这里插入图片描述
关注微信公众号:Python高效编程,后台回复2019527,获取源代码。

相关文章

  • Python 实现基于元胞自动机的生命游戏

    这次我们使用 Python 来实现生命游戏,这是一种简单的元胞自动机。基于一定规则,程序可以自动从当前状态推演到下...

  • 元胞自动机实现生命游戏

    元胞自动机(CA)是一种新的研究复杂系统的模型,主要将连续系统离散化,方便研究具有相互作用系统的动力学及其时空演化...

  • 基于元胞自动机的谣言传播防治探究毕业设计

    包含: 课程论文+演示视频+答辩PPT+Python代码 基于元胞自动机的谣言传播防治探究 电创xxxx XXX ...

  • Verilog进阶计划

    VGA图像显示功能;元胞自动机,生命游戏,伊辛模型。sd卡存储功能;flappy bird小游戏 数字信号处理算法...

  • 2020-04-13

    生命游戏……元胞自动机?我好像还用MATLAB跑过? 突然觉得这些算法挺有意思的。 我要去复习数模,嘿嘿。

  • Python 实现元胞自动机中的生命游戏(Game of lif

    简介 细胞自动机(又称元胞自动机),名字虽然很深奥,但是它的行为却是非常美妙的。所有这些怎样实现的呢?我们可以把计...

  • Python 实现最简单的元胞自动机

    简介 元胞自动机(cellular automata) 是离散而抽象的计算系统。元胞自动机在时间和空间上是离散的,...

  • 元胞自动机的应用

    【定义】元胞自动机(Cellular Automata, CA)定义在一个具有离散、有限状态的元胞组成的元胞空间上...

  • 元胞自动机和康威生命游戏

    简介 发展和应用 元胞自动机(Cellular Automata, 简称CA),是冯·诺依曼在20世纪50年代初为...

  • 逆转箭头

    设元胞自动机(CA)运行第i步的位形为,若位形中只包含0和1两种元胞,则任一迭代规则都可以改成可逆的元胞自动机规则...

网友评论

    本文标题:Python 实现基于元胞自动机的生命游戏

    本文链接:https://www.haomeiwen.com/subject/czpyxctx.html