1

I'm coding a maze solving algorithm and I'm having trouble with the backtracking once you hit a "wall"

So far I have that my code checks some basic recursive cases such as if I've reached the end or if I have checked all points. I've also made it so that there's a list that keeps track of the solution "path" and adds and removes points accordingly. So every time it adds a point, it checks if its valid and checks the point, above, to the left, to the right, and below etc. If none are valid then this statement is executed

    else:
    path.pop()
    return solve_maze(maze,path,end) 

this removes the point and backtracks and checks the following conditions at the beginning of the function.

square = list(path[-1])

#Base Case

if end in path:
    return True

elif square == None:
    return False

elif maze[square[0]][square[1]] == "X":
    path.pop()
    return solve_maze(maze,path,end)

elif tuple(square) in path:
    path.pop()
    return solve_maze(maze,path,end)

However when I execute the last line, it just removes all the points in my path and i get an indexing error.

Any advice on how I can backtrack once I hit a dead end?

MT0820
  • 21
  • 1
  • 2

1 Answers1

4

Here is a heavily commented solution:

def backtrack(i,j):
   # if matrix[i][j] is visited, then do nothing
   # if it is a wall, then do not insert it in the path from the first place
   if visit[i][j] != 0 or matrix[i][j] == 'X':
      return
   # mark the index as visited as to not visit it again
   visit[i][j] = 1
   # add the index to the path
   path.append((i,j))
   # if it is the GOAL, then store this path somewhere, 
   # and pop the last index to traverse other paths that reaches the GOAL
   if matrix[i][j] == 'G':
      # any paths that reach the GOAL are appended here
      ans.append(list(path))
      path.pop()
      return
   # loop on the neighbors. if they are valid indices, do the same work again
   for k in range(3):
      nwi = i + row[k]
      nwj = j + col[k]
      if valid(nwi, nwj):
         backtrack(nwi, nwj)
   # after finishing this index, just pop because we do not need it any more
   path.pop()
   return

def valid(i,j):
   return (i >= 0 and i <=2) and (j >= 0 and j <= 2)

# just a dummy matrix to start with
matrix = [['.', '.', '.'], ['.', 'X', '.'], ['.', 'G', 'X']]
# an array that marks indices as visited or not
visit = [[0,0,0],[0,0,0],[0,0,0]]
# the path that is used in the back tracking
path = []
# this will be a list of lists containing ALL the paths that can reach the GOAL
ans = []
# these are the neighbors indices
row = [-1, 1, 0, 0]
col = [0, 0, 1, -1]

backtrack(0,0)

if len(ans) == 0: 
   print("no path found!")
else:
   print(ans)

My solution will give you all the paths that can reach your target in a list of lists called ans. If the length of ans is zero, then no paths are found.

If you didn't understand the comments written in the code or are by any means confused, do not hesitate at all to comment down and I will reply.

NOTE:(edit)

I assumed the starting states of the maze and the function content itself because you didn't provide any test cases or your full function itself.

Ahmed Khaled
  • 121
  • 1
  • 5