Java实现康威生命游戏:存活邻居计数异常问题求助
康威生命游戏Java实现邻居计数错误问题
我是编程新手,在Java中实现康威生命游戏时遇到了邻居计数错误的问题。已知初始5x5棋盘如下(.代表死亡细胞,0代表存活细胞):
. . . . . . . . . . . . 0 . . . . . . . . . . . .
我编写了countLivingNeighbors方法统计单个细胞周围的存活邻居数量,但可视化邻居数量后,结果不符合预期:
EXPECTED: ACTUAL: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
我发现countLivingNeighbors无法正确统计当前细胞左侧、左上、上方、右上方向的存活细胞,但自认为代码逻辑正确,希望得到帮助。
以下是完整的当前代码版本:
package GameOfLife; import java.util.Random; public class Main { public static void main(String[] args){ int boardWidth = 5, boardHeight = 5; boolean[][] board = {{false, false, false, false, false}, {false, false, false, false, false}, {false, false, true , false, false}, {false, false, false, false, false}, {false, false, false, false, false}}; renderBoard(board); System.out.println(); board = getNextBoardState(board); renderBoard(board); } static boolean[][] createRandomBoard(int width, int height) { boolean[][] board = new boolean[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { switch (new Random().nextInt(2)) { case 0 -> board[i][j] = false; case 1 -> board[i][j] = true; } } } return board; } static void renderBoard(boolean[][] board) { for (boolean[] cellRows : board) { for (boolean cells : cellRows) { if (cells) System.out.print(" 0 "); else System.out.print(" . "); } System.out.println(); } } static boolean[][] getNextBoardState(boolean[][] board) { boolean[][] nextBoard; nextBoard = board; for (int y = 0; y < board.length; y++) { for (int x = 0; x < board[0].length; x++) { int livingNeighbors = countLivingNeighbors(board, x, y); System.out.print(" " + livingNeighbors + " "); nextBoard[y][x] = setNextCellState(livingNeighbors, board[y][x]); } System.out.println(); } System.out.println(); return nextBoard; } static int countLivingNeighbors(boolean[][] board, int posX, int posY) { int counter = 0; for (int j = -1; j < 2; j++) { if (posY + j < 0 || posY + j >= board.length) continue; for (int i = -1; i < 2; i++) { if (posX + i < 0 || posX + i >= board[0].length) continue; if (board[posY + j][posX + i]) ++counter; } } if (board[posY][posX]) --counter; return counter; } static boolean setNextCellState(int livingNeighbors, boolean cellState) { if (cellState) { if (livingNeighbors <= 1 || livingNeighbors > 3) return false; } else { if (livingNeighbors == 3) return true; } return cellState; } }
问题分析与解决方案
问题根本不在countLivingNeighbors方法里,而是在getNextBoardState方法中:你直接将nextBoard赋值为board,这意味着两者指向同一个二维数组对象。当你修改nextBoard[y][x]时,实际上是在修改原board数组的内容,后续的countLivingNeighbors调用会读取到已经被修改过的细胞状态,导致邻居计数错误。
比如初始中间的存活细胞(坐标2,2)会因为邻居数不足被设置为死亡,当计算下方细胞(3,2)的邻居时,原中间细胞已经变成死亡状态,所以统计不到它,导致实际输出第三行之后的邻居数都是0。
修改方式:在getNextBoardState方法中创建一个全新的二维数组作为nextBoard,而非直接引用原数组:
static boolean[][] getNextBoardState(boolean[][] board) { // 创建和原数组大小一致的新数组 boolean[][] nextBoard = new boolean[board.length][board[0].length]; for (int y = 0; y < board.length; y++) { for (int x = 0; x < board[0].length; x++) { int livingNeighbors = countLivingNeighbors(board, x, y); System.out.print(" " + livingNeighbors + " "); nextBoard[y][x] = setNextCellState(livingNeighbors, board[y][x]); } System.out.println(); } System.out.println(); return nextBoard; }
这样修改后,所有邻居计数都会基于原数组的初始状态计算,不会因为提前修改细胞状态干扰后续计算,邻居计数结果就能和预期一致。
内容的提问来源于stack exchange,提问作者Eugene Olete
相关产品推荐
相关产品推荐

