Question

I don't really know what's causing this problem but my program, which is supposed to be Conway's Game of Life, crashes after 2 generations, seemingly no matter what I do, and I've been trying for days to locate the error.

I've narrowed the cause down to a few possible areas--or at least, I think I have.

short numNeighbors(int x, int y) {
    short numNeighbors; 
    numNeighbors = 0;
    if(x > 0 && y > 0 && matrix[x][y] != null){
        if (matrix[x+1][y] == true) numNeighbors++;
        if (matrix[x][y+1] == true) numNeighbors++;
        if (matrix[x+1][y+1] == true) numNeighbors++;
        if (matrix[x][y-1] == true) numNeighbors++;
        if (matrix[x-1][y] == true) numNeighbors++;
        if (matrix[x+1][y-1] == true) numNeighbors++;
        if (matrix[x-1][y+1] == true) numNeighbors++;
        if (matrix[x-1][y-1] == true) numNeighbors++;
    }
    return numNeighbors;
}
//returns the number of neighbours that a coordinate has

I'm assuming that this section above checks outside of the boundaries of my 2D array, but that shouldn't be possible, because I took precautions to make sure that didn't happen. Even so, this is one possible cause.

void nextGen(){
    Boolean[][] newMatrix = new Boolean[rows()][cols()];

    for (int i = 1; i < cols()-1; i++){
        for (int j = 1; j < rows()-1; j++){
        //avoiding null pointer errors
            if (matrix[j][i] == null) matrix[j][i] = false;
            //if a cell has 3 neighbours, become or stay true
            if (numNeighbors(j, i) == 3) newMatrix[j][i] = true;
            //if it doesn't have 3 neighbours, become or stay false
            else newMatrix[j][i] = false;
        }
    }

    matrix = newMatrix;
}
//makes matrix represent the next generation

This is my next guess at a cause for the error, but I can't really tell what would be wrong, though.

    for (int j = 0; j < numGenerations; j++){
        JOptionPane.showMessageDialog(null,"generation " + (j+1) + ":\n\n" + myGrid.showGrid());
        myGrid.nextGen();
    }

I'm only posting the above because it calls the block above it, and I don't want to rule anything out.

I don't really know what else the problem could be, but just in case anyone wants to look at the full source code of my project, I've posted it on pastebin.

Was it helpful?

Solution

In nextGen you do:

 //avoiding null pointer errors
 if (matrix[j][i] == null) matrix[j][i] = false;

Do the same for all ifs in numNeighbors()

short numNeighbors(int x, int y) {
    short numNeighbors; 
    numNeighbors = 0;
    if(x > 0 && y > 0 && matrix[x][y] != null){
        if (matrix[j][i] != null && matrix[x+1][y] == true) numNeighbors++;
        if (matrix[j][i] != null && matrix[x][y+1] == true) numNeighbors++;
        if (matrix[j][i] != null && [x+1][y+1] == true) numNeighbors++;
        if (matrix[j][i] != null && matrix[x][y-1] == true) numNeighbors++;
        if (matrix[j][i] != null && matrix[x-1][y] == true) numNeighbors++;
        if (matrix[j][i] != null && matrix[x+1][y-1] == true) numNeighbors++;
        if (matrix[j][i] != null && matrix[x-1][y+1] == true) numNeighbors++;
        if (matrix[j][i] != null && matrix[x-1][y-1] == true) numNeighbors++;
    }
    return numNeighbors;
}

Or even better pre-instantiate all cells to false.

//Run in constructor
for(int i ..
   for(int j ..
      matrix[j][i] = false

OTHER TIPS

And actually, all blocks should be enclosed in curly braces. You'll save your tail many times if you take the time to do this. e.g.,

if (matrix[j][i] == null) {
   newMatrix[j][i] = false;
}

Edit 2
Your big if block is going to have boundary problems. Why not simply use nested for loops:

short numNeighbors(int x, int y) {
  short numNeighbors; 
  numNeighbors = 0;

  int xMin = Math.max(x - 1, 0);
  int xMax = Math.min(x + 1, MAX_X - 1); // MAX_X is a constant, number of columns
  int yMin = Math.max(y - 1, 0);
  int yMax = Math.min(y + 1, MAX_Y - 1); // ditto, number of rows

  for (int i = xMin; i <= xMax; i++) {
     for (int j = yMin; j <= yMax; j++) {
        if (i != x && j != y) {
           if (matrix[i][j]) {
              numNeighbors++;
           }
        }
     }
  }

  return numNeighbors;
}

And as mentioned elsewhere and in my comment, the array should be initialized to non-null values so there should be no need for a null check.

I will post another answer as I inspected your whole project.

void nextGen(){
    Boolean[][] newMatrix = new Boolean[rows()][cols()];

What you do where is creating an array of Boolean objects and not boolean primitives.

  • boolean primitives default to false
  • Boolean objects defaults to null

Java has something called autoboxing for primitives which can be tricky and hide this kind of "smal" differences which infact kan be realy significant as seen here,

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top