Created
December 8, 2012 13:56
-
-
Save KrofDrakula/4240350 to your computer and use it in GitHub Desktop.
Game of Life
This file contains hidden or 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
| function Cell(x, y) { | |
| this.x = x; | |
| this.y = y; | |
| } | |
| function World(cells) { | |
| this.cells = cells || []; | |
| } | |
| Array.prototype.hasCell = function(cell) { | |
| if (arguments.length == 2) cell = new Cell(arguments[0], arguments[1]); | |
| return this.filter(function(c) { | |
| return c.x == cell.x && c.y == cell.y; | |
| }, this).length > 0; | |
| }; | |
| World.prototype.advanceStep = function(){ | |
| var candidates = this.computeCandidates(), | |
| newState = []; | |
| candidates.forEach(function(cell) { | |
| var neighbours = this.findNeighbours(cell); | |
| if (neighbours.length == 2 && this.cells.hasCell(cell) || neighbours.length == 3) | |
| newState.push(cell); | |
| }, this); | |
| this.cells = newState; | |
| }; | |
| World.prototype.computeCandidates = function() { | |
| var candidates = []; | |
| this.cells.forEach(function(cell) { | |
| for (var y = cell.y - 1; y <= cell.y + 1; y++) | |
| for (var x = cell.x - 1; x <= cell.x + 1; x++) { | |
| var c = new Cell(x, y); | |
| if (!candidates.hasCell(c)) candidates.push(c); | |
| } | |
| }); | |
| return candidates; | |
| }; | |
| World.prototype.findNeighbours = function(cell) { | |
| if (arguments.length == 2) { | |
| cell = new Cell(arguments[0], arguments[1]); | |
| } | |
| return this.cells.filter(function(c) { | |
| var dx = Math.pow(c.x - cell.x, 2), | |
| dy = Math.pow(c.y - cell.y, 2); | |
| return (dx + dy > 0) && (dx + dy <= 2); | |
| }); | |
| } | |
| World.prototype.render = function() { | |
| var xs = this.cells.map(function(cell){ return cell.x; }); | |
| var ys = this.cells.map(function(cell){ return cell.y; }); | |
| var minX = Math.min.apply(Math, xs) - 2; | |
| var maxX = Math.max.apply(Math, xs) + 2; | |
| var minY = Math.min.apply(Math, ys) - 2; | |
| var maxY = Math.max.apply(Math, ys) + 2; | |
| console.log(); | |
| for (var y = minY; y <= maxY; y++) { | |
| for (var x = minX; x <= maxX; x++) { | |
| if (this.cells.hasCell(x, y)) { | |
| process.stdout.write('X '); | |
| } else { | |
| process.stdout.write('- '); | |
| } | |
| } | |
| console.log(); | |
| } | |
| } | |
| exports.World = World; | |
| exports.Cell = Cell; |
This file contains hidden or 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
| // npm install mocha chai | |
| require('chai').should(); | |
| var gol = require('./gol'), | |
| World = gol.World, | |
| Cell = gol.Cell; | |
| describe('Game of Life', function() { | |
| describe('an empty world', function() { | |
| it('should have no cells', function() { | |
| var w = new World(); | |
| w.cells.length.should.equal(0); | |
| }); | |
| it('should stay dead', function() { | |
| var w = new World(); | |
| w.advanceStep(); | |
| w.cells.length.should.equal(0); | |
| }); | |
| }); | |
| describe('simple structures', function() { | |
| it('should store cells correctly', function() { | |
| var w = new World([ | |
| new Cell(0,0) | |
| ]); | |
| w.cells.length.should.equal(1); | |
| w.cells.push(new Cell(1,0)); | |
| w.cells.length.should.equal(2); | |
| }); | |
| it('should correctly count neighbours', function() { | |
| var w = new World([ | |
| new Cell(0,0), | |
| new Cell(0,1), | |
| new Cell(0,2) | |
| ]); | |
| w.findNeighbours(0, -2).length.should.equal(0); | |
| w.findNeighbours(0, -1).length.should.equal(1); | |
| w.findNeighbours(w.cells[0]).length.should.equal(1); | |
| w.findNeighbours(w.cells[1]).length.should.equal(2); | |
| w.findNeighbours(w.cells[2]).length.should.equal(1); | |
| w.findNeighbours(0, 3).length.should.equal(1); | |
| w.findNeighbours(0, 4).length.should.equal(0); | |
| }); | |
| }); | |
| describe('too small world', function() { | |
| it('should not survive', function() { | |
| var w = new World([ | |
| new Cell(0, 0) | |
| ]); | |
| w.advanceStep(); | |
| w.cells.length.should.equal(0); | |
| }); | |
| }); | |
| describe('line', function() { | |
| it('should rotate', function() { | |
| var w = new World([ | |
| new Cell(0, 0), | |
| new Cell(1, 0), | |
| new Cell(2, 0) | |
| ]); | |
| w.advanceStep(); | |
| w.cells.hasCell(new Cell(1, -1)).should.be.true; | |
| w.cells.hasCell(new Cell(1, 0)).should.be.true; | |
| w.cells.hasCell(new Cell(1, 1)).should.be.true; | |
| w.cells.length.should.equal(3); | |
| }); | |
| }); | |
| describe('glider', function() { | |
| it('should have a period of four generations', function() { | |
| }); | |
| }); | |
| describe('render', function() { | |
| it('should render', function() { | |
| var w = new World([ | |
| new Cell(0, 0), | |
| new Cell(1, 0), | |
| new Cell(2, 0) | |
| ]); | |
| w.render(); | |
| w.advanceStep(); | |
| w.render(); | |
| }); | |
| }); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment