Game of Life, C checking life conditions

917 views Asked by At

I have been looking at this for a while and rewritten the code three times so far, this is what I have and what I do not understand.

I have a method which checks the neighborhood, through various print lines and my running through it, this works.

int getLiveCellCount(Generation *currentGeneration, int i, int j)
{
int liveCellCount = 0;
// check top row
if( i > 0 )
{
    if( j > 0 && currentGeneration->generation[i-1][j-1] == 'X' )
    {
        liveCellCount++;
    }
    if( currentGeneration->generation[i-1][j] == 'X' )
    {
        liveCellCount++;
    }
    if( j < currentCols && currentGeneration->generation[i-1][j+1] == 'X' )
    {
        liveCellCount++;
    }

}

// check mid row
if( j > 0 && currentGeneration->generation[i][j-1] == 'X' )
{
    liveCellCount++;
}
if( j < currentCols && currentGeneration->generation[i][j+1] == 'X' )
{
    liveCellCount++;
}

// check bottom row
if( i < currentRows )
{
    if( j > 0 && universe[i+1][j-1] == 'X' )
    {
        liveCellCount++;
    }
    if( currentGeneration->generation[i+1][j] == 'X' )
    {
        liveCellCount++;
    }
    if( j < currentCols && currentGeneration->generation[i+1][j+1] == 'X' )
    {
        liveCellCount++;
    }
}

return liveCellCount;
}

I have specific conditions in which a cell lives or dies, live cells contain X and dead cells are a blank space.

If the cell is alive:
   it dies if it has 0, 1, 4 or more living neighbours (starvation), or
   it lives if it has 2 or 3 living neighbours (balance).
If the cell is dead:
   it springs to life if it has exactly 3 neighbours (procreation).

I implement the code as follows:

for( i=0; i<currentRows; i++ )
        {
            for( j=0; j<currentCols; j++ )
            {
                int livingCells = 0;
                livingCells = getLiveCellCount(currentGeneration, i,j);
                if(universe[i][j] == 'X' )
                {
                    if( livingCells == 2 || livingCells == 3 )
                    {
                        universe[i][j] = 'X';
                    }
                    else
                    {
                        universe[i][j] = ' ';
                    }
                }
                else
                {
                    if( livingCells == 3 )
                    {
                        universe[i][j] = 'X';
                    }
                }
            }
        }

Know that universe[][] is a file scope variable, my idea with this code is read in the initial condition into universe, this works. I copy this array into an array of structs (storage for later and currently commented out). I scan the universe and check each cell for living cells in its neighborhood, based on that follow the rules above and edit the universe on an element by element basis. What am I missing in this? Somewhere a condition is not being read correctly by me and I can not see it.

I want to thank you all for the help you have given me! Like many of you mentioned I had over looked the small detail that each cell in the universe must be updated simultaneously! As I mentioned, I copy the current state of the universe into a 2d array in a struct and store it in an array for later use, using the current snapshot of the universe to count cell counts, then edit the universe works perfectly! Thank you so much!

2

There are 2 answers

4
Deepak On BEST ANSWER

I think you have two problems with your code:

  1. As @ogga said in comments you are not checking for upper bounds in getlivecellcounts. You checked for lower bounds in when you check i and j are more than 0 but you need to do this for upper bound too (just check that it does not goes more than size of array to check if cell is dead or alive).

  2. In your for loop I think you are counting the live cell count on the fly. The problem with this approach is when you are on some cell [x][y] and it is live and it has some z number of neighbors and you change it to dead cell and then move on to next cell. Which will give you incorrect number of neighbours at cell [x] [y+1] because you changed the status of cell x y already to new generation which is dead now and was alive before.

*Changing of cell should be done in same generation.

Other way could be you make a different 2d array and save the new version or new generation there and then copy to previous one once its complete. This way you will be changing generations all at once.

1
user3629249 On

in general,

1) the check for the state of neighbouring cells must always check that the cell being checked is within the bounds of the 2D array.

2) the same array cannot be used to update the target cell contents because that can change the neighbour count for when some neighbour cell becomes the target cell. The way around this is to keep two 2D arrays and use a pointer to switch to the latest version after all the updates have been applied.