Maze problem
Problem Description:
Maze can be represented by square matrix [M, n], 0 means that it can pass, 1 means that it cannot pass. If the upper left corner (0, 0) is required to enter, the algorithm is designed to find a path that can go out from the lower right corner (m-1, n-1).
Example figure:
The basic parameters of this example diagram are as follows:
- m: Correspondence
- X-axis n: corresponding to y-axis
- The green line represents the path of the desired output
Algorithm thinking
- Mark current location
- If the position at this time is the end point, it means that you can reach the end point and exit recursion;
Otherwise, there are four possible moving directions, i.e. up, down, left and right. Traverse these four directions. If there are points with adjacent value of 0 in these four directions, mark the current point coordinate as the point coordinate with adjacent value of 0, and enter recursion
Intuitive understanding is as follows:
In the figure above, if there are three points with the adjacent value of 0 in the red circle, they will traverse the three points in turn to seek a certain condition and enter recursion
Implementation process
Marker function
def mark(maze, pos):
"""
Mark function, used to mark the location of the history
: param maze: an M * n-size two-dimensional matrix maze
: param pos: the current position coordinates to be marked POS = (x, y), x = POS [0], y = POS [1]
"""
Make [POS [0] [POS [1]] = 2
Moving function
def move(maze, pos):
"""
The move function is used to test whether the current position can continue to move. The move condition is that the current position is 0
: param maze: an M * n-size two-dimensional matrix maze
: param pos: the current position coordinates to be marked POS = (x, y), x = POS [0], y = POS [1]
: Return: bool type
"""
return maze[pos[0]][pos[1]] == 0
Core function path lookup function
def find_path(maze, start, end):
"""
Path lookup function
: param maze: an M * n-size two-dimensional matrix maze
: param start: start point position coordinates, start = (1,1)
: param end: end coordinates, end = (m, n)
: Return: bool type
"""
Mark (make, start) ා mark the starting position
If start = = end: # the end condition of path lookup (recursion) is to reach the end point
move_path.append(start)
return True
#Before reaching the destination, there are four possible moving directions: up (- 1,0), down (1,0), left (0, - 1), right (0,1)
move_direction = [
(-1, 0), (1, 0), (0, -1), (0, 1)
]
direction = ['↑', '↓', '←', '→']
For I in range (4): # traverse four possible directions
next_ start = (start[0] + move_ direction[i][0], start[1] + move_ Direction [i] [1]) the next possible starting point coordinates
if move(maze, next_ Start): # find out the coordinates of the next starting point that can be moved when there is 0, and enter recursion
if find_path(maze, next_start, end):
#The reason why the starting point coordinates are still added here is that when the next position is the end point or reachable end point, the current position is recorded
move_path.append(start)
path_ direction.append (direction [i]) record the path direction
return True
Return false # if you can't reach the destination after traversing four possible directions, you can't walk out of the maze
So far, the algorithm has been basically completed, and it is not too complicated on the whole
Beautify output
Generating maze matrix with moving path data
def path_maze(maze, directions_map):
"""
Generating maze matrix with moving path
: param maze: an M * n-size two-dimensional matrix maze
:param directions_ Map: a dictionary to record the coordinates of the moving direction, with ↑, ↓, ←, → 4 elements
:return: path_maze
"""
n, m = len(maze[0]), len(maze)
for x in range(1, m-1):
for y in range(1, n-1):
Maze [x] [y] = maze [x] [y] if maze [x] [y]! = 2 else 0 # restore marked 2 to 0
for x in range(m):
for i in range(1, 2 * n - 1, 2):
Maze [x]. Insert (I, ') ා reinitialize maze, and insert three spaces between every two elements
for x in range(1, 2 * m - 1, 2):
maze.insert (x, [','] * (n-1) + [']) #
for direction in directions_map:
for directions_position in directions_map[direction]:
i, j = directions_position
i = 2 * i
j = 2 * j
if direction == "↑":
maze[i - 1][j] = "↑"
if direction == "↓":
maze[i + 1][j] = "↓"
if direction == "←":
maze[i][j] = " ← "
if direction == "→":
maze[i][j + 1] = " → "
return maze
The generated partial data screenshot of maze matrix with path data is as follows:
Beautify printing maze matrix
def print_ Maze (maze, text ='the original maze is: ', end1 =', end2 = ', XS = 0, Xe = 0, ys = 0, ye = 0):'
"""
Output labyrinth matrix, not necessary, can be deleted
: param maze: an M * n-size two-dimensional matrix maze
: param text: output prompt
: param end1: controls the end of each line
: param end2: controls the end of each line
: param XS: control whether to output the top 1 loop, 0 is output, 1 is not output
: param Xe: control whether to output the top 1 loop, 0 is output, 1 is not output
: paramys: control whether to output the top 1 loop, 0 is output, 1 is not output
: param ye: control whether to output the top 1 loop, 0 is output, 1 is not output
"""
print(text)
n, m = len(maze[0]), len(maze)
for x in range(xs, m-xe):
for y in range(ys, n-ye):
print(maze[x][y], end=end1)
print(end=end2)
The final output results are as follows
The effect is acceptable
Complete code
# -*- coding: utf-8 -*-
"""
Created on 2020/1/11 10:51
Author : zxt
File : maze_recursion.py
Software: PyCharm
"""
from random import randint
def mark(maze, pos):
"""
Mark function, used to mark the location of the history
: param maze: an M * n-size two-dimensional matrix maze
: param pos: the current position coordinates to be marked POS = (x, y), x = POS [0], y = POS [1]
"""
Make [POS [0] [POS [1]] = 2
def move(maze, pos):
"""
The move function is used to test whether the current position can continue to move. The move condition is that the current position is 0
: param maze: an M * n-size two-dimensional matrix maze
: param pos: the current position coordinates to be marked POS = (x, y), x = POS [0], y = POS [1]
: Return: bool type
"""
return maze[pos[0]][pos[1]] == 0
move_ Path = [] # record the moving path coordinates that can successfully reach the exit
path_ Direction = [] # record the direction of the moving path that can successfully reach the exit
def find_path(maze, start, end):
"""
Path lookup function
: param maze: an M * n-size two-dimensional matrix maze
: param start: start point position coordinates, start = (1,1)
: param end: end coordinates, end = (m, n)
: Return: bool type
"""
Mark (make, start) ා mark the starting position
If start = = end: # the end condition of path lookup (recursion) is to reach the end point
move_path.append(start)
return True
#Before reaching the destination, there are four possible moving directions: up (- 1,0), down (1,0), left (0, - 1), right (0,1)
move_direction = [
(-1, 0), (1, 0), (0, -1), (0, 1)
]
direction = ['↑', '↓', '←', '→']
For I in range (4): # traverse four possible directions
next_ start = (start[0] + move_ direction[i][0], start[1] + move_ Direction [i] [1]) the next possible starting point coordinates
if move(maze, next_ Start): # find out the coordinates of the next starting point that can be moved when there is 0, and enter recursion
if find_path(maze, next_start, end):
#The reason why the starting point coordinates are still added here is that when the next position is the end point or reachable end point, the current position is recorded
move_path.append(start)
path_ direction.append (direction [i]) record the path direction
return True
Return false # if you can't reach the destination after traversing four possible directions, you can't walk out of the maze
def gen_maze(m, n):
"""
Generating random maze array
: param: int type
: param n: int type
:return: maze
"""
m += 2
N + = 2 # m and N are both + 2 in order to construct the outermost 1
Maze = [[1 for I in range (n)] for J in range (m)] # initialize a two-dimensional matrix with size m * N and all values 1
for x in range(1, m-1):
for y in range(1, n-1):
"""
Here, the value range of X and Y is x ∈ [1, m-1), y ∈ [1, n-1) because we make the outermost layer (all around) of the maze 1
A possible array of 3 * 3 matrices is as follows
[
_ |←--- n:y ---→|
↑ [1, 1, 1, 1, 1],
| [1, 0, 1, 0, 1],
m:x [1, 0, 0, 1, 1],
| [1, 1, 0, 0, 1],
↓ [1, 1, 1, 1, 1]
]
"""
if (x == 1 and y == 1) or (x == m - 2 and y == n - 2):
Maze [x] [y] = 0
else:
Maze [x] [y] = randInt (0,1) # if the outermost layer is all 1, take 0,1 randomly
return maze
def print_ Maze (maze, text ='the original maze is: ', end1 =', end2 = ', XS = 0, Xe = 0, ys = 0, ye = 0):'
"""
Output labyrinth matrix, not necessary, can be deleted
: param maze: an M * n-size two-dimensional matrix maze
: param text: output prompt
: param end1: controls the end of each line
: param end2: controls the end of each line
: param XS: control whether to output the top 1 loop, 0 is output, 1 is not output
: param Xe: control whether to output the top 1 loop, 0 is output, 1 is not output
: paramys: control whether to output the top 1 loop, 0 is output, 1 is not output
: param ye: control whether to output the top 1 loop, 0 is output, 1 is not output
"""
print(text)
n, m = len(maze[0]), len(maze)
for x in range(xs, m-xe):
for y in range(ys, n-ye):
print(maze[x][y], end=end1)
print(end=end2)
def path_maze(maze, directions_map):
"""
Generating maze matrix with moving path
: param maze: an M * n-size two-dimensional matrix maze
:param directions_ Map: a dictionary to record the coordinates of the moving direction, with ↑, ↓, ←, → 4 elements
:return: path_maze
"""
n, m = len(maze[0]), len(maze)
for x in range(1, m-1):
for y in range(1, n-1):
Maze [x] [y] = maze [x] [y] if maze [x] [y]! = 2 else 0 # restore marked 2 to 0
for x in range(m):
for i in range(1, 2 * n - 1, 2):
Maze [x]. Insert (I, ') ා reinitialize maze, and insert three spaces between every two elements
for x in range(1, 2 * m - 1, 2):
maze.insert (x, [','] * (n-1) + [']) #
for direction in directions_map:
for directions_position in directions_map[direction]:
i, j = directions_position
i = 2 * i
j = 2 * j
if direction == "↑":
maze[i - 1][j] = "↑"
if direction == "↓":
maze[i + 1][j] = "↓"
if direction == "←":
maze[i][j] = " ← "
if direction == "→":
maze[i][j + 1] = " → "
return maze
def main():
# maze = gen_maze(m=10, n=12)
maze = \
[
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]Input style matrix, where the outermost layer is surrounded by a ring, in order to facilitate subsequent processing, you can use Gen_ Self generation of maze() function
print_maze(maze)
if find_path(maze, start=(1, 1), end=(10, 12)):
mp = move_path[::-1]
pd = path_direction[::-1]
#Here, both POS [0] and POS [1] need - 1 because there is an outermost 1-ring in the original recursive computation
Print ('coordinate moving order: ', [(POS [0] - 1, POS [1] - 1) for POS in MP])
path_direction_map = {
'↑': [],
'↓': [],
'←': [],
'→': []
}Mapping table of path direction
for i in range(len(pd)):
path_direction_map[pd[i]].append(mp[i])
maze = path_maze(maze, path_direction_map)
print_ Maze (maze, text ='maze moving path is: ', end1 =', end2 = ', XS = 1, Xe = 1, ys = 1, ye = 1)
else:
Print ('There is no solution to this maze ')
if __name__ == '__main__':
main()
The above is the whole content of this article, I hope to help you learn, and I hope you can support developer more.