Game of Life

Last updated at 20 September 2020 at 5:12pm


The game of life is cellular automaton by John Conway that simulates the birth and death of cells. It is made up by a collection of cells, the universe, that based on a some rules can either give birth, die or survive.

A cell is either dead or alive. Each cell has eight neighbors. In each tick the following happens :

  1. Any cell with less than two live neighbors dies, underpopulation.
  2. Any cell with 2 or 3 neighbors survives.
  3. Any cell with more that 3 neighbors dies, overpopulation.
  4. A dead cell with three neighbors becomes alive.

Implementation

We start of by creating some data structures.

#include <limits.h>

int grid[INT_MAX][INT_MAX];
int neighbors[INT_MAX][INT_MAX];

The universe is a 2D array grid. Each item in the grid is either 0 or 1 dead or alive respectively. neighbors is also a 2D array that will hold the number of neighbors in each cell. So if neighbors[2][2] = 4 then that means that grid[2][2] has 4 live neighbors.

I split the logic into two parts,

  1. Determining number neighbors of each cell
  2. Populating the universe based on the first part

1. Determining the number of neighbors

A cell as mentioned has eight neighbors,

Neighbours

To determine the number of neighbors for each cell, we’ll loop through each value of the grid to and check the status of its neighbors.

int rows = (sizeof(grid)/ sizeof(int)) / INT_MAX;

for(int i = 0; i < rows ; i ++)
{
    for(int j = 0; j < rows; j++)
    {
        int number_of_neighbours = 0;
        int x, y;
        
        ...
    }
}

This will loop through the grid. We now need to check if the status of the neighbors of that cell and increment number_of_neighbors.

To check the status of the neighbors we read directly from the grid array by adding or subtracting from values i and j as shown below.

Continuing inside the loop :

// Neighbor 1
x = i-1; y = j-1;
if(grid[x][y] == 1) { number_of_neighbours ++; } 

// Neighbor 2
x = i; y = j-1;
if(grid[x][y] == 1) { number_of_neighbours ++; } 

// Continue for neighbors 3 - 8
...

neighbors[i][j] = number_of_neighbours;

You can continue for the rest of the neighbors and then store the number of neighbors in the neighbors array.

Populate grid based on neighbors

Now that we have the number of neighbors of each cell we can now proceed to determine the next state of each cell based on the rules of the game.

Again we’ll create a new loop to go through the grid :

int rows = (sizeof(grid)/ sizeof(int)) / INT_MAX;

for(int i = 0; i < rows ; i ++)
{
    for(int j = 0; j < rows; j++)
    {
        ...
    }
}

Then proceed to get the status of that cell from the value of grid[i][j], dead or alive, and the number of neighbors it has from neighbors[i][j].

int status = grid[i][j];
int number_of_neighbors = neighbors[i][j];

Finally we handle the rules of the game :

if(status == 1) {
    if(number_of_neighbors < 2) // Under population :(
        grid[i][j] = 0;
    else if(number_of_neighbors > 3) // Overpopulation :(
        grid[i][j] = 0;
    else if(number_of_neighbors == 2 || n == 3) // Survival :|
        grid[i][j] = 1;
}else {
    if(number_of_neighbors == 3) // Birth :)
        grid[i][j] = 1;
}

You can abstract this logic to use one function like I did. My function is called tick() that is in a while loop that is called when the user presses enter (return).

The full source code can be found here as a gist.

I hope you found this interesting. This is just my implementation, you can try to implement it in a different way and then compare it with mine. You can also send me your implementation using mail, check contacts page.