Search code examples
javaconways-game-of-life

Conway's Game of Life New Values


The question revolves around Conway's Game of Life and how to implement all the rules at the same time for the new generations. The game follows three rules for new generations, which are: a dead cell with exactly three live neighbors becomes live, a live cell with exactly one live neighbor becomes dead, and a live cell with more than three live neighbors becomes dead. The original generation is random. I think my problem, which is that my new generations are implementing the rules one at a time instead of all at once, is in this method:

public static int[][] nextgeneration(int[][] lastgen){
    int[][] nextgen = new int[lastgen.length][lastgen[0].length];
    for(int i = 0; i < lastgen.length; i++){
        for(int j = 0; j < lastgen[i].length; j++){
             if(aliveneighbors(lastgen, i, j) == 3){
                nextgen[i][j] = 1;
            }
        else if(aliveneighbors(lastgen, i, j) == 1){
                nextgen[i][j] = 0;
            }
        else if(aliveneighbors(lastgen, i, j) >  3){
                nextgen[i][j] = 0;
            }         
        else    nextgen[i][j] = lastgen[i][j];
        }
    }
    return nextgen;

Here's my full code just in case the problem was not in that method:

import java.util.Random;
public class Life {
public static int[][] origin(int a, int b) {
    int[][] randomMatrix = new int [a][b];
    for (int i = 0; i < a; i++) {
        for (int j = 0; j < b; j++) {
            Random random = new Random();
            int abc = random.nextInt(2);
        randomMatrix[i][j] = abc;
        }
    }
    return randomMatrix;
    }
public static void print(int[][] a) {
    for(int i = 0; i < a.length; i++){
        for(int j = 0; j < a.length; j++){
             System.out.print(a[i][j] + " ");
        }
        System.out.println();
    }
}
public static void show(int[][] b) {
    int N = b.length;
    StdDraw.setXscale(0, N-1);
    StdDraw.setYscale(0, N-1);
    for(int i = 0; i < b.length; i++){
        for(int j = 0; j < b.length; j++){
            if(b[i][j] == 1){
                StdDraw.setPenColor(StdDraw.RED);
                StdDraw.filledSquare(j, N-i-1, .5);

            }
            else if(b[i][j] == 0){
                StdDraw.setPenColor(StdDraw.BLACK);
                StdDraw.filledSquare((double)j, (double)-i, .5);
            }
        }
    }
}
public static int[][] nextgeneration(int[][] lastgen){
    int[][] nextgen = new int[lastgen.length][lastgen[0].length];
    for(int i = 0; i < lastgen.length; i++){
        for(int j = 0; j < lastgen[i].length; j++){
             if(aliveneighbors(lastgen, i, j) == 3){
                nextgen[i][j] = 1;
            }
        else if(aliveneighbors(lastgen, i, j) == 1){
                nextgen[i][j] = 0;
            }
        else if(aliveneighbors(lastgen, i, j) >  3){
                nextgen[i][j] = 0;
            }         
        else    nextgen[i][j] = lastgen[i][j];
        }
    }
    return nextgen;
}
public static int aliveneighbors(int[][] board, int x, int y){
    int count = 0;
    int up;
    int down;
    int left;
    int right;
    {
    if(x > 0)   
        up = x - 1;
    else
        up = board.length - 1;

    if(x < (board.length - 1))
        down = x + 1;
    else
        down = 0;

    if(y > 0) 
        left = y - 1;
    else
        left = board[x].length - 1;

    if(y < (board[x].length - 1))
        right = y + 1;
    else
        right = 0;
    //Count the live neighbors
    if(board[up][left] == 1)
        count++;

    if(board[up][y] == 1)
        count++;

    if(board[up][right] == 1)
        count++;

    if(board[x][left] == 1)
        count++;

    if(board[x][right] == 1)
        count++;

    if(board[down][left] == 1)
        count++;

    if(board[down][y] == 1)
        count++;

    if(board[down][right] == 1)
        count++;

    return count;
}
}
public static void main(String[] args) {
    int[][] b = origin(5, 5);
    int gens = 5;
    for (int i = 0; i < gens; i++) {
        System.out.println();
        int nextboard[][] = nextgeneration(b);
        b = nextboard; //I feel like this could be a problem as well
        System.out.println("Generation " + i + ":");
        print(nextgeneration(b));
        show(nextgeneration(b)); //This line of code seems useless
        //print(b); This one also seems useless and makes output confusing
        show(b);
    }
}
}

Here is what my output is:

Generation 0:
0 1 1 0 0 
0 1 1 0 0 
0 0 0 1 1 
1 1 0 1 1 
1 0 0 0 0 

Generation 1:
1 0 1 0 0 
1 1 0 0 0 
0 0 0 0 0 
0 1 1 1 0 
0 0 0 1 0 

Generation 2:
1 0 1 0 1 
1 1 0 0 0 
1 0 0 0 0 
0 0 1 1 0 
0 0 0 1 1 

Generation 3:
0 0 1 0 0 
0 0 0 0 0 
1 0 1 0 1 
0 0 1 1 0 
1 1 0 0 0 

Generation 4:
0 1 0 0 0 
0 1 0 1 0 
0 1 1 0 1 
0 0 1 1 0 
0 1 0 1 0 

I expect something like this:

Generation 0:
0 1 1 0 0 
0 1 1 0 0 
0 0 0 1 1 
1 1 0 1 1 
1 0 0 0 0 

Generation 1:
0 1 1 0 0 
0 1 0 0 0 
1 0 0 0 1 
1 1 1 1 1 
1 1 0 0 0 

Generation 2:
0 1 1 0 0 
1 1 1 0 0 
1 0 0 0 1 
0 0 1 1 1 
1 0 0 1 0

Also on my animation of the game the alive cells stay alive in the animation, which should not be happening. That's not my main problem, but if you know how to fix that it would also be helpful.


Solution

  • Your output looks fine to me. Pay attention, that you actually do "wrap-around" of the borders, so this

    Generation 0:
    0 1 1 0 0 
    

    has this as a upper border:

    1 0 0 0 0 
    

    and a left border:

    0
    0
    1
    1
    0
    

    For calculations it looks like:

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

    So this output:

    Generation 1:
    1 0 1 0 0 
    1 1 0 0 0 
    

    Is correct for the wrap-around. From the expected result, however, it looks you want to treat it as a actual border. I mean:

    010

    000

    with x=1, y=0, has only 5 neighbours.

    In that case you need something like this:

        public static int aliveneighbors(int[][] board, int x, int y){
        int width = board.length;
        int height = board[0].length;
        int count = 0;
         
         
        boolean isNotLower =  (y-1) >= 0;
        boolean isNotUpper = (y+1) < height;
            
        if (x-1 >= 0) {
            
           if( isNotLower && (board[x-1][y-1] == 1) )
            count++;
           if(board[x-1][y] == 1)
            count++;
           if(isNotUpper && (board[x-1][y+1] == 1) )
            count++;            
        }
        
        if (x+1 < width) {
           if( isNotLower && (board[x+1][y-1] == 1) )
            count++;
           if(board[x+1][y] == 1)
            count++;
           if( isNotUpper && (board[x+1][y+1] == 1) )
            count++;            
        }
        
        if( isNotUpper && (board[x][y+1] == 1) )
            count++;
        if(isNotLower && (board[x][y-1] == 1) )
            count++;
            
         return count;
    }