Search code examples
javasimplifyconways-game-of-life

How to simplify this Game of Life method that counts the number of neighbors a cell has?


This method checks if the cell is an edge cell (on a border) and then counts how many live neighbors it has. The value is then returned and used to determine if that cell lives or dies. This takes a lot of space and looks pretty ugly. Is there a way I can do all of this in a lot fewer lines?

// takes in board and checks a cell's neighbors, returning the number of living neighbors
// checks if a cell is on a border, therefore causing it to have less neigbors
public static int checkNeighbors(int[][] board, int i, int j)
{
    int count = 0;   // live neighbors of cell will be added here

    if(i - 1 < 0 && j - 1 < 0)   // in top left corner, only three neighbors
    {
        if(board[i][j + 1] == 1)
            count++;
        if(board[i + 1][j] == 1)
            count++;
        if(board[i + 1][j + 1] == 1)
            count++;
    }
    else if(i - 1 < 0 && j + 1 > width - 1)   // in top right corner, only three neighbors
    {
        if(board[i][j - 1] == 1)
            count++;
        if(board[i + 1][j] == 1)
            count++;
        if(board[i + 1][j - 1] == 1)
            count++;
    }
    else if(i + 1 > height - 1 && j - 1 < 0)   // in bottom left corner, only three neighbors
    {
        if(board[i][j + 1] == 1)
            count++;
        if(board[i - 1][j] == 1)
            count++;
        if(board[i - 1][j + 1] == 1)
            count++;
    }
    else if(i + 1 > height - 1 && j + 1 > width - 1)   // in bottom right corner, only three neighbors
    {
        if(board[i][j - 1] == 1)
            count++;
        if(board[i - 1][j] == 1)
            count++;
        if(board[i - 1][j - 1] == 1)
            count++;
    }
    else if(j - 1 < 0)   // on left border, only five neighbors
    {
        if(board[i - 1][j] == 1)
            count++;
        if(board[i - 1][j + 1] == 1)
            count++;
        if(board[i][j + 1] == 1)
            count++;
        if(board[i + 1][j + 1] == 1)
            count++;
        if(board[i + 1][j] == 1)
            count++;
    }
    else if(j + 1 > width - 1)   // on right border, only five neighbors
    {
        if(board[i - 1][j] == 1)
            count++;
        if(board[i - 1][j - 1] == 1)
            count++;
        if(board[i][j - 1] == 1)
            count++;
        if(board[i + 1][j - 1] == 1)
            count++;
        if(board[i + 1][j] == 1)
            count++;
    }
    else if(i - 1 < 0)   // on top border, only five neighbors
    {
        if(board[i][j - 1] == 1)
            count++;
        if(board[i - 1][j - 1] == 1)
            count++;
        if(board[i - 1][j] == 1)
            count++;
        if(board[i - 1][j + 1] == 1)
            count++;
        if(board[i][j + 1] == 1)
            count++;
    }
    else if(i + 1 > height - 1)   // on bottom border, only five neighbors
    {
        if(board[i][j - 1] == 1)
            count++;
        if(board[i + 1][j - 1] == 1)
            count++;
        if(board[i + 1][j] == 1)
            count++;
        if(board[i + 1][j + 1] == 1)
            count++;
        if(board[i][j + 1] == 1)
            count++;
    }
    else   // cell is not on any border, has full eight neighbors
    {
        if(board[i - 1][j - 1] == 1)
            count++;
        if(board[i - 1][j] == 1)
            count++;
        if(board[i - 1][j + 1] == 1)
            count++;
        if(board[i][j - 1] == 1)
            count++;
        if(board[i][j + 1] == 1)
            count++;
        if(board[i + 1][j - 1] == 1)
            count++;
        if(board[i + 1][j] == 1)
            count++;
        if(board[i + 1][j + 1] == 1)
            count++;
    }
    return count;
}

StackOverflow is telling me to add more details because my post is mostly code. I dont think any more details are required so I am typing this down here just to get rid of that error.


Solution

  • You can move your check into one place:

    public static int countNeighbours(int[][] board, int i, int j) {
        int count = 0;
        for (int x = -1; x <= 1; x++) {
            for (int y = -1; y <= 1; y++) {
                if ((x != 0 || y != 0) && checkCell(board, i + x, j + y)) {
                    ++count;
                }
            }
        }
        return count;
    }
    
    public static boolean checkCell(int[][] board,int x, int y) {
        return (x >= 0 && y >= 0 && x < width && y < height && board[x][y] == 1);
    }
    

    You could do something even shorter with Streams, but this is clearer if you aren't familiar with them.