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

复刻John Conway生命游戏异常:[2][1]细胞错误存活

生命游戏(Game of Life)Java实现的异常问题修复

问题描述

近期用Java复刻John Conway's生命游戏,测试阶段显示正常,但实际运行时出现异常:第3代中,索引为[2][1](右数第3个、上数第2个)的细胞在拥有4个邻居的情况下错误变为存活状态——根据规则,死细胞只有在拥有3个邻居时才会激活。

问题代码

public int getNeighbors(int x, int y) {
    int neighbors = (cells[y][x] == 1)? -1 : 0;
    
    for(int i = -1; i < 2; i++) {
        for(int j = -1; j < 2; j++) {
            if(x-j >= 0 && y-i >= 0 && x-j <=4 && y-i <=4) {
                neighbors += cells[y-i][x-j];
            }
        }
    }
        
    return neighbors;
}
    
public int nextCellGen(int x, int y) {
    int neighbors = getNeighbors(x, y);
    int newStatus = 0;
    
    if(neighbors < 2) {
        newStatus = 0;
    }
    if((neighbors == 2 || neighbors ==3) && cells[y][x] ==1) {
        newStatus =1;
    }
    if(neighbors >3) {
        newStatus =0;
    }
    if(neighbors ==3 && cells[y][x] ==0) {
        newStatus =1;
    }
    
    return newStatus;
}
    
public void nextFullGen() {
    for(int i =0; i <6; i++) {
        for(int j=0; j <6; j++) {
            newCells[i][j] = nextCellGen(j, i);
        }
    }
}

问题分析与修复

1. 邻居计数逻辑错误(核心问题)

getNeighbors方法存在两个致命问题:

  • 偏移方向完全搞反:循环变量i/j是坐标偏移量,但代码中用x-j/y-i计算邻居坐标,导致统计的是与预期完全相反的位置,直接造成邻居数量统计错误。
  • 边界判断错误:网格是6x6(索引0-5),但代码中判断上限为<=4,会漏掉最右列、最底行细胞的右侧/下侧邻居。

修复后的getNeighbors方法(更直观的实现,直接跳过当前细胞):

public int getNeighbors(int x, int y) {
    int neighbors = 0;
    // 遍历8个方向的邻居
    for(int i = -1; i < 2; i++) {
        for(int j = -1; j < 2; j++) {
            // 跳过当前细胞自身
            if(i == 0 && j == 0) continue;
            int neighborX = x + j;
            int neighborY = y + i;
            // 修正边界判断:6x6网格索引为0-5
            if(neighborX >= 0 && neighborY >= 0 && neighborX <= 5 && neighborY <= 5) {
                neighbors += cells[neighborY][neighborX];
            }
        }
    }
    return neighbors;
}

2. 细胞状态更新的条件覆盖风险

原nextCellGen的多个独立if会导致条件覆盖问题(比如后续条件会覆盖前面的结果),改用分支结构清晰区分活细胞/死细胞规则:

public int nextCellGen(int x, int y) {
    int neighbors = getNeighbors(x, y);
    int currentStatus = cells[y][x];
    
    if(currentStatus == 1) {
        // 活细胞规则:少于2个邻居或多于3个邻居死亡,否则存活
        return (neighbors < 2 || neighbors > 3)? 0 : 1;
    } else {
        // 死细胞规则:恰好3个邻居激活,否则保持死亡
        return neighbors == 3? 1 : 0;
    }
}

3. 下一代状态的同步问题

nextFullGen方法中生成newCells后,需要将其同步到cells数组,否则下一轮迭代会继续使用旧状态:

public void nextFullGen() {
    for(int i = 0; i < 6; i++) {
        for(int j = 0; j < 6; j++) {
            newCells[i][j] = nextCellGen(j, i);
        }
    }
    // 同步新状态到cells数组(需导入java.util.Arrays)
    cells = Arrays.copyOf(newCells, newCells.length);
    for(int k = 0; k < newCells.length; k++) {
        cells[k] = Arrays.copyOf(newCells[k], newCells[k].length);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 15:34:52