```java
class Solution {
public void gameOfLife(int[][] board) {
//use -1 to indicate the cell lives but die at this generation
//use 2 to indicate the cell dies but live at this generation
int[][] shift = new int[][] { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 }, { 1, 1 }, { 1, -1 }, { -1, 1 },
{ -1, -1 } };
int m = board.length;
int n = board[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int cnt_live = 0;
for (int k = 0; k < 8; k++) {
int x = i + shift[k][0];
int y = j + shift[k][1];
if (x >= 0 && y >= 0 && x < m && y < n && Math.abs(board[x][y]) == 1) {
cnt_live++;
}
}
if (board[i][j] == 0 && cnt_live == 3)
board[i][j] = 2;
if (board[i][j] == 1 && (cnt_live > 3 || cnt_live < 2)) {
board[i][j] = -1;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == -1)
board[i][j] = 0;
if (board[i][j] == 2)
board[i][j] = 1;
}
}
return;
}
}
```