frrlod
frrlod

Reputation: 6685

Minesweeper game - Maximum call stack side exceeded

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

Answers (1)

TheSuccessor
TheSuccessor

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

Related Questions