maze
is a 20 × 10
string
of characters.
a
is a 20 × 10
array of
bools.
(In other words,
a
is a
list
of 10 smaller
lists.
Each of these 10 smaller
lists
is a
list
of 20
bools.)
"""
Find a path through a maze.
From "The Elements of Programming Style", 2nd ed., by Kernighan and Plauger, pp. 67-77.
"""
import sys
import copy
#dot is empty space, X is a wall.
maze = """\
XXXXXXXXXXXXXXXXXXXX
XXXX.XXXXXXXX.......
..XX........X.XXXXXX
X.XX.XXXXXXXX.XXX.XX
X......XX.........XX
XXXXXX.XX.XXX.XXX.XX
XX.XXX.XX.XXX.XXX.XX
XX...........XXXX.XX
XXXXXXXXXXXXXXXX..XX
XXXXXXXXXXXXXXXXXXXX"""
def findPath():
"""
Return True if the maze has an entrance along an edge, with a path to an exit
along an edge. Record the path in the path list.
"""
for row in range(1, nrows - 1):
if search(row, 0, row, 1): #left edge
return True
if search(row, ncols - 1, row, ncols - 2): #right edge
return True
for col in range(1, ncols - 1):
if search(0, col, 1, col): #top edge
return True
if search(nrows - 1, col, nrows - 2, col): #bottom edge
return True
def search(row1, col1, row2, col2):
"""
Return True if the newMaze has a path starting at (row1, col1),
going next to (row2, col2), and ending on the edge.
"""
if newMaze[row2][col2]:
return False #Our path is blocked right at the very beginning.
path.append((row1, col1)) #May be popped off below.
if row2 == 0 or row2 == nrows - 1 or col2 == 0 or col2 == ncols - 1:
#Position (row2, col2) is on an edge. We have solved the maze.
path.append((row2, col2))
return True
newMaze[row1][col1] = True #Make sure we don't come back this way.
if (search(row2, col2, row2, col2 - 1) #leftwards
or search(row2, col2, row2 + 1, col2) #downwards
or search(row2, col2, row2, col2 + 1) #rightwards
or search(row2, col2, row2 - 1, col2)): #upwards
return True
path.pop()
return False
def printPath():
"Print the maze, marking the path with "+" signs."
for row in range(nrows):
for col in range(ncols):
if (row, col) in path:
c = "+"
elif oldMaze[row][col]:
c = "X"
else:
c = "."
print(c, end = "")
print()
#Create a two-dimensional array of bools, with the same dimensions as the maze.
oldMaze = [[c == "X" for c in line] for line in maze.splitlines()]
newMaze = copy.deepcopy(oldMaze)
nrows = len(oldMaze)
ncols = len(oldMaze[0])
path = [] #a list of tuples. Each tuple is (row, col)
if findPath():
printPath()
sys.exit(0)
else:
sys.exit(1)
XXXXXXXXXXXXXXXXXXXX XXXX.XXXXXXXX+++++++ ++XX........X+XXXXXX X+XX.XXXXXXXX+XXX.XX X++++++XX+++++....XX XXXXXX+XX+XXX.XXX.XX XX.XXX+XX+XXX.XXX.XX XX....++++...XXXX.XX XXXXXXXXXXXXXXXX..XX XXXXXXXXXXXXXXXXXXXX