javaconways-game-of-life

Intro programming: Conways Game of Life


I have been working on this code for a long time and i can't seem to figure it out. The top portion of my code works to pre-populate the grid. but for some reason I cant get my image to move and to grow as its supposed to. Please Help Me!!

import java.util.Random;
public class Life {
    public static void main(String []args){

        //Declaring and initializing grid variables
        int gridSize = 200;
        int cellSize = 3;
        Grid grid = new Grid(gridSize, cellSize, "The Game of Life");
        grid.setDelay(10);

        Random r = new Random();
        int aliveColor = 1;
        int deadColor= 0;
        int aliveCells;
        int row = 0; 
        int column =  0;
        int val = grid.getPos(row,column);
        int generation;
        int aliveNeighbors;
        int cell;

        //loop statement pre-populating the grid
        for (row = 0; row <= gridSize-1; row++){
            for(column = 0; column <= gridSize-1; column++){
                if (r.nextInt(100) > 49){
                    grid.setPos(row,  column, aliveColor);
                }
                else
                    grid.setPos(row, column, deadColor);
            }
        }
        grid.initialize();


        //Loop executing the rules of the Game of Life
        do
        {
            row = 0;
            column = 0;
            generation = 0;
            while (row <= gridSize-1){
                while (column <= gridSize-1){
                    cell = grid.getPos(row, column);
                    aliveNeighbors = grid.matchingNeighbors(row, column,aliveColor);
                    if (cell == aliveColor)
                    {
                        if (aliveNeighbors == 2 || aliveNeighbors == 3){
                            val =1;
                            grid.setPos(row,  column,val);
                        }
                    }
                    else if (cell == deadColor)
                    {   
                        if (aliveNeighbors == 3){
                            val =1;
                            grid.setPos(row, column,val);
                        }
                    }
                    else{
                        val = 0;
                        grid.setPos(row,column,val);

                    }
                    column++;
                }   
                row++;
                grid.update();
            } 
            grid.update();
            generation++;
        } while (generation >= 0);
    }
}

EDIT

//Loop executing the rules of the Game of Life

    do
    {   
        row = 0;
        column = 0;
        generation = 0;
        while (row <= gridSize-1){
            while (column <= gridSize-1){
                cell = grid.getPos(row, column);
                aliveNeighbors = grid.matchingNeighbors(row, column,aliveColor);
                if (cell == aliveColor)
                {
                    if (aliveNeighbors == 2 || aliveNeighbors == 3){
                        val =1;
                        grid.setPos(row,  column,val);
                    }
                    if (aliveNeighbors ==1 || aliveNeighbors == 4){
                        val = 0;
                        grid.setPos(row,column,val);
                    }
                }
                else
                {
                    if (cell == deadColor)
                    {   
                        if (aliveNeighbors == 3){
                            val =1;
                            grid.setPos(row, column,val);
                        }
                        if (aliveNeighbors == 1 || aliveNeighbors == 2 || aliveNeighbors == 4){
                            val = 0;
                            grid.setPos(row, column, val);
                        }
                    }
                }   
                column++;
            }
            row++;
        } 
        grid.update();
        generation++;
    } while (generation >= 0);
}








    EDIT****
      do
    {   
        row = 0;
        column = 0;
        generation = 0;
        while (row <= gridSize-1){
            while (column <= gridSize-1){
                cell = grid.getPos(row, column);
                aliveNeighbors = grid.matchingNeighbors(row, column,aliveColor);
                if (cell == aliveColor)
                {
                    if (aliveNeighbors == 2 || aliveNeighbors == 3){
                        grid.setPos(row, column, aliveColor);
                    } else {
                        grid.setPos(row,column, deadColor); 
                    }
                }
                else
                {
                    if (cell == deadColor){ 
                        if (aliveNeighbors == 3){
                            grid.setPos(row, column,aliveColor);
                        } else {
                            grid.setPos(row,column,deadColor);
                        }
                    }
                }   
                column++;
            }
            row++;
        } 
        grid.update();
        generation++;
    } while (generation >= 0);
}

Solution

  • Two problems that I have noticed:

    1. You should only update the grid after you complete updating all the cells.
    2. Your indentation was off, and there was a } misplaced. After re-formatting, it can clearly be seen that you are not covering all the cases, so there are cells that do not get a new value. For example, if a cell is alive, you only handle the case when it has 2 or 3 neighbors, but there is no else to that if, and so, a live cell with 1 or 4 or more neighbors is never updated.

      You may think that somehow in that case the code falls through to the general "else", but in fact, it never gets there. All cell values are either "alive" or "dead". So a construct such as:

      if ( cell == aliveColor ) {
          // Handle alive cell
      } else if ( cell == deadColor ) {
          // Handle dead cell
      } else {
          // Handle all other cases - but there are none!
      }
      

      Is equivalent to:

      if ( cell == aliveColor ) {
         // Handle alive cell
      } else {
         // Handle dead cell
      }
      

      The original "else" is never reached because there is no other case than "aliveColor" and "deadColor".


    Response to your edit:

                if (cell == aliveColor)
                {
                    if (aliveNeighbors == 2 || aliveNeighbors == 3){
                        val =1;
                        grid.setPos(row,  column,val);
                    }
                    if (aliveNeighbors ==1 || aliveNeighbors == 4){
                        val = 0;
                        grid.setPos(row,column,val);
                    }
                }
    

    For some reason, you seem to think that there could be at most 4 neighbors to each cell. Look at the example cell in your lab document again:

    ⬜︎⬜︎⬛︎
    ⬛︎⬜︎⬛︎
    ⬛︎⬛︎⬜︎
    

    This cell has 5 dead neighbors, and 3 live ones. In fact, each cell can have up to 8 neighbors - the diagonal neighbors also count!

    But your rules were:

    1. If x is alive and has exactly 2 or 3 live neighbors, then x survives to the next generation. Otherwise it dies.
    2. If x is dead and has exactly 3 live neighbors, then x is alive in the next generation. Otherwise it remains dead

    This otherwise translates directly to else in programming. So instead of having a second if with the complementary condition (if there are 1, 4,5,6,7 or 8 live neighbors...), just give the first if an else:

                    if (aliveNeighbors == 2 || aliveNeighbors == 3) {
                        grid.setPos(row, column, aliveColor);
                    } else {
                        grid.setPos(row, column, deadColor);
                    }
    

    The same thing applies to the rules for a dead cell, of course.

    (Note that I also removed the val=1 and just used the value directly, val is superfluous. Also I used the names that explain what the value is rather than 1 and 0 (what if you want to change the game to work with green and red)?).


    One important thing that I didn't notice before:

    do
    {   
        row = 0;
        column = 0;
        generation = 0;
        while (row <= gridSize-1){
            while (column <= gridSize-1){
    

    You initialize both the row and the column to zero before the row loop.

    This means that at the end of the first row, column stays gridSize-1 and is not set to zero again. So in fact you are only updating one row and then only the last column of each of the other rows.

    It should be:

      do
    {   
        row = 0;
        generation = 0;
        while (row <= gridSize-1){
            column = 0;
            while (column <= gridSize-1){
    

    Or you could use a for loop:

    for ( row = 0; row < gridSize; row++ ) {
        for ( column = 0; column < gridSize; column++ ) {
            ...
    

    If you choose to do so, don't forget to remove the row++ and column++ from inside the loop body so that they are not incremented twice.