【问题标题】:Java: How to implement Conway's Game of Life?Java:如何实现康威的生命游戏?
【发布时间】:2017-04-14 00:21:09
【问题描述】:

我正在研究康威的生命游戏以自己实现它,并遇到了以下带有规则的实现:

给定一个有 m x n 个单元格的棋盘,每个单元格都有一个初始状态活 (1) 或死 (0)。每个单元格与其八个邻居(水平、垂直、对角线)使用以下四个规则(取自上述维基百科文章)进行交互:

  • 任何活细胞少于两个的活细胞都会死亡,好像是由于人口不足造成的。
  • 任何有两三个活邻居的活细胞都可以传给下一代。
  • 任何有超过三个活邻居的活细胞都会死亡,就好像人口过剩一样。..
  • 任何只有三个活邻居的死细胞都会变成活细胞,就像通过繁殖一样。

以及实现(https://discuss.leetcode.com/topic/29054/easiest-java-solution-with-explanation):

public void gameOfLife(int[][] board) {
    if (board == null || board.length == 0) return;
    int m = board.length, n = board[0].length;

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            int lives = liveNeighbors(board, m, n, i, j);

            // In the beginning, every 2nd bit is 0;
            // So we only need to care about when will the 2nd bit become 1.
            if (board[i][j] == 1 && lives >= 2 && lives <= 3) {  
                board[i][j] = 3; // Make the 2nd bit 1: 01 ---> 11
            }
            if (board[i][j] == 0 && lives == 3) {
                board[i][j] = 2; // Make the 2nd bit 1: 00 ---> 10
            }
        }
    }

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            board[i][j] >>= 1;  // Get the 2nd state.
        }
    }
}

public int liveNeighbors(int[][] board, int m, int n, int i, int j) {
    int lives = 0;
    for (int x = Math.max(i - 1, 0); x <= Math.min(i + 1, m - 1); x++) {
        for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, n - 1); y++) {
            lives += board[x][y] & 1;
        }
    }
    lives -= board[i][j] & 1;
    return lives;
}

还有司机:

public static void main(String args[]) {
    GameOfLife gl = new GameOfLife();

    int[][] board = {
                {0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 1, 0, 0, 0, 0, 0},
                {0, 1, 0, 1, 0, 0, 0, 0, 0},
                {0, 0, 1, 1, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0},
                {0, 0, 0, 0, 0, 0, 0, 0, 0}
            };

    gl.gameOfLife(board);
}

我的问题是,liveNeighbors() 中的 xy 代表什么?不明白为什么需要Math.min()Math.max()。另外,lives 是否代表板上初始化生命的数量?

【问题讨论】:

    标签: java algorithm bit


    【解决方案1】:

    给定的代码使用minmax 函数将搜索限制为数组中的有效条目。如果不这样做,代码将在尝试使用 -1mn 作为数组索引时返回 ArrayOutOfBoundsException。 (循环不“知道”给定地图右边缘的正方形,它不应该在更右边搜索活着的邻居;这些函数编码了这一事实。)xy 只是循环控制变量,用于迭代目标方块周围的有效方块。

    至于lives 变量,它是一个占位符,用于计算下面的循环找到了多少活邻居。您可能已经猜到了,因为它是 liveNeighbors 函数的返回值。

    让我们举个例子。我们将调用liveNeighbors(board,9,9,0,2),其中board 是驱动程序中提供的板。您的棋盘尺寸为 9x9,所以我们通过的是 mn,在我们的示例中,我们正在调查位于 0,2 的正方形,这是第三行中的第一个条目(其中右侧有一个1)。太好了,让我们开始吧。

    i=0,所以x = Math.max(i - 1, 0) = Math.max(-1, 0) = 0(这说明了max函数的原因:如果我们刚才说int x=i-1,我们最终会得到x = -1,它超出了数组的范围。下一步我们计算 x

    我将把涉及yj 的类似逻辑留给你。

    循环简化为:

    for (int x = 0; x <= 1; x++) {
        for (int y = 1; y <= 3; y++) {
            lives += board[x][y] & 1;
        }
    }
    

    内部循环将运行六次,使用以下 (x,y) 对:(0,1),(0,2),(0,3),(1,1),(1,2),(1,3)。说服自己这些是我们正在调查的广场的邻居,以及广场本身。

    这六个方块中有五个将返回0(1,2) 处的一个返回1,因此在此循环结束时,lives 将等于1。最后要做的是lives -= board[i][j] &amp; 1;,即如果我们正在调查的正方形中有 1,则将 lives 减少 1。在我们的例子中,它不是 (board[i][j] = 0),所以我们减去 0,剩下 1,我们返回。 liveNeighbors(board,9,9,0,2) = 1

    我可能已经将xy 倒退了一次或两次,但希望这已经足够让您了解发生了什么。

    【讨论】:

    • 我可能误解了实现,为了澄清,在我接受/赞成答案之前,你能评论一下每次迭代发生了什么吗?真的会帮助解决问题。
    • 非常感谢。这澄清了很多事情!还有几个问题。我仍然没有得到lives -= board[i][j] &amp; 1 部分。我们的广场上不是有一个 1 吗?在(1,2)?减去1的原因是什么?编辑:啊,这就是我们在周围找到正方形的点本身,如果它本身是 1,我们减去 1,对吗?
    • 另外,board[x][y] &amp; 1 中的 & 1 和 board[i][j] &gt;&gt;= 1 中的 >>=1 是做什么的?
    • 正确,因为循环也包含他们正在调查的方格,如果那个方格包含 1(一个方格不是它自己的邻居),我们减去 1。我们正在摆脱您最初的问题,进入一个您可以进行更多研究或提出其他问题的空间,但&amp; 是按位与运算符,&gt;&gt;= 是按位移位赋值运算符 (docs.oracle.com/javase/tutorial/java/nutsandbolts/…) .
    • 抱歉做了研究,但仍然没有得到按位运算符。在&amp;&gt;&gt;= 的情况下,它们是如何工作的?不应该只是&gt;&gt;吗?如果你不介意你能像以前一样为每个人提供一个小例子吗?真正帮助并保证这些将是最后一个问题:D
    猜你喜欢
    • 1970-01-01
    • 2021-02-28
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 2010-09-07
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多