I made a program that ask the user a size and generate a perfect maze of size n^2 using the recursive backtarcking algorithm. I've run into this error and saw that i could simply use :
sys.setrecursionlimit(8000)
It worked well at the begining but when i increased the size of the maze my python program simply exited without saying anything...
Here is the dictionary i use to check directions :
_dic = {
"N": (-1, 0),
"S": (1, 0),
"E": (0, 1),
"W": (0, -1),
}
I store the maze inside a numpy array of str, i only store the part of the maze that is going to be modified and add the rest for display when i convert it into a string. For instance a maze of size 3 (3x3) will look like this in display :
.######
..#.#.#
#######
#.#.#.#
#######
#.#.#..
######.
But in my array i'll only have the middle part :
.#.#.
#####
.#.#.
#####
.#.#.
This is just to try to optimize a bit...
Here is the actual backtracking function :
# Recursive backtracking function that takes a posx and posy as position of the cell to visit
def _backtrack(self, posx, posy):
self._map[posx][posy] = 'V' # Mark the cell as visited
while True:
# hasNeighbors returns a empty list if no valid neighbors ar found
# but returns a list of cardinal directions corresponding to valid neighbors if found such as ["N", "E"]
# if there si a valid neighbor on the right and beneath.
dir = self._hasNeighbors(posx, posy)
lenght = len(dir)
# If there is no valid neighbors this is a dead end then return to backtrack
if lenght == 0:
return
# select a random direction to move to and remove it from the list
toBreak = dir.pop(dir.index(random.choice(dir)))
# Replace '#' by '.'
self._map[posx + self._dic[toBreak][0]][posy + self._dic[toBreak][1]] = '.'
# If there is only one valid neightbor break the wall and update posx and posy
# It uses the while loop to keep visiting cells without recursion as long as there is only one choice
if lenght == 1:
posx += self._dic[toBreak][0] * 2
posy += self._dic[toBreak][1] * 2
self._map[posx][posy] = 'V'
#recursive call of the backtrack function with the position of the cell we want to visit
else:
self._backtrack(posx + self._dic[toBreak][0] * 2, posy + self._dic[toBreak][1] * 2)
And here is the hasNeighbors one :
def _hasNeighbors(self, posx, posy):
result = []
# Checking neighbors in each direction
for dir in self._dic.keys():
# If the indexes doesn't exceed the size of the maze
if 0 <= posx + self._dic[dir][0] < self._size * 2 - 1 and 0 <= posy + self._dic[dir][1] < self._size * 2 - 1:
# If the neighbor hasn't been visited
if self._map[posx + self._dic[dir][0] * 2][posy + self._dic[dir][1] * 2] == '.':
#Append this direction to the list of valid neighbors
result.append(dir)
return result
It works like a charm for small sizes like 5, 20, 50... but when i start to go a bit bigger i either have the maximum recursion depth error if i don't increase the limit and if i do increase it the program simply exit without saying anything like this :
PS C:\Users\pierr\Travail\Code\Amazing-Maze> python -m amazingmaze
Please entre the size of the maze : 100
PS C:\Users\pierr\Travail\Code\Amazing-Maze>
I really don't know how to solve this. I don't understand why it blocks at such small sizes i mean i should be able to generate bigger size without breaking a sweat... Is it my recursive backtracking implementation that is the issue have i missed something ? My teacher told me that it was because my stopping condition wasn't working and i was probably visiting cells that i already visited but i kinda disagree, there is obviously something wrong but i really don't think it's that. You can find the complete code at https://github.com/lebair-pierre-alexis/Amazing-Maze