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

两种生命游戏(Game of Life)实现结果迥异的原因排查

为什么两个生命游戏版本运行结果不同?

我来帮你分析一下核心原因——问题出在版本2的逻辑漏洞上,尤其是生命游戏规则里最容易被忽略的细节,加上初始化的遗漏,导致结果完全偏离预期。

首先先明确两个版本的设计差异:

  • 版本1用单个state字段记录细胞状态,先一次性计算所有细胞的邻居数,再统一更新状态
  • 版本2拆分出current(当前状态)和next(下一状态)字段,先计算所有细胞的next状态,再统一同步到current——这个设计其实更规范,避免更新时影响邻居计算,但代码里漏了关键逻辑。

核心问题1:版本2未处理「邻居数为2」的规则

回忆生命游戏的核心规则:

  1. 存活细胞:
    • 邻居数<2 → 死亡
    • 邻居数=2或3 → 保持存活
    • 邻居数>3 → 死亡
  2. 死亡细胞:
    • 邻居数=3 → 复活

看版本1的updateField:

void updateField(const int rows, const int cols, cell field[rows][cols]) {
    getNeighbours(rows, cols, field);
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            if(field[r][c].neighbours == 3) {
                field[r][c].state = ALIVE;
            } else if(field[r][c].neighbours <= 1) {
                field[r][c].state = DEAD;
            } else if(field[r][c].neighbours >= 4) {
                field[r][c].state = DEAD;
            }
            // 重点:当邻居数为2时,没有修改state,自动保持原状态,符合规则!
        }
    }
}

再看版本2的updateField:

void updateField(const int rows, const int cols, cell field[rows][cols]) {
    getNeighbours(rows, cols, field);
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            if(field[r][c].neighbours == 3) {
                field[r][c].next = ALIVE;
            } else if(field[r][c].neighbours <= 1) {
                field[r][c].next = DEAD;
            } else if(field[r][c].neighbours >= 4) {
                field[r][c].next = DEAD;
            }
            // 致命漏洞:邻居数为2时,next字段完全没赋值!
        }
    }
    // 同步next到current的代码
    ...
}

当邻居数为2时,next字段没有被设置值,会保留内存里的垃圾值(或者上一轮循环的残留值),同步到current后状态完全错误。

核心问题2:版本2未初始化next字段

版本2的initField只初始化了current字段,next字段完全没处理:

void initField(const int rows, const int cols, cell field[rows][cols]) {
    for (int r = 0 ; r < rows ; r++) {
        for (int c = 0 ; c < cols ; c++) {
            field[r][c].current = DEAD;
            // 缺失:field[r][c].next = DEAD;
        }
    }
    // 初始化活细胞时,也没同步设置next
    field[0][1].current = ALIVE;
    // 缺失:field[0][1].next = ALIVE;
    ...
}

这会导致第一次运行时next是随机的垃圾值,进一步加剧状态混乱。


修复版本2的步骤

1. 完善initField,初始化next字段

void initField(const int rows, const int cols, cell field[rows][cols]) {
    for (int r = 0 ; r < rows ; r++) {
        for (int c = 0 ; c < cols ; c++) {
            field[r][c].current = DEAD;
            field[r][c].next = DEAD; // 新增:初始化next状态
        }
    }
    // 初始化活细胞时同步设置next
    field[0][1].current = ALIVE;
    field[0][1].next = ALIVE;
    field[1][2].current = ALIVE;
    field[1][2].next = ALIVE;
    field[2][0].current = ALIVE;
    field[2][0].next = ALIVE;
    field[2][1].current = ALIVE;
    field[2][1].next = ALIVE;
    field[2][2].current = ALIVE;
    field[2][2].next = ALIVE;
}

2. 补全updateField中邻居数为2的逻辑

当邻居数为2时,next应该等于current的状态(保持原状态):

void updateField(const int rows, const int cols, cell field[rows][cols]) {
    getNeighbours(rows, cols, field);
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            if(field[r][c].neighbours == 3) {
                field[r][c].next = ALIVE;
            } else if(field[r][c].neighbours <= 1 || field[r][c].neighbours >=4) {
                field[r][c].next = DEAD;
            } else {
                // 邻居数为2,保持当前状态
                field[r][c].next = field[r][c].current;
            }
        }
    }
    // 同步next到current可以简化成一行
    for (int r = 0; r < rows; r++) {
        for(int c = 0; c < cols; c++) {
            field[r][c].current = field[r][c].next;
        }
    }
}

修复这两个问题后,版本2的运行结果就会和版本1完全一致了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:05:29