289. Game of Life

1、題目編程

  一、審題spa

    

  二、分析code

    編程實現  「LIFE」 這個遊戲:blog

      ①、若 m 的周圍8個鄰居細胞中存活的細胞數 < 2,則此細胞從存活狀態變爲死亡狀態;遊戲

      ②、若 m 的周圍8個鄰居細胞中存活的細胞數 = 2 或 = 3,則此細胞從存活狀態變爲存活狀態;ip

      ③、若 m 的周圍8個鄰居細胞中存活的細胞數 > 3,則此細胞從存活狀態變爲死亡狀態;it

      ③、若 m 的周圍8個鄰居細胞中存活的細胞數 = 3,則此細胞從死亡狀態變爲存活狀態;  io

    只能一次性更新全部的細胞的狀態,不能用改變後的狀態來判斷後邊的細胞的狀態。class

    其中 1表明存活狀態,0 表明死亡狀態。循環

 

2、解答

  一、思路

   方法1、

  

   ①、採用兩個 bit 位來表示狀態。剛開始,全部細胞所有是 00 或者 01;

   ②、注意狀態 1 與狀態 2 是獨立的。

   ③、全部的細胞是同時從狀態 1 變爲狀態 2的。

   ④、計算全部細胞在未變化以前的全部鄰居細胞的狀態,並記錄此細胞將要變化的狀態2。

   ⑤、由於狀態 2 默認爲 0,即死亡狀態,故不須要考慮狀態轉變: 01 --> 00

   ⑥、最終,經過  >> 1 向右移動一位,刪除全部細胞的狀態 1.

   ⑦、每個細胞的狀態 2 的計算方法:

      01 --> 11: 當 board == 1 而且 2 <= lives && lives <= 3;

      00 --> 10: 當 board == 0 而且 lives == 3。

   ⑧、獲取當前的細胞的狀態:  board[i][j] & 1

   ⑨、獲取細胞將要變化的狀態: board[i][j] >> 1

 1     public void gameOfLife(int[][] board) {
 2         if(board == null || board.length == 0)
 3             return;
 4         int m = board.length, n = board[0].length;
 5         
 6          // In the beginning, every 2nd bit is 0;
 7         // So we only need to care about when will the 2nd bit become 1.
 8         for(int i = 0; i < m; i++) {
 9             for (int j = 0; j < n; j++) {
10                 int lives = liveNeighbors(board, m, n, i, j);
11                 if(board[i][j] == 1 && 2 <= lives && lives <= 3)
12                     board[i][j] = 3;    // Make the 2nd bit 1: 01 ---> 11
13                 if(board[i][j] == 0 && lives == 3)
14                     board[i][j] = 2;    // Make the 2nd bit 1: 00 ---> 10
15             }
16         }
17         
18         for(int i = 0; i < m; i++)
19             for (int j = 0; j < n; j++) 
20                 board[i][j] >>= 1;
21     }
22     
23     private int liveNeighbors(int[][] board, int m, int n, int i, int j) {
24         int lives = 0;
25         for(int x = Math.max(i - 1, 0); x <= Math.min(i + 1, m - 1); x++) {
26             for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, n - 1); y++) {
27                 lives += board[x][y] & 1;
28             }
29         }
30         lives -= board[i][j] & 1;
31         return lives;
32     }

 

  方法2、

    能夠經過值不是 0 和 1 的兩個常量記錄此細胞將要變化的狀態。

    從而不影響統計出其餘細胞的周圍的存活細胞數。

    最終在循環給元素賦更新的值。

 1     int live = 3;
 2     int die = 2;
 3     public void gameOfLife2(int[][] board) {
 4         if(board == null || board.length == 0)
 5             return;
 6         int rows = board.length, cols = board[0].length;
 7         // we only flip the 1 to die and 0 to live
 8         // so when we find a die around, it must be a previous 1
 9         // then we can count the 1s without being affected
10         for (int i = 0; i < rows; i++) {
11             for (int j = 0; j < cols; j++) {
12                 int around = countLive(i, j, board);
13                 if(board[i][j] == 0 && around == 3)
14                     board[i][j] = live;
15                 else if(board[i][j] == 1) {
16                     if(around == 2 || around == 3)
17                         continue;
18                     if(around < 2 || around > 3)
19                         board[i][j] = die;
20                 }
21             }
22         }
23         for (int i=0;i<rows;i++){
24             for (int j=0;j<cols;j++){
25              if (board[i][j] == die)
26                  board[i][j] = 0;
27              if (board[i][j] == live)
28                  board[i][j] = 1;
29             }
30         }
31     }
32     
33     private int countLive(int i, int j, int[][] board) {
34         int count = 0;
35         int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
36         
37         for (int[] dir:dirs){
38             int x = i+dir[0];
39             int y = j+dir[1];
40             
41             if (x>=0 && y>=0 && x < board.length && y<board[0].length ){
42                 
43                 if (board[x][y] == 1 || board[x][y] == die)
44                     count ++;
45             }
46         }
47         
48         return count;
49     }
相關文章
相關標籤/搜索