用Python写一个走迷宫的小程序(图形化:matplotlib,dfs,prim)

不要脸的放到了Github上面,嘿嘿。

Github:https://github.com/Radium1209/Maze

先看一下动态效果图(慢放):

所需要的库:

matplotlib

# for Linux
# python 3+
$ sudo apt-get install python3-matplotlib

# python 2+
$ sudo apt-get install python-matplotlib

numpy

# for Linux
# python 3+
$ sudo pip3 install numpy

# python 2+
$ sudo pip install numpy

首先生成迷宫:

主要用了两个算法:Prim和dfs

总结:DFS生成的比较像真正的迷宫,所以默认用了DFS生成迷宫

具体参考:https://blog.csdn.net/juzihongle1/article/details/73135920

先输入n,m,会生成一个迷宫(prim生成),然后会动态的走完整个迷宫。

走迷宫用的是bfs(dfs)算法,具体不多说了,关键难点在于记录路径:

我是用一个path二维数组来记录路径的,每一个位置存的是这个位置的上一个位置,在输出的时候倒着从最后一个点回溯到第一个点存入一个栈,最后正常出栈就是路径了。

画路径:有上,下,左,右,上左,上右,下左,下右,左下,左上,右上,右下12中情况分类讨论(实在是太麻烦了)。

最后用pyinstaller生成exe

教程:https://blog.csdn.net/Radium_1209/article/details/82939368

全部代码(已更新,添加了DFS寻路):

import random
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.cm as cm
from collections import deque

def show_maze(Maze):
    plt.imshow(Maze, cmap=cm.Wistia_r, interpolation='none')
    # plt.ion()
    plt.show()


def find_path_bfs(image, M):
    path = np.zeros((num_rows, num_cols, 2))
    vis = np.zeros((num_rows, num_cols))
    vis[0][0] = 1
    Queue = deque()
    Queue.append((0, 0))
    while(Queue):
        temp = Queue.popleft()
        nr = temp[0]
        nc = temp[1]

        if (nc == num_cols - 1) and (nr == num_rows - 1):
            show_path(image, path)
            break
        if (nc > 0) and (not vis[nr][nc - 1]) and (M[nr][nc][0]):
            vis[nr][nc] = 1
            Queue.append((nr, nc - 1))
            path[nr][nc - 1][0] = nr
            path[nr][nc - 1][1] = nc
        if (nr > 0) and (not vis[nr - 1][nc]) and (M[nr][nc][1]):
            vis[nr][nc] = 1
            Queue.append((nr - 1, nc))
            path[nr - 1][nc][0] = nr
            path[nr - 1][nc][1] = nc
        if (nc < num_cols - 1) and (not vis[nr][nc + 1]) and (M[nr][nc][2]):
            vis[nr][nc] = 1
            Queue.append((nr, nc + 1))
            path[nr][nc + 1][0] = nr
            path[nr][nc + 1][1] = nc
        if (nr < num_rows - 1) and (not vis[nr + 1][nc]) and (M[nr][nc][3]):
            vis[nr][nc] = 1
            Queue.append((nr + 1, nc))
            path[nr + 1][nc][0] = nr
            path[nr + 1][nc][1] = nc


def find_path_dfs(image, M):
    path = np.zeros((num_rows, num_cols, 2))
    vis = np.zeros((num_rows, num_cols))
    vis[0][0] = 1
    def dfs(pos):
        nr = pos[0];
        nc = pos[1];
        if (nc == num_cols - 1) and (nr == num_rows - 1):
            show_path(image, path)
            return
        if (nc > 0) and (not vis[nr][nc - 1]) and (M[nr][nc][0]):
            vis[nr][nc] = 1
            path[nr][nc - 1][0] = nr
            path[nr][nc - 1][1] = nc
            dfs((nr, nc - 1))
            vis[nr][nc] = 0
        if (nr > 0) and (not vis[nr - 1][nc]) and (M[nr][nc][1]):
            vis[nr][nc] = 1
            path[nr - 1][nc][0] = nr
            path[nr - 1][nc][1] = nc
            dfs((nr - 1, nc))
            vis[nr][nc] = 0
        if (nc < num_cols - 1) and (not vis[nr][nc + 1]) and (M[nr][nc][2]):
            vis[nr][nc] = 1
            path[nr][nc + 1][0] = nr
            path[nr][nc + 1][1] = nc
            dfs((nr, nc + 1))
            vis[nr][nc] = 0
        if (nr < num_rows - 1) and (not vis[nr + 1][nc]) and (M[nr][nc][3]):
            path[nr + 1][nc][0] = nr
            path[nr + 1][nc][1] = nc
            vis[nr][nc] = 1
            dfs((nr + 1, nc))
            vis[nr][nc] = 0

    dfs((0,0))


def Create_maze_dfs():
    M = np.zeros((num_rows, num_cols, 5))
    image = np.zeros((num_rows * 10, num_cols * 10))

    r = 0
    c = 0
    history = [(r, c)]

    while history:
        M[r, c, 4] = 1
        check = []
        if c > 0 and M[r, c - 1, 4] == 0:
            check.append('L')
        if r > 0 and M[r - 1, c, 4] == 0:
            check.append('U')
        if c < num_cols - 1 and M[r, c + 1, 4] == 0:
            check.append('R')
        if r < num_rows - 1 and M[r + 1, c, 4] == 0:
            check.append('D')

        if len(check):
            history.append([r, c])
            move_direction = random.choice(check)
            if move_direction == 'L':
                M[r, c, 0] = 1
                c = c - 1
                M[r, c, 2] = 1
            if move_direction == 'U':
                M[r, c, 1] = 1
                r = r - 1
                M[r, c, 3] = 1
            if move_direction == 'R':
                M[r, c, 2] = 1
                c = c + 1
                M[r, c, 0] = 1
            if move_direction == 'D':
                M[r, c, 3] = 1
                r = r + 1
                M[r, c, 1] = 1
        else:
            r, c = history.pop()

    M[0, 0, 0] = 1
    M[num_rows - 1, num_cols - 1, 2] = 1

    for row in range(0, num_rows):
        for col in range(0, num_cols):
            cell_data = M[row, col]
            for i in range(10 * row + 2, 10 * row + 8):
                image[i, range(10 * col + 2, 10 * col + 8)] = 255
            if cell_data[0] == 1:
                image[range(10 * row + 2, 10 * row + 8), 10 * col] = 255
                image[range(10 * row + 2, 10 * row + 8), 10 * col + 1] = 255
            if cell_data[1] == 1:
                image[10 * row, range(10 * col + 2, 10 * col + 8)] = 255
                image[10 * row + 1, range(10 * col + 2, 10 * col + 8)] = 255
            if cell_data[2] == 1:
                image[range(10 * row + 2, 10 * row + 8), 10 * col + 9] = 255
                image[range(10 * row + 2, 10 * row + 8), 10 * col + 8] = 255
            if cell_data[3] == 1:
                image[10 * row + 9, range(10 * col + 2, 10 * col + 8)] = 255
                image[10 * row + 8, range(10 * col + 2, 10 * col + 8)] = 255
    return M, image


def Create_maze_prim():
    M = np.zeros((num_rows, num_cols, 5))
    image = np.zeros((num_rows * 10, num_cols * 10))

    r = 0
    c = 0
    history = [(r, c)]

    while history:
        r, c = random.choice(history)
        M[r, c, 4] = 1
        history.remove((r, c))
        check = []

        if c > 0:
            if M[r, c - 1, 4] == 1:
                check.append('L')
            elif M[r, c - 1, 4] == 0:
                history.append((r, c - 1))
                M[r, c - 1, 4] = 2
        if r > 0:
            if M[r - 1, c, 4] == 1:
                check.append('U')
            elif M[r - 1, c, 4] == 0:
                history.append((r - 1, c))
                M[r - 1, c, 4] = 2
        if c < num_cols - 1:
            if M[r, c + 1, 4] == 1:
                check.append('R')
            elif M[r, c + 1, 4] == 0:
                history.append((r, c + 1))
                M[r, c + 1, 4] = 2
        if r < num_rows - 1:
            if M[r + 1, c, 4] == 1:
                check.append('D')
            elif M[r + 1, c, 4] == 0:
                history.append((r + 1, c))
                M[r + 1, c, 4] = 2

        if len(check):
            move_direction = random.choice(check)
            if move_direction == 'L':
                M[r, c, 0] = 1
                c = c - 1
                M[r, c, 2] = 1
            if move_direction == 'U':
                M[r, c, 1] = 1
                r = r - 1
                M[r, c, 3] = 1
            if move_direction == 'R':
                M[r, c, 2] = 1
                c = c + 1
                M[r, c, 0] = 1
            if move_direction == 'D':
                M[r, c, 3] = 1
                r = r + 1
                M[r, c, 1] = 1

    M[0, 0, 0] = 1
    M[num_rows - 1, num_cols - 1, 2] = 1

    for row in range(0, num_rows):
        for col in range(0, num_cols):
            cell_data = M[row, col]
            for i in range(10 * row + 2, 10 * row + 8):
                image[i, range(10 * col + 2, 10 * col + 8)] = 255
            if cell_data[0] == 1:
                image[range(10 * row + 2, 10 * row + 8), 10 * col] = 255
                image[range(10 * row + 2, 10 * row + 8), 10 * col + 1] = 255
            if cell_data[1] == 1:
                image[10 * row, range(10 * col + 2, 10 * col + 8)] = 255
                image[10 * row + 1, range(10 * col + 2, 10 * col + 8)] = 255
            if cell_data[2] == 1:
                image[range(10 * row + 2, 10 * row + 8), 10 * col + 9] = 255
                image[range(10 * row + 2, 10 * row + 8), 10 * col + 8] = 255
            if cell_data[3] == 1:
                image[10 * row + 9, range(10 * col + 2, 10 * col + 8)] = 255
                image[10 * row + 8, range(10 * col + 2, 10 * col + 8)] = 255
    return M, image


def show_path(image, path):
    plt.imshow(image, cmap=cm.Wistia_r, interpolation='none')
    plt.ion()
    plt.pause(2)
    str = ""
    stack = []
    nr = num_rows - 1
    nc = num_cols - 1
    stack.append((nr, nc + 1))
    stack.append((nr, nc))
    while nr or nc:
        tr = nr
        tc = nc
        nr = (int)(path[tr][tc][0])
        nc = (int)(path[tr][tc][1])
        stack.append((nr, nc))
    # stack.append((num_rows, num_cols))
    pr = 0
    pc = 0
    dir = 2
    color_num = 150
    while(stack):
        temp = stack.pop()
        nr = temp[0]
        nc = temp[1]
        if nr or nc:
            if (nr == pr):
                if (nc > pc):
                    # print("R")
                    if (dir == 2):
                        image[10 * pr + 4,
                              range(10 * pc + 0, 10 * pc + 10)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 0, 10 * pc + 10)] = color_num
                    elif (dir == 1):
                        image[10 * pr + 4,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 5] = color_num
                    elif (dir == 3):
                        image[10 * pr + 4,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 5] = color_num
                    dir = 2
                else:
                    # print("L")
                    if (dir == 0):
                        image[10 * pr + 4,
                              range(10 * pc + 0, 10 * pc + 10)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 0, 10 * pc + 10)] = color_num
                    elif (dir == 1):
                        image[10 * pr + 4,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 5] = color_num
                    elif (dir == 3):
                        image[10 * pr + 4,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 5] = color_num
                    dir = 0
            elif (nc == pc):
                if (nr > pr):
                    # print("D")
                    if (dir == 3):
                        image[range(10 * pr + 0, 10 * pr + 10),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 0, 10 * pr + 10),
                              10 * pc + 5] = color_num
                    elif (dir == 0):
                        image[10 * pr + 4,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 5] = color_num
                    elif (dir == 2):
                        image[10 * pr + 4,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 4, 10 * pr + 10),
                              10 * pc + 5] = color_num
                    dir = 3
                else:
                    # print("U")
                    if (dir == 1):
                        image[range(10 * pr + 0, 10 * pr + 10),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 0, 10 * pr + 10),
                              10 * pc + 5] = color_num
                    elif (dir == 0):
                        image[10 * pr + 4,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 4, 10 * pc + 10)] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 5] = color_num
                    elif (dir == 2):
                        image[10 * pr + 4,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[10 * pr + 5,
                              range(10 * pc + 0, 10 * pc + 6)] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 4] = color_num
                        image[range(10 * pr + 0, 10 * pr + 6),
                              10 * pc + 5] = color_num
                    dir = 1
            pr = nr
            pc = nc
            plt.clf()
            plt.imshow(image, cmap=cm.Wistia_r, interpolation='none')
            # plt.ion()
            if (stack):
                plt.ion()
                plt.pause(0.03 / (num_cols * num_rows / 100))
            else:
                plt.ioff()
                plt.show()
                # plt.pause(1000)


if __name__ == '__main__':
    num_rows = int(input("Please input rows: "))
    num_cols = int(input("Please input columns: "))

    path = np.zeros((num_rows, num_cols, 2))
    M = np.zeros((num_rows, num_cols, 5))
    image = np.zeros((num_rows * 10, num_cols * 10))
    # row_image = np.zeros((num_rows * 10, num_cols * 10))

    # M, image = Create_maze_prim()
    M, image = Create_maze_dfs()

    # show_maze(image)
    # find_path_bfs(image, M)
    find_path_dfs(image, M)

    # show_path(image, path)
发布了113 篇原创文章 · 获赞 30 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Radium_1209/article/details/83051436