Developing a Conway's Game of Life algorithm in Javascript

gordoncaister

Gordon Caister

Posted on June 23, 2020

Developing a Conway's Game of Life algorithm in Javascript

First we will start with our possibilities:

Given the possibilities of a cell's neighbours where the cell is 'C' there are 8 possible neighbours as detailed in the tables below, the first table would be cardinal direction while the second table is a relative coordinate where the first digit represents x or the rows, and the second represents y or the columns. I.e. SW is relatively 1 row further than C and -1 column further than C.

NW  N  NE 
W   C  E  
SW  S  SE 

[
 [-1,-1],
 [-1,0],
 [-1,1],
 [0,-1],
 [0,0],
 [0,1],
 [1,-1],
 [1,0],
 [1,1]
]

We need to cycle through each cell in the total grid and compare each of its neighbours and see how many of its neighbours are alive.

To this end, I have represented alive with ‘1’ and dead with ‘0’ which in javascript equate to truthy and falsy respectively, while still maintaining their integer value.I am using this to my advantage.

Duplicate the existing grid.
For i in rows,
For j in columns
For x,y in possibilities
We will add the current row index (i) to the possible x value
We will add the current col index (j) to the possible y value
If the combined x is greater than or equal to 0 and less than the number of rows and the combined y is greater than or equal to 0 and less than the number of columns:
Add 1 to the total number of neighbours for the current cell
Once we’re finished finding number of neighbours: if the neighbours is greater than 3 or less than 2, set the current cells value to 0 (Rule 1 and 3)
If the current cell’s value is 0 and the number of neighbours is 3, set the current cell to 1 (alive)
All other cells should be left alone
Set the existing grid equal to the altered duplicated grid

    const tempGrid = JSON.parse(JSON.stringify(grid))

    for(let i = 0; i < rows; i++){
      for(let j = 0; j < cols; j++){
        let neighbours = 0;
        possibilities.forEach(([x,y])=> {
          const nextI = i + x;
          const nextJ = j + y;
          if(nextI >= 0 && nextI<rows && nextJ >= 0 && nextJ < cols){
            neighbours += grid[nextI][nextJ] 
          }
        });
        if (neighbours < 2 || neighbours > 3){
          tempGrid[i][j] =  0;
        } else if (grid[i][j] === 0 && neighbours === 3) {
          tempGrid[i][j] = 1;
        }
      };
    }

Given the above code requires a few other pieces of data to run I will include how they existed in my code. I was using React to run my frontend so I used the useState hook to maintain the state of my grid.


const rows = 50
const cols = 50

const possibilities = [
  [-1,-1],
  [-1,0],
  [-1,1],
  [0,1],
  [1,1],
  [1,0],
  [1,-1],
  [0,-1],
]

const zeroArray = (rows,cols)=> {

  let arr = new Array(rows);
  for(let i = 0; i < arr.length; i++){
    arr[i] = new Array(cols);
    for(let j = 0; j < rows; j++){
      arr[i][j] = 0
    }
  }
  return arr;
}

const [grid, setGrid] = useState(zeroArray)

I kept a reference to zeroArray because I wanted to include a function that cleared the board and reset all cells to 0.

💖 💪 🙅 🚩
gordoncaister
Gordon Caister

Posted on June 23, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related