2016-11-29 109 views
2

我学习生活的康威的游戏来实现它在我自己的,和整个以下实现的规则来:Java:如何实施康威的人生游戏?

由N个单元给定板有m个,每个单元都有活的初始状态(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是否代表董事会初始化的生命数量?

回答

3

给定的代码使用minmax函数将搜索限制为数组中的有效条目。如果没有这样做,代码将在尝试使用-1,mn作为数组索引时返回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 < = Math.min( i + 1,m - 1)= Math.min(1,8)= 1。如果我们正在调查最后一列中的单元格,则此条件会强制数组的右边缘。

我会给你留下类似的逻辑,涉及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)。相信这些是我们正在调查的广场的邻居,以及广场本身。

这六个平方五将在(1,2)返回1返回0,用一个,所以在这个循环结束,lives将等于1的最后一件事做的是lives -= board[i][j] & 1;,从而降低lives 1如果正方形我们正在调查中有一个1。在我们的情况下,它不会(board[i][j] = 0),所以我们减去0,留下1,我们返回。 liveNeighbors(board,9,9,0,2) = 1

我可能已经将xy倒退一次或两次,但希望这足以让您了解正在发生的事情。

+0

我误解实施的可能性,为了澄清,在我接受/赞成答案之前,您能评论每次迭代发生了什么吗?真的有助于清理事情。 –

+0

非常感谢。这清理了很多东西!还有几个问题。我仍然没有得到'生命' - 板子[i] [j]&1'部分。我们的广场没有1个?在'(1,2)'?减1的原因是什么?编辑:啊,这是我们正在寻找周围的方格本身,如果这本身是1,我们减去1,对吗? –

+0

另外,board [i] [j] >> = 1'中的board [x] [y]&1'和>> = 1中的&1是做什么的? –