DEV Community

loading...
Cover image for The Game of Life

The Game of Life

Luke Garrigan
English lad currently a C#/Java/VueJs/JavaScript/TypeScript engineer. Extra dribbling can be found at https://codeheir.com Portfolio found at https://lukegarrigan.com
・3 min read

The Game of Life or cellular automaton was developed by John Horton Conway in 1970 with just some paper and a Go board. It takes place on a two-dimensional grid where each cell is in one of two states on (alive) or off (dead). The state of a cell is determined by its neighbours, and 4 simple rules determine whether the given state will live or die.

Rules

There are four rules that determine a cell’s fate.

  1. Underpopulation: Any live cell that has less than two neighbours dies.
  2. Overpopulation: Any live cell that has more than three neighbours dies.
  3. Any cell with two or three neighbours survives.
  4. Reproduction: Any dead cell with exactly three neighbours becomes a live cell.

These rules can be further simplified for implementation:

  1. Any live cell with two or three neighbours survives
  2. Any dead cell with three live neighbours becomes a live cell
  3. Everything else is now a dead cell

Implementing

I’m going to be using p5.js to implement this, all the code can be found here.

The first step is to create a grid and randomly choose whether the cell is dead or alive:

let grid;
let columns;
let rows;
let size = 20;

function setup() {
  createCanvas(800, 600);
  columns = width / size;
  rows = height / size;
  grid = createGrid();

  for (let i = 0; i < columns; i++) {
    for (let j = 0; j < rows; j++) {
      grid[i][j] = floor(random(2));
    }
  }
}

function draw() {
  background(0);
  for (let i = 0; i < columns; i++) {
    for (let j = 0; j < rows; j++) {
      let x = i * size;
      let y = j * size;
      if (grid[i][j] == 1) {
        fill(0, 255, 255);
        stroke(0, 255, 255);
        rect(x, y, size, size);
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Which should give us something like the following, where the blue colour represents a live cell:

image of grid

The next step is to create the next generation.

function createNewGeneration() {
  let nextGeneration = createGrid();
  for (let i = 0; i < columns; i++) {
    for (let j = 0; j < rows; j++) {
      let currentState = grid[i][j];
      let count = countNeighbours(i, j);
      if (currentState == 1 && count == 2 || count == 3) {
        nextGeneration[i][j] = 1;
      } else if (currentState == 0 && count == 3) {
        nextGeneration[i][j] = 1;
      } else {
        nextGeneration[i][j] = 0;
      }
    }
  }
  return nextGeneration;
}

function countNeighbours(x, y) {
  let sum = 0;
  for (let i = -1; i <= 1; i++) {
    for (let j = -1; j <= 1; j++) {
      let col = (x + i + columns) % columns;
      let row = (y + j + rows) % rows;
      sum += grid[col][row];
    }
  }
  sum -= grid[x][y];
  return sum;
}

Enter fullscreen mode Exit fullscreen mode

Now all that's needed is to assign the new generation to the current grid: grid = createNewGeneration() in the draw function and we're good to go!

image of grid moving game of life

Let's make each cell a little smaller, thus increasing the population size: let size = 5

image of grid moving game of life more cells

Conclusion

The Game of Life is a marvellous simulation. It demonstrates how just a few simple rules and structures can form very complex systems. There's far more to learn about the Game of Life, there's a whole lexicon of patterns that perform particular behaviours.

What is even more remarkable about the Game of Life is that it is Turing Complete. It is able to make any arbitrarily complex computation, meaning a computer can be built in the Game of Life that can run a simulation of the Game of Life, which of course, has been done.

Discussion (0)