Last active
January 23, 2020 04:11
-
-
Save rmela/76fe92595473ac07c25cf3dd1d631a38 to your computer and use it in GitHub Desktop.
Simple Game of Life module - ( add to package.json as "any-name-here": "gist:76fe92595473ac07c25cf3dd1d631a38" )
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
function toString( rows ) { | |
return rows | |
.map( row => row | |
.map( cell => cell.value ? '1' : '0' ) | |
.join( ' ' ) | |
).join("\n") | |
} | |
class Game { | |
constructor( rows, cols ) { | |
this.rows = rows | |
this.cols = cols | |
this.length = rows * cols | |
this.cells = [] | |
this.initialize() | |
this.flattened = this.cells.flat() | |
} | |
set( row, col, value ) { | |
this.cells[row][col].value = value | |
} | |
get( row, col ) { | |
return this.cells[row][col].value | |
} | |
count( cell ) { | |
let cnt = 0 | |
for( let n of cell.neighbors ) { | |
n = this.cells[ n.row ][n.col] | |
if( n.value === 1 ) { | |
cnt += 1 | |
} | |
} | |
return cnt | |
} | |
initialize() { | |
let idx = 0 | |
for( let rownum = 0; rownum < this.rows; ++rownum ) { | |
let row = this.cells[rownum] = [] | |
for( let colnum = 0; colnum < this.cols; ++colnum ) { | |
let cell = { idx: idx++, row: rownum, col: colnum, value: 0 } | |
this.assignNeighbors( cell ) | |
row.push( cell ) | |
} | |
} | |
} | |
assignNeighbors(cell) { | |
let r = cell.row | |
let c = cell.col | |
let i = cell.idx | |
let neighbors = [ | |
{ idx: i, row: r , col: c - 1 }, // left | |
{ idx: i, row: r , col: c + 1 }, // right | |
{ idx: i, row: r - 1, col: c }, // above | |
{ idx: i, row: r - 1, col: c - 1 }, // aboveLeft | |
{ idx: i, row: r - 1, col: c + 1 }, // aboveRight | |
{ idx: i, row: r + 1, col: c }, // below | |
{ idx: i, row: r + 1, col: c - 1 }, // belowLeft | |
{ idx: i, row: r + 1, col: c + 1 } // belowRight | |
] | |
let filter = cell => ( | |
cell.row >= 0 && | |
cell.row < this.rows && | |
cell.col >= 0 && | |
cell.col < this.cols | |
) | |
cell.neighbors = neighbors.filter( filter ) | |
} | |
changes() { | |
let rv = [] | |
for( let cell of this.flattened ) { | |
let cnt = this.count( cell ) | |
if( cnt === 3 && cell.value === 0 ) { | |
//console.log( 'reviving', cell.row, cell.col ) | |
rv.push( { row: cell.row, col: cell.col, value: 1 } ) | |
continue | |
} | |
if( cell.value === 1 && ( cnt > 3 || cnt < 2 ) ) { | |
//console.log( 'killing', cell.row, cell.col ) | |
rv.push( { row: cell.row, col: cell.col, value: 0 } ) | |
} | |
} | |
return rv | |
} | |
apply( changes ) { | |
let cells = [] | |
for( let c of changes ) { | |
let cell = this.cells[c.row][c.col]; | |
cell.value = c.value | |
cells.push( cell ) | |
} | |
return cells | |
} | |
toString() { | |
return toString( this.cells ) | |
} | |
advance() { | |
return this.apply( this.changes() ) | |
} | |
} | |
module.exports.Game = Game |
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
{ | |
"name": "gol", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"test": "mocha test.js" | |
}, | |
"devDependencies": { | |
"mocha": "" | |
}, | |
"author": "[email protected]", | |
"license": "ISC" | |
} |
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
/* Lives at package root since gists don't allow subdirs */ | |
const assert = require('assert') | |
const Game = require('./index').Game | |
const VERTICAL = [ | |
// Blink pattern | |
[ 1, 0 ], | |
[ 1, 1 ], | |
[ 1, 2 ] | |
] | |
const HORIZONTAL = [ | |
[ 0, 1 ], | |
[ 1, 1 ], | |
[ 2, 1 ], | |
] | |
function match( game, expected ) { | |
for( let ridx = 0; ridx < game.rows; ++ridx ) { | |
for( let cidx = 0; cidx < game.cols; ++cidx ) { | |
if( orientation[ridx][cidx] != game.get( ridx, cidx ) ) | |
return false | |
} | |
} | |
return true | |
} | |
function newGame() { | |
let rv = new Game( 3, 3 ) | |
for( let [row,col] of VERTICAL ) { | |
rv.set( row, col, 1 ) | |
} | |
return rv | |
} | |
it("should run blink", function() { | |
let game = newGame() | |
assert.equal( true, match( VERTICAL ) ) | |
game.advance() | |
assert.equal( true, match( HORIZONTAL ) ) | |
game.advance() | |
assert.equal( true, match( VERTICAL ) ) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment