Home > front end >  Trying to implement Conway's Game of Life in Java but having trouble with counting the "li
Trying to implement Conway's Game of Life in Java but having trouble with counting the "li

Time:09-16

I'm a beginner in coding. I have this problem that I know already, but I can't seem to find the solution

Given a preset 5x5 2D array representing the board (. means dead cell and 0 means living cell. )

. . . . .
. . . . .
. . 0 . .
. . . . .
. . . . .

I have a method countLivingNeighbors that counts the "living" cells around a cell. When I visualize the number of living neighbors of each cell in a the same grid pattern, the expected output and the actual output are:

EXPECTED:           ACTUAL:
0 0 0 0 0           0 0 0 0 0
0 1 1 1 0           0 1 1 1 0
0 1 0 1 0           0 1 0 0 0
0 1 1 1 0           0 0 0 0 0
0 0 0 0 0           0 0 0 0 0

I know the problem is that the method countLivingNeighbors doesn't count a "living" cell if its position is on the left, above-right, above, or above-left of the current cell. But I'm pretty sure the logic of my code is alright, I think.

For reference, here's the code for the method:

// 'true' means living, 'false' means dead
static int countLivingNeighbors(boolean[][] board, int posX, int posY) {
       int counter = 0;

       // Iterate around the cell
       for (int j = -1; j <= 1; j  ) {
           if (posY   j < 0 || posY   j >= board.length) continue;
           for (int i = -1; i <= 1; i  ) {
               if (posX   i < 0 || posX   i >= board[0].length) continue;
               if (board[posY   j][posX   i])   counter;
           }
       }
       
       // It counts the current cell as well, so let's remove that.
       if (board[posY][posX]) --counter;
       return counter;

I don't think I have problems with the code except for this which stomps me for quite a while now. Any help is much appreciated.

Here's the current version of the entire code.

package GameOfLife;

import java.util.Random;

public class Main {

   public static void main(String[] args){
       int boardWidth = 5, boardHeight = 5;
       boolean[][] board = {{false, false, false, false, false},
                            {false, false, false, false, false},
                            {false, false, true , false, false},
                            {false, false, false, false, false},
                            {false, false, false, false, false}};

       renderBoard(board);

       System.out.println();

       board = getNextBoardState(board);
       renderBoard(board);
   }


   static boolean[][] createRandomBoard(int width, int height) {
       boolean[][] board = new boolean[height][width];

       for (int i = 0; i < height; i  ) {
           for (int j = 0; j < width; j  ) {
               switch (new Random().nextInt(2)) {
                   case 0 -> board[i][j] = false;
                   case 1 -> board[i][j] = true;
               }
           }
       }

       return board;
   }

   static void renderBoard(boolean[][] board) {
       for (boolean[] cellRows : board) {
           for (boolean cells : cellRows) {
               if (cells) System.out.print(" 0 ");
               else System.out.print(" . ");
           } System.out.println();
       }
   }

   static boolean[][] getNextBoardState(boolean[][] board) {
       boolean[][] nextBoard;
       nextBoard = board;

       for (int y = 0; y < board.length; y  ) {
           for (int x = 0; x < board[0].length; x  ) {
                int livingNeighbors = countLivingNeighbors(board, x, y);
                System.out.print(" "   livingNeighbors   " ");
                nextBoard[y][x] = setNextCellState(livingNeighbors, board[y][x]);
           } System.out.println();
       } System.out.println();

       return nextBoard;
   }

   static int countLivingNeighbors(boolean[][] board, int posX, int posY) {
       int counter = 0;

       for (int j = -1; j < 2; j  ) {
           if (posY   j < 0 || posY   j >= board.length) continue;
           for (int i = -1; i < 2; i  ) {
               if (posX   i < 0 || posX   i >= board[0].length) continue;
               if (board[posY   j][posX   i])   counter;
           }
       }

       if (board[posY][posX]) --counter;
       return counter;
   }

   static boolean setNextCellState(int livingNeighbors, boolean cellState) {
       if (cellState) {
           if (livingNeighbors <= 1 || livingNeighbors > 3) return false;
       } else {
           if (livingNeighbors == 3) return true;
       }

       return cellState;
   }
}

CodePudding user response:

In the getNextBoardState method you are assigning nextBoard = board.

static boolean[][] getNextBoardState(boolean[][] board) {
    boolean[][] nextBoard;
    nextBoard = board;

It's natural to think that this should copy all of the values in the board array into a new array called nextBoard. But in fact, it creates a new pointer called nextBoard, which points to the same array as board. This means that when you change a value in nextBoard, you are in fact changing the same value pointed to by board.

To get around this, make a method that copies values from the board into a new board. Here's a very simple example (which has some pitfalls of its own):

private static boolean[][] copyBoard(boolean[][] board) {
    boolean[][] newBoard = new boolean[board.length][board[0].length];
    for (int i = 0; i < board.length; i  ) {
        for (int j = 0; j < board[i].length; j  ) {
            newBoard[i][j] = board[i][j];
        }
    }
    return newBoard;
}

Then in getNextBoardState, replace

boolean[][] nextBoard;
nextBoard = board;

with

boolean[][] nextBoard = copyBoard(board);

You should get the result you expect:

0  0  0  0  0 
0  1  1  1  0 
0  1  0  1  0 
0  1  1  1  0 
0  0  0  0  0 

Note: the copyBoard method assumes that board always has at least one inner array (board[0]) and that all of board's inner arrays have the same length as the array at board[0].

  • Related