2

I am trying to make Minesweeper with Python arrays and have successfully generated the board and the bombs. However, I am having difficulty with Minesweeper's "zero recursion". If you select a 0 in Minesweeper, it will reveal all adjacent tiles and if any of the adjacent tiles are 0 it will reveal all adjacent tiles to that 0 and so on. Ultimately, there can be no 0s on the edges of the revealed tiles, as all adjacent tiles to revealed 0s will be revealed. My recursion algorithm is exceeding python's maximum recursion depth. Here's the code:

def zero():

    for y in range(height):

        for x in range(width-1):

            if hidden[y][x] == 0 and (hidden[y+1][x] == '?' or hidden[y-1][x] == '?' or hidden[y+1][x+1] == '?' or hidden[y-1][x-1] == '?' or hidden[y+1][x-1] == '?' or hidden[y-1][x+1] == '?' or hidden[y][x+1] == '?' or hidden[y][x-1] == '?'):

                if y+1 < height:

                    hidden[y+1][x] = board[y+1][x]

                if y-1 >= 0:

                    hidden[y-1][x] = board[y-1][x]

                if y+1 < height and x+1 < width:

                    hidden[y+1][x+1] = board[y+1][x+1]

                if y-1 >= 0 and x+1 < width:

                    hidden[y-1][x+1] = board[y-1][x+1]

                if y-1 >= 0 and x-1 >= 0:

                    hidden[y-1][x-1] = board[y-1][x-1]

                if x+1 < width:

                    hidden[y][x+1] = board[y][x+1]

                if x-1 >= 0:

                    hidden[y][x-1] = board[y][x-1]

                if y+1 < height and x-1 >= 0:

                    hidden[y+1][x-1] = board[y+1][x-1]


                zero()

The code checks to see if there are any revealed zeroes with any hidden adjacent tiles in the array. (Hidden tiles are represented with a '?'). If there are any zeroes that meet these parameters, all adjacent tiles to the zero will be revealed. It then restarts the function. Once there are no zeroes that meet the parameters in the entire array, the function loop will be broken and the code will continue flowing. This exceeds the recursion limit. Any suggestions?

  • Not the best possible apporach but should work: Set a variable `modified = False` before the for-loops. Set it true if you really modify (reveal) a field. Call `zero()` after the for-loops if `modified` was set. Instead of recursive approach this can of course be done in a simple loop. – Michael Butscher Oct 07 '18 at 22:42
  • 1
    You have no return statements, so EVERY SINGLE TIME that you hit `zero()`, it will recurse infinitely. You need to find an appropriate place for `return` statements above `zero()`. – UtahJarhead Oct 07 '18 at 22:44
  • 1
    Honestly, recursion is a great way to solve some problems, but I think I would consider not using it in this situation. Perhaps have zero() return the integer number of squares revealed, and wrap it in a while statement that keeps running zero() until the return is 0. – CJR Oct 07 '18 at 22:46
  • @UtahJarhead: The recursive call is protected by an `if`: it’s not intrinsically implausible that `hidden` might get all its 0/`?` pairs removed so as to terminate the recursion. – Davis Herring Oct 08 '18 at 01:42

1 Answers1

0

Your test for '?' is not protected against indexing outside the board. At the low-index edges, this produces negative indices that wrap around. However, the code that clears the '?'s does check its indices, so any cross-edge 0-? pair persists and infinite recursion results.

At the high-index edges of the board, the read would fail with IndexError (assuming no padding with “ghost cells”), but of course the algorithm is biased by its search order toward the smaller indices, so it normally never gets that far.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76