1、题目名称
Game of Life(康威生命游戏)
2、题目地址
https://leetcode.com/problems/game-of-life
3、题目内容
英文:
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
-
Any live cell with fewer than two live neighbors dies, as if caused by under-population.
-
Any live cell with two or three live neighbors lives on to the next generation.
-
Any live cell with more than three live neighbors dies, as if by over-population..
-
Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.
中文:
根据维基百科条目 Conway's Game of Life(康威生命游戏),康威生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
给出一个m*n的细胞矩阵,每个细胞都有一个初始状态:生存(1)或死亡(0)。每个细胞的变化都与它周围8个细胞有关,规则如下:
-
当前细胞为存活状态时,当周围存活细胞不到2个时, 该细胞变成死亡状态。(模拟生命数量稀少)
-
当前细胞为存活状态时,当周围有2个或3个存活的细胞时, 该细胞保持原样。
-
当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
-
当前细胞为死亡状态时,当周围恰好有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)
写一个函数,根据矩阵当前的状态,计算这个细胞矩阵的下一个状态。
4、解题方法
在不使用定义新矩阵的情况下,要想解决本问题就需要先定义一组中间状态,中间状态要求能看出一个单元格变化前后两方面的生死情况。Java代码如下:
/**
* @功能说明:LeetCode 289 - Game of Life
* @开发人员:Tsybius2014
* @开发时间:2015年10月8日
*/
public class Solution {
//死亡单位
final int DEAD = 0;
//存活单位
final int ALIVE = 1;
//变化情况:死亡→死亡
final int DEAD_TO_DEAD = 0;
//变化情况:存活→存活
final int ALIVE_TO_ALIVE = 1;
//变化情况:存活→死亡
final int ALIVE_TO_DEAD = 2;
//变化情况:死亡→存活
final int DEAD_TO_ALIVE = 3;
/**
* 判断某点在本轮变化前是否是死亡状态
* @param obj
* @return
*/
private boolean isAliveOld(int obj) {
if (obj == ALIVE_TO_ALIVE || obj == ALIVE_TO_DEAD) {
return true;
}
else {
return false;
}
}
/**
* 判断某点在本轮变化后是否是死亡状态
* @param obj
* @return
*/
private boolean isAliveNew(int obj) {
if (obj % 2 == 1) {
return true;
} else {
return false;
}
}
/**
* 生命游戏
* @param board
*/
public void gameOfLife(int[][] board) {
//输入合法性检查
if (board == null) {
return;
}
int height = board.length;
if (height == 0) {
return;
}
int width = board[0].length;
if (width == 0) {
return;
}
//考察所有的点,变化其生命状态
int counter = 0;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
//统计周边生命生存情况
counter = 0;
if (i > 0 && j > 0 && isAliveOld(board[i - 1][j - 1])) {
counter++;
}
if (i > 0 && isAliveOld(board[i - 1][j])) {
counter++;
}
if (i > 0 && j < width - 1 && isAliveOld(board[i - 1][j + 1])) {
counter++;
}
if (j > 0 && isAliveOld(board[i][j - 1])) {
counter++;
}
if (j < width - 1 && isAliveOld(board[i][j + 1])) {
counter++;
}
if (i < height - 1 && j > 0 && isAliveOld(board[i + 1][j - 1])) {
counter++;
}
if (i < height - 1 && isAliveOld(board[i + 1][j])) {
counter++;
}
if (i < height - 1 && j < width - 1 && isAliveOld(board[i + 1][j + 1])) {
counter++;
}
//根据指定点周边的生命生存情况决定当前点的变化
if (isAliveOld(board[i][j])) {
if (counter < 2) {
//1.存活单位周边的存活单位少于2个,该单位死亡
board[i][j] = ALIVE_TO_DEAD;
} else if (counter == 2 || counter == 3) {
//2.存活单位周边的存活单位有2-3个,该单位继续存活
board[i][j] = ALIVE_TO_ALIVE;
} else {
//3.存活单位周边的存活单位多余3个,该单位死亡
board[i][j] = ALIVE_TO_DEAD;
}
} else {
if (counter == 3) {
//4.死亡单位周边的存活单位恰好为3个,该单位变为存活状态
board[i][j] = DEAD_TO_ALIVE;
} else {
board[i][j] = DEAD_TO_DEAD;
}
}
}
}
//根据变换后的存活状态,重新赋予每个点的生死情况
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (isAliveNew(board[i][j])) {
board[i][j] = ALIVE;
} else {
board[i][j] = DEAD;
}
}
}
}
}
END