建议用Thonny一步步调试观察过程。有时候自己先实现再看书,能领悟的更深刻。直接看作者代码不一定效果最好。

# @Time : 8/16/21 2:23 PM 

# @Author : LY(Zhenghui.Lyu)

# @File : aa.py 

# @Software: PyCharm

# @Email: lzhfootmark@163.com

from collections import deque


def migong(maze):
    length = len(maze)  # 行数
    width = len(maze[0])  # 列数
    # 建立二维数组,由0填充,表示是否访问,初始都未访问,访问一个节点后,设置位置为1
    visited = [[0 for _ in range(width)] for _ in range(length)]
    step = [[(-1, -1) for _ in range(width)] for _ in range(length)]  # ?父子关系
    direction = [[1, 0], [-1, 0], [0, -1], [0, 1]]  # 右左上下四个方向
    queue = deque([(0, 0)])  # 初始坐标
    visited[0][0] = 1  # 设置已访问
    result = []  # 最终如果有路的返回值
    while queue:
        x, y = queue.popleft()  # 弹出队列首个元素
        if x == length - 1 and y == width - 1:  # 到达右下角
            break
        for d in direction:
            x1 = x + d[0]
            y1 = y + d[1]
            if x1 < 0 or y1 < 0 or x1 >= length or y1 >= width or \
                    visited[x1][y1] == 1 or maze[x1][y1] == 1:  # 超出边界或已访问的点或不能到达
                continue
            step[x1][y1] = (x, y)  # 每个点的step坐标,代表了来到此点的父坐标x,y点
            visited[x1][y1] = 1
            queue.append((x1, y1))  # 将可访问方向的节点加入到队列当中
    if step[length - 1][width - 1] == (-1, -1):  # 若右下角的点对应的step未更新,证明未达到此点的路径,返回False
        return False
    # 如果有可达路径
    re_x = length - 1
    re_y = width - 1
    result.append((length - 1, width - 1))
    while re_x and re_y:
        re_x, re_y = step[re_x][re_y]
        result.append((re_x, re_y))  # result为从尾到头
    return result[::-1]  # 反方向 从头到尾


maze1 = [
    [0, 1, 0, 0, 0],
    [0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0],
    [0, 0, 0, 1, 0]]
maze2 = [
    [0, 1, 1, 0, 0],
    [0, 1, 0, 1, 0],
    [0, 0, 1, 0, 0],
    [0, 1, 1, 1, 1],
    [0, 0, 0, 1, 0]]
print(migong(maze1))
# print(migong(maze2))