As this linked Wikipedia page says:

"Most of the early algorithms were similar; they represented Life patterns as two-dimensional arrays in computer memory. Typically two arrays are used, one to hold the current generation, and one in which to calculate its successor. Often 0 and 1 represent dead and live cells respectively. A nested for-loop considers each element of the current array in turn, counting the live neighbours of each cell to decide whether the corresponding element of the successor array should be 0 or 1. The successor array is displayed. For the next iteration the arrays swap roles so that the successor array in the last iteration becomes the current array in the next iteration."

I derived the following super straightforward solution, didn't use other fancy tricks to clean the code or bit manipulation, although as the wikipedia page says: "A variety of minor enhancements to this basic scheme are possible..."

```
public void gameOfLife(int[][] board) {
int height = board.length, width = board[0].length;
int[][] next = new int[height][width];
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board[0].length; j++){
int liveCellsCount = 0;
//count all its live cells
if(j+1 < width && board[i][j+1] == 1) liveCellsCount++;//right cell
if(j-1 >= 0 && board[i][j-1] == 1) liveCellsCount++;//left cell
if(i+1 < height && board[i+1][j] == 1) liveCellsCount++;//down cell
if(i-1 >= 0 && board[i-1][j] == 1) liveCellsCount++;//up cell
if(i-1 >= 0 && j-1 >= 0 && board[i-1][j-1] == 1) liveCellsCount++;//up left cell
if(i-1 >= 0 && j+1 < width && board[i-1][j+1] == 1) liveCellsCount++;//up right cell
if(i+1 < height && j-1 >= 0 && board[i+1][j-1] == 1) liveCellsCount++;//down left cell
if(i+1 < height && j+1 < width && board[i+1][j+1] == 1) liveCellsCount++;//down right cell
if(board[i][j] == 1){
if(liveCellsCount > 3 || liveCellsCount < 2) {
next[i][j] = 0;
} else {
next[i][j] = 1;
}
} else if(board[i][j] == 0) {
if(liveCellsCount == 3){
next[i][j] = 1;
}
}
}
}
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board[0].length; j++){
board[i][j] = next[i][j];
}
}
}
```