JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<canvas width="400" height="400"></canvas>
CSS
canvas {
border: 1px solid black;
}
JavaScript
var canvas = $('canvas')[0];
var context = canvas.getContext('2d');
var size = 100;
var cellSize = 400 / size;
var board = [];
for (var i = 0; i < size; i++) {
board[i] = [];
for (var j = 0; j < size; j++) {
board[i][j] = i < size / 2 ? (j < size / 2 ? 'red' : 'blue') : (j < size / 2 ? 'black' : 'green');
}
}
function getRandomNeighbor(board, x, y) {
var neighbors = [];
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
if (board[x + i] && board[x + i][y + j]) {
neighbors.push(board[x + i][y + j]);
}
}
}
// clump bias
if (_.countBy(neighbors)[board[x][y]] > 7) {
return board[x][y];
} else {
return _.sample(neighbors);
}
}
function update() {
var nextGeneration = [];
for (var i = 0; i < size; i++) {
nextGeneration[i] = [];
for (var j = 0; j < size; j++) {
nextGeneration[i][j] = getRandomNeighbor(board, i, j);
}
}
board = nextGeneration;
}
function draw() {
for (var i = 0; i < size; i++) {
for (var j = 0; j < size; j++) {
context.fillStyle = board[i][j];
context.fillRect(i * cellSize, j * cellSize, cellSize, cellSize);
}
}
context.fill();
}
function step() {
update();
draw();
}
setInterval(step, 40);