Skip to content

Instantly share code, notes, and snippets.

@coryk135
Last active August 29, 2015 13:59
Show Gist options
  • Save coryk135/10799089 to your computer and use it in GitHub Desktop.
Save coryk135/10799089 to your computer and use it in GitHub Desktop.
Golang Game of Life ported to JavaScript
<html>
<head>
</head>
<body>
<canvas id="canvas" width="1000" height="1000"></canvas>
<script src="life.js"></script>
<body>
</html>
rand = {
Intn: function(n) {
var val = Math.floor(Math.random() * n);
if (val == n) val--;
return val;
}
}
// Functions can be treated like classes.
// Think of this as the constructor
// Field represents a two-dimensional field of cells.
function Field(s, w, h) {
this.s = s
this.w = w
this.h = h
}
// The next function is just a helper funciton that creates a new
// field for you.
// NewField returns an empty field of the specified width and height.
function NewField(w, h) {
var s = new Array(h);
for (i = 0; i < s.length; i++) {
s[i] = new Array(w);
}
return new Field(s, w, h);
}
// Field.prototype.<Function_Name> = function(){}
// This adds a method to the prototype of a function
// In this sense we are adding a "method" to the "class" Field
// Set sets the state of the specified cell to the given value.
Field.prototype.Set = function(x, y, b) {
this.s[y][x] = b
}
Field.prototype.Alive = function(x, y) {
x += this.w
x %= this.w
y += this.h
y %= this.h
return this.s[y][x]
}
Field.prototype.Next = function(x, y) {
// Count the adjacent cells that are alive.
var alive = 0
for (i = -1; i <= 1; i++) {
for (j = -1; j <= 1; j++) {
if ((j != 0 || i != 0) && this.Alive(x+i, y+j)) {
alive++
}
}
}
// Return next state according to the game rules:
// exactly 3 neighbors: on,
// exactly 2 neighbors: maintain current state,
// otherwise: off.
return alive == 3 || alive == 2 && this.Alive(x, y)
}
function Life(a, b, w, h) {
this.a = a
this.b = b
this.w = w
this.h = h
}
function NewLife(w, h) {
var a = NewField(w, h)
for (i = 0; i < (w * h / 4); i++) {
a.Set(rand.Intn(w), rand.Intn(h), true)
}
return new Life(a, NewField(w, h), w, h);
}
Life.prototype.Step = function() {
// Update the state of the next field (b) from the current field (a).
for (y = 0; y < this.h; y++) {
for (x = 0; x < this.w; x++) {
this.b.Set(x, y, this.a.Next(x, y))
}
}
// Swap fields a and b.
var temp = this.a; this.a = this.b; this.b = temp;
}
Life.prototype.String = function() {
var buf = ""
for (y = 0; y < this.h; y++) {
for (x = 0; x < this.w; x++) {
b = ' '
if (this.a.Alive(x, y)) {
b = '*'
}
buf += b
}
buf += '\n'
}
return buf
}
var id;
function main() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var width = 100;
var height = 100;
l = NewLife(100, 100)
id = setInterval(function(){
l.Step();
var chars = l.String();
ctx.fillStyle = "rgb(255,255,255)";
ctx.clearRect(0,0,1000,1000);
ctx.fillStyle = "rgb(200,0,0)";
var i = 0;
var j = 0;
var r,g,b;
for(var c = 0; c < chars.length; c++){
var char = chars[c];
if(char == "\n"){
i++;
j=0;
} else {
if(char == "*"){
r = Math.floor(Math.random()*255);
g = Math.floor(Math.random()*255);
b = Math.floor(Math.random()*255);
ctx.fillStyle = "rgb("+r+","+g+","+b+")";
ctx.fillRect(i*10,j*10, 10, 10);
}
j++;
}
}
/*
for(var i = 0; i<width; i+=1){
for(var j = 0; j<height; j+=1){
if(cells[i][j].alive){
ctx.fillRect(i*10,j*10, 10, 10);
}
}
}
*/
}, 40);
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment