Reputation: 6685
So I'm making a minesweeper game in JS.
I have this function:
function doSquare(x, y) { //takes x,y coordinates of a square. checks and acts accordingly to what's around it
var revealed = [];
var size = board.length;
var mines = countAround(x,y);
table.rows[x].cells[y].innerHTML = mines;
if (mines === 0) {
for (var i=Math.max(0,x-1), l = Math.min(x+1, size-1); i<=l; i++) {
for (var j=Math.max(0, y-1), k = Math.min(y+1, size-1); j<=k; j++) {
if (x == i && y==j) {continue;}
if (revealed.indexOf(i+"."+j) === -1) {
doSquare(i, j);
revealed.push(i+"."+j);
}
}
}
}
}
The board's rows and cols are equal. countAround(x,y)
returns the amount of mines around (x,y); revealed
is an array which stores which squares have already been dealt with, to prevent dealing with them again.
This function is supposed to, when a square is clicked, reveal the number of mines near it and write it into the cell. Then, it checks every square around it, and if that square hasn't already been dealt with (if it isn't in the revealed
array), the function doSquare()
runs on it again. The function will not 'spread' from a square if the square has any mines next to it.
I get an error: maximum call stack size exceeded. But the function stops its 'spreading' upon reaching a square with mines, and also doesn't run on a square which already has been taken care of. So I would love an explanation as to why this happens.
Upvotes: 1
Views: 258
Reputation: 124
I think the problem is that 'revealed' is defined inside your function. This means that each time the function is called, a new 'revealed' is created locally for the function. Therefore, a square with no mines around it will call doSquare for an adjacent square, which may in turn call doSquare on the original square. However, doSquare won't remember that it has already checked this square as a new local version of 'revealed' is created for this call.
Solution:
Either pass 'revealed' as an argument to doSquare so all calls use the same variable (i.e. function doSquare(x, y, revealed){...
, making the initial call as doSquare(x, y, []);
, or declare 'revealed' outside of doSquare, and empty it each time you wish to check for mines.
Upvotes: 1