class GameOfLife {
constructor(cells){
this.cells = cells.concat([]).map(row => row.concat([]));
this.newCells = [];
for (let y = 0; y < this.cells.length; y++) {
this.newCells[y] = [];
for (let x = 0; x < this.cells[y].length; x++) {
this.newCells[y][x] = this.cells[y][x];
}
}
this.WIDTH = this.cells[0].length;
this.HEIGHT = this.cells.length;
this.gen = 1;
}
next() {
this.gen++;
for (let y = 0; y < this.cells.length; y++) {
for (let x = 0; x < this.cells[y].length; x++) {
let numNeighbors = this._checkNeighbors(x, y);
if (this._isAlive(x, y)) {
switch (numNeighbors) {
case 3:
case 2:
this.on(x, y);
break;
default:
this.off(x, y);
}
} else {
switch (numNeighbors) {
case 3:
this.on(x, y);
break;
default:
this.off(x, y);
}
}
}
}
let aux = this.cells;
this.cells = this.newCells;
this.newCells = aux;
}
on(x, y) {
this._set(x, y, 1);
}
off(x, y) {
this._set(x, y, 0);
}
toggle(x, y) {
this._set(x, y, 1 - this._check(x, y));
}
_isAlive(x, y) {
return this._check(x, y) > 0;
}
_isDead(x, y) {
return this._check(x, y) === 0;
}
_check(x, y) {
return this.cells[y][x];
}
_set(x, y, v) {
this.newCells[y][x] = v;
}
_checkNeighbors(x, y) {
let count = 0;
for (let j = y - 1; j <= y + 1; j++) {
for (let i = x - 1; i <= x + 1; i++) {
if (i === x && j === y) continue;
count += this._check((this.WIDTH + i) % this.WIDTH, (this.HEIGHT + j) % this.HEIGHT);
}
}
return count;
}
}