You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简洁检查二维列表中细胞邻居数,实现边缘循环边界

元胞自动机循环边界邻居计数的简洁实现

问题描述

编写元胞自动机时,细胞存活(值为1)的概率随邻居数量增加而提升,但检查棋盘边缘或角落细胞的邻居数时会报错——比如无法访问最右侧细胞右侧的细胞状态。希望实现循环边界(即最右侧的右侧对应最左侧,最底部的底部对应最顶部),但不想通过大量位置判断来实现(这会让amt()函数代码量激增约9倍,过于冗余),需要更简洁的实现方式。

解决方案

核心思路是用取模运算处理循环边界:对偏移后的行列索引取棋盘的尺寸模,自动将超出边界的索引映射到对面的有效索引,无需任何位置判断。具体步骤:

  • 定义所有8个邻居的行列偏移量列表
  • 遍历每个偏移量,计算邻居的行列索引((col + dc) % csize、(row + dr) % rsize)
  • 统计所有存活邻居的数量

这种方式代码简洁,且能完美处理边缘、角落的循环边界问题。

修改后的完整代码

from random import randint

board = []
csize = 69
rsize = 69

# 初始化棋盘
for col in range(csize):
    board.append([])
    for row in range(rsize):
        board[col].append(1 if col == 0 else 0)

def ranize():
    for col in range(csize):
        for row in range(rsize):
            board[col][row] = randint(0, 1)

def check():
    for col in range(csize):
        for row in range(rsize):
            if board[col][row] == 1:
                return True
    return False

def show():
    loc = "\n"
    for col in range(csize):
        for row in range(rsize):
            if board[col][row] == 1:
                loc += "@ "
            else:
                loc += f"{amt(col, row)} "
        loc += "\n"
    print(loc, end="\r")

def amt(col, row):
    neighbor_count = 0
    # 定义8个邻居的行列偏移量
    offsets = [(-1, -1), (-1, 0), (-1, 1),
               (0, -1),          (0, 1),
               (1, -1),  (1, 0), (1, 1)]
    for dc, dr in offsets:
        # 取模运算实现循环边界
        neighbor_col = (col + dc) % csize
        neighbor_row = (row + dr) % rsize
        if board[neighbor_col][neighbor_row] == 1:
            neighbor_count += 1
    return neighbor_count

def onestep():
    if not check():
        input("所有细胞已死亡,按回车键随机初始化棋盘: ")
        ranize()
    # 先创建新棋盘存储状态,避免遍历中覆盖原状态导致错误
    new_board = [[0 for _ in range(rsize)] for _ in range(csize)]
    for col in range(csize):
        for row in range(rsize):
            neighbors = amt(col, row)
            ranum = randint(0, 8)
            if board[col][row] == 1:
                new_board[col][row] = 0 if (8 - neighbors) > ranum else 1
            else:
                new_board[col][row] = 1 if neighbors > ranum else 0
    # 更新全局棋盘
    global board
    board = new_board

while True:
    show()
    onestep()

额外说明

原代码的onestep()函数存在逻辑问题:直接在遍历过程中修改board会导致后续细胞的邻居计数基于已修改的状态,而非初始状态。修改后的代码先创建new_board存储新状态,遍历完成后再替换原棋盘,保证每一步的状态更新基于上一步的完整棋盘。

内容的提问来源于stack exchange,提问作者aecy four

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 15:04:56