康威生命遊戲

_Meriellan發表於2024-09-04

題目:康威生命遊戲
分類:陣列、矩陣、模擬
根據 百度百科 , 生命遊戲 ,簡稱為 生命 ,是英國數學家約翰·何頓·康威在 1970 年發明的細胞自動機。
給定一個包含 m × n 個格子的皮膚,每一個格子都可以看成是一個細胞。每個細胞都具有一個初始狀態: 1 即為 活細胞 (live),或 0 即為 死細胞 (dead)。每個細胞與其八個相鄰位置(水平,垂直,對角線)的細胞都遵循以下四條生存定律:
1.如果活細胞周圍八個位置的活細胞數少於兩個,則該位置活細胞死亡;
2.如果活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活;
3.如果活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡;
4.如果死細胞周圍正好有三個活細胞,則該位置死細胞復活;
下一個狀態是透過將上述規則同時應用於當前狀態下的每個細胞所形成的,其中細胞的出生和死亡是同時發生的。給你 m x n 網格皮膚 board 的當前狀態,返回下一個狀態。
示例 1:
輸入:board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
輸出:[[0,0,0],[1,0,1],[0,1,1],[0,1,0]]
示例 2:
輸入:board = [[1,1],[1,0]]
輸出:[[1,1],[1,1]]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 25
board[i][j] 為 0 或 1

思路

  • 源自題解,也是容易忽視的,導致後續資料被汙染,部分出錯;

此處複製一個newboard,所有的檢索均針對newborad[i][j],在本元素的值確認後賦給board[i][j]

  • 鑑於對每個元素來說,都要檢測8個鄰居,可以看作三行三列,除開自己,而這裡需要用本身來表示鄰居,明顯有-1、0、1的關係(行與列均是如此),所以可以共用一個偏移量skewing來表示鄰居的行與列,分別是

  • 根據規則對live++

  • 注意此時skewing[s]和skewing[t]代表的是偏移的量

    當skewing[s]和skewing[t]都為0時,我們實際上並沒有檢查任何鄰居。這種情況發生在當前細胞位於邊界或角落時,它只有1或2個鄰居。在這種情況下,我們不需要更新該細胞的狀態,因為它的鄰居數量已經符合上述規則。

  • 這裡區分一個經典出錯
    !((a == b) && (c == d)) 和 (a != b) && (c != d)

    • 對於 !((a == b) && (c == d)):
      此表示式取真的條件是當 a 不等於 b 或者 c 不等於 d。即如果兩對比較中至少有一對不相等,則此表示式為真。
      用邏輯表示式來表示就是: !((a == b) && (c == d)) 等價於 (a != b) || (c != d),根據德摩根定律。
    • 對於 (a != b) && (c != d):
      此表示式取真的條件是當 a 不等於 b 且 c 不等於 d。即兩對比較都必須不滿足相等關係,此表示式才為真。
      這兩個表示式雖然在某種程度上是邏輯等價的,但它們在具體實現上有著細微的差異。
/*java*/

class Solution {
    public void gameOfLife(int[][] board) {
        int m = board.length;
        int n = board[0].length;
        int live = 0;
        int[] skewing = {-1,0,1};
        int[][] newboard = new int[m][n];
        //i即newboard的行,j即newboard的列
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                newboard[i][j] = board[i][j];
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                live = 0; // 重置 live 計數器
				/*掃描8個元素*/
                for (int s = 0; s < 3; s++) {
                    for (int t = 0; t < 3; t++) {
                        if (!(skewing[s] == 0 && skewing[t] == 0)) {
                            int front = i + skewing[s];
                            int back = j + skewing[t];

                            if (front >= 0 && front < m && back >= 0 && back < n ) {
                                if(newboard[front][back] == 1)
                                    live++;
                            }
                        }
                    }
                }

                if (newboard[i][j] == 1) {
                    if (live < 2 || live > 3) {
                        board[i][j] = 0;
                    }
                } else if (live == 3) {
                    board[i][j] = 1;
                }
            }
        }
    }
}

相關文章