Conway’s Game of Life takes place on a grid of “cells” which can have two possible states - alive or dead. The grid is periodically updated, and during these updates, cells will come alive or die based on the following rules:
And that’s all. From just those rules, you can get a dizzying variety of results and patterns - including a Turing machine!
The cells themselves are represented as
in an HTML table.
Each cell is of either the class
alive or the class
dead, and those classes are used both to keep track of the
cell’s state in the script and to manage CSS formatting.
Each cell also has an “age” class that can be either
age3. This is
outside the strict rules of the Game of Life and is purely a cosmetic
thing: it’s used to add CSS rules showing how long which cells recently
came alive or died.
The elements themselves are automatically added (both to avoid repetitive HTML entry, and to make the size of the grid easily adjustable):
The most unusual part of using an HTML table for this is accessing
each cell’s neighbors to determine whether the cell must live or die.
In most implementations of this game, the cell data would probably be
stored in a matrix; then, checking the cell at
(x, y) would be accomplished by looking up the cell at,
(x+1, y+1), for a diagonal neighbor. You could do this
here, too! You could implement the grid’s data as a matrix, and then pass
that data to your HTML table to “draw” it.
But if you’re storing the data in a table anyway, then that opens up
another method for checking the neighbors: DOM traversal! In particular,
can work well here.
The horizontal neighbors are the easiest to check, since they are located
in the adjacent
td elements, so they can be accessed by
(If the cell being checked is at the left or right edge, then
there is no sibling, and the relevant one of these methods will just return
null - which I interpret here as equivalent to “dead”:
The other six neighbors are a little more complicated, since they’re
in different rows. There isn’t really (as far as I know) an equivalent
one-liner for “traverse to the
td directly above this one.”
Instead, order to get to them, we have to first traverse to
the parent row (the
tr element) that contains our cell.
Then, we use
get to the adjacent rows (where before we were traversing between cells.)
Assuming the adjacent row isn’t
null, we then
td elements inside it using its
children property. But which of the children do we
look at? Even though we aren’t using a matrix, we still need to know our
X coordinate… but we can get it using
How? We just call it repeatedly until it
With that, we can access the correct elements of the adjacent rows, which will be our vertically adjacent elements. We can also pick up the diagonally adjacent elements while we’re at it.
Getting the number of living neighbors was the hard part. Once that is known, actually doing that whole Game of Life thing is easy!
One implementation detail I didn’t quite figure out: if you
fire it up and try to draw on the grid,
you can only do it one cell at a time.
You can’t click and drag multiple cells at
once, which makes it a bit harder to draw in a pattern you want.
Right now, clicking on the grid is implemented using
But there might be a better event, or a better way to use it. If you know how I might improve this part of the experience, feel free to drop me a line!
You can check out the full script here along with the full implementation here.