一个简单的模拟宇宙——基于NKS理论的3D元胞自动机

在这里插入图片描述

这是一个基于NKS(一种新科学)思想的3D元胞自动机模拟器。它使用 Python + Pygame + NumPy 实现,你可以在三维网格中探索简单规则如何产生复杂结构。

import pygame
import numpy as np
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import sys

# ==================== 配置参数 ====================
GRID_SIZE = 20           # 网格 20x20x20
CELL_SIZE = 0.5          # 单元格大小
CUBE_SIZE = CELL_SIZE * 0.9  # 立方体绘制大小(留间隙)
UPDATE_DELAY = 100       # 更新间隔(毫秒)

# ==================== 三维元胞自动机类 ====================
class CellularAutomaton3D:
    def __init__(self, size):
        self.size = size
        # 随机初始化三维网格 (0 或 1)
        self.grid = np.random.choice([0, 1], size=(size, size, size), p=[0.85, 0.15])
        self.new_grid = np.zeros_like(self.grid)

    def get_neighbor_sum(self, x, y, z):
        """计算 (x,y,z) 周围26个邻居的和(不包含自身)"""
        total = 0
        for i in (-1, 0, 1):
            for j in (-1, 0, 1):
                for k in (-1, 0, 1):
                    if i == 0 and j == 0 and k == 0:
                        continue
                    ni, nj, nk = x + i, y + j, z + k
                    if 0 <= ni < self.size and 0 <= nj < self.size and 0 <= nk < self.size:
                        total += self.grid[ni, nj, nk]
        return total

    def update(self):
        """根据 NKS 风格规则更新网格"""
        for x in range(self.size):
            for y in range(self.size):
                for z in range(self.size):
                    neighbors = self.get_neighbor_sum(x, y, z)
                    state = self.grid[x, y, z]

                    # ---- NKS 风格规则(可自由修改) ----
                    # 规则:死细胞周围恰好有3个活细胞时诞生;活细胞周围有2或3个活细胞时存活
                    if state == 1:
                        if neighbors < 2 or neighbors > 3:
                            self.new_grid[x, y, z] = 0
                        else:
                            self.new_grid[x, y, z] = 1
                    else:
                        if neighbors == 3:
                            self.new_grid[x, y, z] = 1
                        else:
                            self.new_grid[x, y, z] = 0

        self.grid, self.new_grid = self.new_grid, self.grid
        self.new_grid.fill(0)

# ==================== 3D 渲染函数 ====================
def draw_cube(x, y, z, size, color):
    """在 (x,y,z) 处绘制一个彩色立方体"""
    half = size / 2.0
    vertices = [
        [x-half, y-half, z-half], [x+half, y-half, z-half],
        [x+half, y+half, z-half], [x-half, y+half, z-half],
        [x-half, y-half, z+half], [x+half, y-half, z+half],
        [x+half, y+half, z+half], [x-half, y+half, z+half]
    ]
    edges = [
        (0,1), (1,2), (2,3), (3,0),
        (4,5), (5,6), (6,7), (7,4),
        (0,4), (1,5), (2,6), (3,7)
    ]
    glColor3f(*color)
    glBegin(GL_QUADS)
    # 六个面:每个面两个三角形
    faces = [
        (0,1,2,3), (4,5,6,7),
        (0,1,5,4), (2,3,7,6),
        (0,3,7,4), (1,2,6,5)
    ]
    for face in faces:
        glVertex3fv(vertices[face[0]])
        glVertex3fv(vertices[face[1]])
        glVertex3fv(vertices[face[2]])
        glVertex3fv(vertices[face[3]])
    glEnd()
    glColor3f(0, 0, 0)
    glBegin(GL_LINES)
    for edge in edges:
        glVertex3fv(vertices[edge[0]])
        glVertex3fv(vertices[edge[1]])
    glEnd()

def render(ca):
    """渲染整个三维网格"""
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    gluPerspective(45, 1.0, 0.1, 50.0)
    glTranslatef(0.0, 0.0, -25)
    glRotatef(25, 1, 0, 0)
    glRotatef(-30, 0, 1, 0)

    offset = (ca.size - 1) * CELL_SIZE / 2.0
    for x in range(ca.size):
        for y in range(ca.size):
            for z in range(ca.size):
                if ca.grid[x, y, z] == 1:
                    # 根据位置映射颜色(从蓝色渐变到红色)
                    r = x / float(ca.size)
                    g = y / float(ca.size)
                    b = z / float(ca.size)
                    draw_cube(x * CELL_SIZE - offset,
                              y * CELL_SIZE - offset,
                              z * CELL_SIZE - offset,
                              CUBE_SIZE, (r, g, b))

# ==================== 主程序 ====================
def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
    pygame.display.set_caption("3D NKS 元胞自动机 - Pygame")
    glEnable(GL_DEPTH_TEST)

    ca = CellularAutomaton3D(GRID_SIZE)
    clock = pygame.time.Clock()
    last_update = pygame.time.get_ticks()
    running = True

    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    # 空格键:随机重置
                    ca.grid = np.random.choice([0, 1], size=(GRID_SIZE, GRID_SIZE, GRID_SIZE),
                                               p=[0.85, 0.15])
                elif event.key == pygame.K_r:
                    # R键:完全随机重置
                    ca.grid = np.random.choice([0, 1], size=(GRID_SIZE, GRID_SIZE, GRID_SIZE))
                elif event.key == pygame.K_c:
                    # C键:清空
                    ca.grid.fill(0)

        # 定时更新
        now = pygame.time.get_ticks()
        if now - last_update > UPDATE_DELAY:
            ca.update()
            last_update = now

        render(ca)
        pygame.display.flip()
        clock.tick(30)

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

运行说明

  1. 安装依赖pip install pygame numpy PyOpenGL
  2. 运行代码:直接执行即可
  3. 交互控制
    • 空格键:按85%/15%概率随机重置
    • R键:完全随机重置
    • C键:清空所有细胞

代码设计思路

  • NKS核心思想:从极简单的局部规则出发,观察全局涌现的复杂模式。当前使用的是经典康威生命游戏规则(三维推广),你可以自由修改 update() 方法中的规则逻辑,探索不同的NKS规则空间。
  • 三维网格:使用 numpy 存储 20x20x20 的0/1状态数组,邻居统计采用26邻域(周围所有相邻格子)。
  • 3D渲染:基于 PyOpenGL 绘制彩色立方体,颜色根据坐标位置从蓝到红渐变,方便观察结构分布。
  • 性能优化:通过 UPDATE_DELAY 控制演化速度,避免帧率过高导致卡顿。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值