Arin Yaldizciyan Arin Yaldizciyan -3 years ago 70
Javascript Question

Javascript game of life array gets reset

For a fun little project I decided to program conway's game of life in javascript. My logic seems to make sense and each individual function does its job however I still dont get my intended result. I have an array called grid, which stores the value of all the cells, and if they are alive or dead. I check each individual cell, then check all 8 surrounding cells to count neighbors, repeat for every other cell. At some point my grid no longer stores the correct value and resets. At this point I'm starting to think it's a javascript problem.



<body>
<style>
* {
padding: 0;
margin: 0;
}

body {
overflow: hidden;
}

canvas {
background: #FFFFFF;
display: block;
margin: 0 auto;
}
</style>
<canvas id="canvas" style="border:1px solid #000000;"></canvas>
</body>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var Game = {};
var nextGrid, emptyGrid, grid;
Game.horCells = 30;
Game.cellSize = canvas.width / Game.horCells;
Game.verCells = Math.floor(canvas.height / Game.cellSize);
Game.startLives = 80;

config();
//setInterval(run, 1000);

function config() {
console.log("in config");
emptyGrid = newGrid(Game.horCells, Game.verCells);
grid = emptyGrid;
nextGrid = emptyGrid;
//Manual Setup
for (var i = 0; i < Game.startLives; i++) {
//grid[getRandomInt(0, Game.horCells - 1)][getRandomInt(0, Game.verCells - 1)] = true;
}
grid[0][3] = true;
grid[1][3] = true;
grid[2][3] = true;
}

function run() {
console.log("gread" + grid[3][3]);
draw();
update();
}


function draw() {
console.log("Draw");
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < Game.horCells; i++) {
for (var j = 0; j < Game.verCells; j++) {
if (grid[i][j] === false) {
ctx.fillStyle = "#FFFFFF";
} else if (grid[i][j] === true) {
console.log("drawing live");
ctx.fillStyle = "#000000";
}
ctx.fillRect(i * Game.cellSize, j * Game.cellSize, Game.cellSize, Game.cellSize);
}
}
}

function update() {
for (var p = 0; p < Game.horCells; p++) {
for (var k = 0; k < Game.verCells; k++) {
nextGrid[p][k] = survival(p, k);
}
}
}

function survival(x, y) {
var neighbours = 0;
for (var l = 0; l < 3; l++) {
for (var m = 0; m < 3; m++) {
var sx = (x - 1) + l;
var sy = (y - 1) + m;
//Check bounds
if (inBounds(sx, sy) === true && grid[sx][sy]) {
neighbours++;
}
}
}
if (grid[x][y]) {
neighbours--;
if (neighbours === 2 || neighbours === 3) {
return true;
} else if (neighbours < 2 || neighbours > 3) {
console.log("DIED");
return false;
}
} else if (grid[x][y] === false && neighbours === 3) {
return true;
} else {
console.log("DIED");
return false;
}
}

function inBounds(x, y) {
return (x >= 0 && x < Game.horCells && y >= 0 && y < Game.horCells);
}

function newGrid(xCells, yCells) {
var gridd = new Array(xCells);
for (var i = 0; i < xCells; i++) {
gridd[i] = new Array(yCells);
}

for (var j = 0; j < xCells; j++) {
for (var k = 0; k < yCells; k++) {
gridd[j][k] = false;
}
}
return gridd;
}


function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>




Answer Source
emptyGrid = newGrid(Game.horCells, Game.verCells);
grid = emptyGrid;
nextGrid = emptyGrid

Creates 1 grid, then assigns grid and nextGrid to the same object. Again, grid and nextGrid are the same object. Any changes you make to 1 will happen to the other.

Create 2 separate grids so they can be changed independently:

grid = newGrid(Game.horCells, Game.verCells);
nextGrid = newGrid(Game.horCells, Game.verCells);

Or, to neaten it up slightly:

var g = () => newGrid(Game.horCells, Game.verCells);

grid = g();
nextGrid = g();

Just to clear up the question in the comments:

var g = () => newGrid(Game.horCells, Game.verCells);

Is (basically) the same thing as:

var g = function() {
    return newGrid(Game.horCells, Game.verCells);
}

It's known as a "fat-arrow" function.

Both bits do the same thing though: they create a function that returns a new grid. This has the benefit of not needing to write newGrid(Game.horCells, Game.verCells); twice.

I used a arrow function instead of the function keyword because the latter is giant and ugly, which takes away from the goal of cleaning up the code.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download