根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
- 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
- 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
- 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
- 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。
示例 1:
输入: “()”
输出: true
示例 2:
输入:
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
输出:
[
[0,0,0],
[1,0,1],
[0,1,1],
[0,1,0]
]
用面向对象的方法其实挺容易。还有就是理解提议规则,可以简化如下
设curCell
为当前细胞,其周边8个细胞活数量为liveCnt
,即
- liveCnt<2,无论原来的细胞死活,下一轮一定死
- liveCnt=2,下一轮的死活状态和当前死活状态一样,即不变
- liveCnt=3,无论原来的细胞死活,下一轮一定活
- liveCnt>3,无论原来的细胞死活,下一轮一定死
这样就简单了
1.定义细胞类Cell
/// <summary>
/// 细胞类
/// </summary>
public class Cell
{
/// <summary>
/// 当前细胞行数
/// </summary>
public int Row { get; set; }
/// <summary>
/// 当前细胞列数
/// </summary>
public int Col { get; set; }
/// <summary>
/// 是否存活
/// </summary>
/// <param name="preBoard"></param>
/// <returns></returns>
public bool IsLive(int[][] preBoard)
{
return preBoard[Row][Col] == 1;
}
/// <summary>
/// 致死
/// </summary>
/// <param name="board"></param>
public void Dead(ref int[][] board)
{
board[Row][Col] = 0;
}
/// <summary>
/// 复活
/// </summary>
/// <param name="board"></param>
public void Live(ref int[][] board)
{
board[Row][Col] = 1;
}
/// <summary>
/// 复制
/// </summary>
/// <param name="preBoard"></param>
/// <param name="board"></param>
public void Copy(int[][] preBoard, ref int[][] board)
{
board[Row][Col] = preBoard[Row][Col];
}
/// <summary>
/// 周围存货细胞数量
/// </summary>
/// <param name="board"></param>
/// <returns></returns>
public int GetLiveCnt(int[][] preBoard)
{
int liveCnt = 0;
for (int i = Row -1; i <= Row + 1 ; i++)
{
for (int j = Col - 1; j <= Col + 1; j++)
{
try
{
if (preBoard[i][j] == 1 && (Row != i || Col != j))
liveCnt++;
}
catch (IndexOutOfRangeException)
{
}
}
}
return liveCnt;
}
}
2.定义细胞类Cell
/// <summary>
/// 刷新下一个状态
/// </summary>
/// <param name="preBoard"></param>
/// <param name="board"></param>
/// <param name="row"></param>
/// <param name="col"></param>
private static void RefreshStatus(int[][] preBoard, ref int[][] board, int row, int col)
{
//当前细胞
Cell curCell = new Cell
{
Col = col,
Row = row
};
//获取周围细胞存活的个数
int liveCnt = curCell.GetLiveCnt(preBoard);
//如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡
if (liveCnt < 2)
{
curCell.Dead(ref board);
}
//如果活细胞周围八个位置有两个活细胞,则该位置活细胞仍然存活,死细胞仍死;
else if (liveCnt == 2)
{
curCell.Copy(preBoard, ref board);
}
//如果活细胞周围八个位置有三个活细胞,则该位置活细胞仍然存活,死细胞复活;
else if (liveCnt == 3)
{
//复活
curCell.Live(ref board);
}
//如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
else
{
curCell.Dead(ref board);
}
}
3.主方法遍历即可
public void GameOfLife(int[][] board)
{
int row = board.Length;
int col = board[0].Length;
int[][] preBoard = board; //保存当前细胞组状态
//初始化都为0,所以只需更新复活的位置
board = new int[row][];
for (int i = 0; i < row; i++)
{
board[i] = new int[col];
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
RefreshStatus(preBoard, ref board, i, j);
}
}
}