2016-11-29 4 views
2

が、私は自分自身でそれを実装するためにライフゲームを研究し、そしてルールを次の実装に出くわしたんだ:Java:ConwayのGame of Lifeを実装する方法は?

n個の細胞によってメートルでボードを考えると、各セルは、ライブの初期状態を持っています(1)または死んだ(0)。下に起因するかのように

  • 少ない2人のつよりライブ隣人を持つ任意の生細胞は、死ぬ:各セルは(Wikipediaの記事上方から見た)以下の4つの規則を使用して、その8つの近傍(水平、垂直、対角)と相互作用します-人口。
  • 2つまたは3つのライブネイバーが存在するライブセルは、次世代に存在します。
  • 過剰集団の場合のように、3つ以上のライブネイバーが存在するライブセルが死ぬ。
  • 正確に3つのライブネイバーを持つ死んだセルは、まるで再生によって生きているセルになります。

と実装(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,m、またはnを使用しようとすると、コードはArrayOutOfBoundsExceptionを返します。 (ループはマップの右端に四角形があることを "認識"していませんが、右隣の居住者を検索するべきではありません)。xyは単にループ制御変数ですターゲットの四角形を囲む有効な四角形を反復するために使用されます。

変数livesは、以下のループによっていくつのライブネイバーが検出されたかをカウントするプレースホルダーです。 liveNeighbors関数の戻り値ということで、これを推測したかもしれません。

例を見てみましょう。 liveNeighbors(board,9,9,0,2)と呼びます(boardはドライバで指定されたボードです)。あなたのボードは9×9の寸法を持っていますので、それらはmnです。この例では、02という正方形を調査しています(右に1を持っています)。偉大な、始めましょう。

i=0、そうx = Math.max(i - 1, 0) = Math.max(-1, 0) = 0(これはmax機能の理由を示しています。私達はちょうどint x=i-1を言っている場合、我々は、配列の範囲外であるx = -1で終わるだろう次は、我々は(X < = Math.minを評価します。 1、m-1)= Math.min(1,8)= 1。最後の列のセルを調べていた場合、この条件は配列の右端を強制していました。

yjという類似のロジックを残しておきます。

ループはに簡素化:(0,1),(0,2),(0,3),(1,1),(1,2),(1,3)

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

内側のループは、以下の(x,y)ペアで、6回実行されます。これらが私たちが調査している広場の隣人であること、そして広場そのものであることを確信してください。

このループの終わりに、livesを行うために、最終的なもの1.等しくなるように、これらの6つの正方形のファイブは、1を返す(1,2) 1つで、0が返され、正方形場合1によってlivesを減少させる、lives -= board[i][j] & 1;あります私たちは調査中で、そこに1が入っています。私たちの場合、それは(board[i][j] = 0)ではないので、0を引いて、1を残して返します。 liveNeighbors(board,9,9,0,2) = 1

私は一度か二度、後方xyを得ているかもしれないが、あなたは何が起こっているかを理解することができますので、うまくいけば、それは十分です。

+0

説明を誤解している可能性があります。解答を受け入れる前に、各反復で何が起こっているのかをコメントできますか?本当に物事をクリアするのに役立ちますか? –

+0

ありがとうございます。それは多くのことをクリアしました!ちょっとだけ質問があります。私はまだ命= board [i] [j]&1'部分を取得しません。私たちの広場には1つもありませんでしたか? '(1,2)? 1を引いた理由は何ですか?編集:ああ、それは私たちが周りの正方形を見つけているポイントそのものです、そしてそれが1ならば、1を引いて、正しい? –

+0

また、 'board [i] [j] >> = 1'の' board [x] [y]&1'と>> = 1の&1はどうしますか? –

関連する問題