An inefficient, non-interactive version of John Conway's Game of Life. Also an exercise of nested selections.
Last active
August 29, 2015 14:10
-
-
Save munshkr/d2eaa3bc4595a8ff692f to your computer and use it in GitHub Desktop.
Game of Life
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<meta charset="utf-8"> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
var width = 960, | |
height = 500, | |
cellSize = 20, | |
speed = 200, | |
blurSpeed = "200ms", | |
color = "#222", | |
backColor = "#fff"; | |
var rows = height / cellSize, | |
cols = width / cellSize; | |
var createWorld = function(rows, cols) { | |
var matrix = []; | |
for (var i = 0; i < rows; i++) { | |
var row = []; | |
for (var j = 0; j < cols; j++) { | |
row.push(Math.random() > 0.9 ? 1 : 0); | |
} | |
matrix.push(row) | |
} | |
return matrix; | |
}; | |
var update = function(matrix) { | |
var cellRow = d3.select("svg").selectAll("g") | |
.data(matrix); | |
// ENTER cellrow | |
cellRow.enter().append("g") | |
.attr("transform", function(d, y) { | |
return "translate(0 " + (cellSize * y) + ")"; | |
}); | |
// EXIT cellrow | |
cellRow.exit().remove(); | |
var cell = cellRow.selectAll("rect") | |
.data(function(d, x) { return d; }); | |
// ENTER cell | |
cell.enter().append("rect") | |
.attr("height", cellSize) | |
.attr("width", cellSize) | |
.attr("x", function(d, x) { return cellSize * x; }) | |
.style("fill", function(d, x) { return d > 0 ? color : backColor; }) | |
.style("transition", "fill " + blurSpeed) | |
.style("-webkit-transition", "fill " + blurSpeed) | |
.style("-moz-transition", "fill " + blurSpeed); | |
// UPDATE cell | |
cell.style("fill", function(d, x) { return d > 0 ? color : backColor; }) | |
// EXIT cell | |
cell.exit().remove(); | |
} | |
var neighbours = function(matrix, x, y) { | |
if (matrix.length === 0) return 0; | |
var c = 0; | |
for (var i = -1; i <= 1; i++) { | |
for (var j = -1; j <= 1; j++) { | |
if (y + i >= 0 && y + i < matrix.length && | |
x + j >= 0 && x + j < matrix[0].length) | |
{ | |
c += matrix[y + i][x + j]; | |
} | |
} | |
} | |
if (matrix[y][x]) c--; | |
return c; | |
} | |
var tick = function(matrix) { | |
var changed = false; | |
if (matrix.length === 0) return { | |
world: matrix, | |
changed: changed, | |
}; | |
// Clone matrix | |
var newMatrix = matrix.slice(); | |
// Make new matrix based on Game of Life rules | |
for (var i = 0; i < matrix.length; i++) { | |
for (var j = 0; j < matrix[0].length; j++) { | |
var n = neighbours(matrix, j, i); | |
if (matrix[i][j] === 1 && (n < 2 || n > 3)) { | |
newMatrix[i][j] = 0; | |
changed = true; | |
} else if (matrix[i][j] === 0 && n === 3) { | |
newMatrix[i][j] = 1; | |
changed = true; | |
} | |
} | |
} | |
return { | |
world: newMatrix, | |
changed: changed, | |
}; | |
} | |
var world = createWorld(rows, cols); | |
var svg = d3.select("body") | |
.append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.style("shape-rendering", "crispedges"); | |
setInterval(function() { | |
var res = tick(world); | |
update(res.world); | |
// If game stops, create a new matrix | |
if (res.changed) { | |
world = res.world; | |
} else { | |
world = createWorld(rows, cols); | |
} | |
}, speed); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment