整个世界是一个巨大的元胞系统

如题,整个世界是一个巨大的元胞系统。如果你想构建一个自己的小天地,做这个世界的老天爷,元胞系统可以说是一个最简单的办法。

1.了解元胞自动机

元胞自动机由四部分构成:元胞、元胞空间、邻居、规则

元胞:将整个空间分为一块块最简单的单位晶格,这些个晶格就是元胞。元胞是组成元胞空间的最基本单位。同时,每个元胞有自己的状态值,通常用离散的整数集来模拟实际的状态。元胞的形状多种多样,但是一般采用正方形(体)便于表达显示。

元胞空间:由一个个元胞组成的空间,用来模拟实际的n维空间。

邻居:与当前元胞相互作用的其他元胞,用于后续的状态转移。

规则:规则实际上是一种状态转移方程。对于下一个阶段,当前元胞在邻居对于规则的作用下发生的转变用于模拟世界中事物的变化趋势,这就是自动的由来。规则的制定越贴合实际、越复杂,那么你构建的世界便越贴合实际。

如城市的发展与演化、城市人流与交通流以及交通堵塞的形成、自然环境下的动物的空间分布、河网的形成、疾病的传播等,都可以通过元胞自动机模拟。一些游戏当然也可以用元胞自动机实现。

2.元胞自动机的实例

2.1初等元胞自动机

初等元胞自动机是状态集S只有两个元素{s1s2},即状态个数k=2,邻居半径r=1的一维元胞自动机。由于在S中具体采用什么符号并不重要,它可取 {01}{-11}{静止,运动} 等等,重要的是S所含的符号个数,通常我们将其记为 {01}。此时,邻居集N的个数r=2,局部映射fS3S可记为:

例如,取{0,1}为{真,假},规定规则为全为真才是真,那么当前元胞在演变过程中与其对应的邻居组成的元胞集为(111)({左邻居 自己 右邻居})才会演变为1,其余全是0。

对应的不同规则会导致不同的演化过程:

2.2康威生命游戏

下面介绍生命游戏的构成及规则:
(1)
元胞分布在规则划分的网格上;
(2)元胞具有01两种状态,0代表1代表
(3)元胞以相邻的8个元胞为邻居。即Moore邻居形式;
(4)一个元胞的生死由其在该时刻本身的生死状态和周围八个邻居的状态 (确切讲是状态的和)决定:
      
在当前时刻,如果一个元胞状态为,且八个相邻元胞中有两个或三个的状态为,则在下--时刻该元胞继续保持为,否则去;
       在当前时刻,如果一个元胞状态为
,且八个相邻元胞中正好有三个为,则该元胞在下一时刻 "复活"。否则保持为""

康威生命游戏

import numpy as np
import tkinter as tk
from tkinter import ttk

class CellularAutomatonApp:
    def __init__(self, root):
        self.root = root
        self.root.title("元胞自动机模拟器")
        self.root.geometry("600x650")  # 窗口大小
        self.root.resizable(False, False)  # 禁止调整窗口大小

        # 元胞参数
        self.rows = 50
        self.cols = 50
        self.cell_size = 10  # 每个元胞的像素大小
        self.grid = np.zeros((self.rows, self.cols), dtype=int)
        self.running = False

        # 创建画布(显示元胞网格)
        self.canvas = tk.Canvas(
            root,
            width=self.cols * self.cell_size,
            height=self.rows * self.cell_size,
            bg="white",
            highlightthickness=2,
            highlightbackground="gray"
        )
        self.canvas.pack(pady=20)

        # 控制区域
        control_frame = ttk.Frame(root)
        control_frame.pack(pady=10)

        # 开始按钮
        self.start_btn = ttk.Button(
            control_frame,
            text="开始模拟",
            command=self.toggle_simulation
        )
        self.start_btn.grid(row=0, column=0, padx=10)

        # 重置按钮
        self.reset_btn = ttk.Button(
            control_frame,
            text="重置网格",
            command=self.reset_grid
        )
        self.reset_btn.grid(row=0, column=1, padx=10)

        # 状态标签
        self.status_label = ttk.Label(
            root,
            text="状态:未运行",
            font=("SimHei", 10)
        )
        self.status_label.pack(pady=5)

        # 初始化网格
        self.reset_grid()

    def reset_grid(self):
        """重置元胞网格(随机初始化)"""
        self.grid = np.random.choice([0, 1], size=(self.rows, self.cols), p=[0.8, 0.2])
        self.generation = 0
        self.status_label.config(text=f"状态:已重置(第 0 代)")
        self.draw_grid()

    def draw_grid(self):
        """在画布上绘制元胞网格"""
        self.canvas.delete("all")  # 清空画布
        for i in range(self.rows):
            for j in range(self.cols):
                x1 = j * self.cell_size
                y1 = i * self.cell_size
                x2 = x1 + self.cell_size
                y2 = y1 + self.cell_size
                # 存活元胞为黑色,死亡元胞为白色
                color = "black" if self.grid[i, j] == 1 else "white"
                self.canvas.create_rectangle(x1, y1, x2, y2, fill=color, outline="lightgray")

    def count_neighbors(self, i, j):
        """计算单个元胞的邻居数量"""
        count = 0
        # 遍历3x3邻域
        for di in [-1, 0, 1]:
            for dj in [-1, 0, 1]:
                if di == 0 and dj == 0:
                    continue  # 跳过自身
                ni, nj = i + di, j + dj
                # 边界处理:超出网格范围视为死亡
                if 0 <= ni < self.rows and 0 <= nj < self.cols:
                    count += self.grid[ni, nj]
        return count

    def update_grid(self):
        """更新元胞状态(康威生命游戏规则)"""
        new_grid = self.grid.copy()
        for i in range(self.rows):
            for j in range(self.cols):
                neighbors = self.count_neighbors(i, j)
                if self.grid[i, j] == 1:
                    # 存活元胞:邻居<2或>3则死亡
                    if neighbors < 2 or neighbors > 3:
                        new_grid[i, j] = 0
                else:
                    # 死亡元胞:邻居=3则复活
                    if neighbors == 3:
                        new_grid[i, j] = 1
        self.grid = new_grid
        self.generation += 1
        self.status_label.config(text=f"状态:运行中(第 {self.generation} 代)")

    def simulate_step(self):
        """模拟一步并刷新显示"""
        if self.running:
            self.update_grid()
            self.draw_grid()
            # 定时刷新(100毫秒/步)
            self.root.after(100, self.simulate_step)

    def toggle_simulation(self):
        """切换模拟状态(开始/暂停)"""
        if self.running:
            self.running = False
            self.start_btn.config(text="继续模拟")
            self.status_label.config(text=f"状态:已暂停(第 {self.generation} 代)")
        else:
            self.running = True
            self.start_btn.config(text="暂停模拟")
            self.simulate_step()

if __name__ == "__main__":
    root = tk.Tk()
    app = CellularAutomatonApp(root)
    root.mainloop()

2.3森林火灾

规则:

元胞有3个不同的状态。状态为 0是树木,状态= 1是空地,状态= 5是燃烧着的树木。如果4个邻居中有一个或一个以上的是燃烧着的并且自身是树木,那么该元胞下一时刻的状态是燃烧。森林元胞(状态为 0 )以一个低概率(例如0.000005 )开始烧(因为闪电)。一个燃烧着的元胞(状态为 5 )在下一时刻(时间步长可以控制)变成空位的(状态为0 ) 。空元胞以一个低概率(例如0.01 )变为森林以模拟生长。

读者可以根据规则自行修改生命游戏代码测试效果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值