回溯法解決迷宮問題(加turtle可視化)

前言:好久好久沒有更新博客了…今天乍一看竟然還漲了粉 不好意思的出來更新一下博客~
運行界面:

迷宮通過list賦值,採用0,1標記,即 0 表示通路,1表示牆
建立dirs序列,表示上下左右四個方向
可視化部分可以採用不同顏色標記實現路徑的呈現
總的來說 功能實現包括三個部分:
  1. 衝突檢測【當座標在迷宮範圍內且相應值是可通行狀態時 返回不衝突】
  2. 主函數部分
  3. 可視化部分
代碼實現:
import copy,turtle
# 迷宮(1是牆,0是通路)
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,0,0,1,1,1,1,0,1],\
          [1,0,1,0,0,0,1,0,0,0,0,0,0,1],\
          [1,1,1,1,1,1,1,1,1,1,1,1,0,0]]
row = len(maze)# 行
column = len(maze[0])#列

n = 40  # 畫圖的每行間隔,小格子邊長
x = -300  # x初始值
y = 200  # x初始值

entry = (1,0) #迷宮入口
exit = (row-1,column-1)# 迷宮出口
path = [entry] #一個解路徑
paths = [] #一組解

# 移動的方向 上下, 左右
dirs = [(0,1),(0,-1),(1,0),(-1,0)]

# 衝突檢測
def conflict(now_x,now_y): # 當前座標x,y
    #如果當前座標在maze範圍內,且可通行 返回不衝突
    if 0<= now_x <row and 0<= now_y<column and maze[now_x][now_y] == 0:
        return  False
    return True # 否則 返回衝突

def main(now_x,now_y):
    global maze,path,paths,dirs,entry,row,column
    if (now_x,now_y)==exit:
        paths.append(path[:])
    else:
        for d in dirs:# 遍歷四個方向
            new_x,new_y = now_x+d[0] ,now_y+d[1]
            path.append((new_x,new_y))# 新座標入棧
            if not conflict(new_x,new_y):
                maze[new_x][new_y] = 2 # 標記 2
                main(new_x,new_y) # 回溯
                maze[new_x][new_y] = 0 # 回溯 恢復
            path.pop() # 回溯 出棧

#解的可視化
"""
copy.copy 淺拷貝 只拷貝父對象,不會拷貝對象的內部的子對象。
copy.deepcopy 深拷貝 拷貝對象及其子對象
"""
step = []
def show(path):
    global maze
    maze_2 = copy.deepcopy(maze) # 深拷貝
    for p in path:
        maze_2[p[0]][p[1]] = 2 # 通路
    draw(maze_2)
    turtle.done()

def draw_square(length: float, fill_color: str):
    """
    畫正方形並填充
    :param length: 邊長
    :param fill_color: 填充顏色
    :return: 無
    """
    turtle.pendown()
    turtle.begin_fill()
    turtle.fillcolor(fill_color)
    for index in range(4):
        turtle.forward(length)
        turtle.left(90)
    turtle.end_fill()
    turtle.penup()

def draw(maze_0):
    for i in range(row):
        for j in range(column):
            turtle.goto(x + j * n, y - i * n)
            if maze_0[i][j] == 1:  # 牆
                draw_square(n, "black")
            elif maze_0[i][j] == 0: # 可通行部分
                draw_square(n, "white")
            else:           # 行走部分
                draw_square(n-10,"pink")


if __name__ == '__main__':
    turtle.speed(200)
    turtle.pensize(2)
    turtle.setup(width=0.5, height=0.75, startx=30, starty=100)
    turtle.penup()
    (origin_x,origin_y) = entry
    main(origin_x,origin_y)
    print("一共有 "+str(len(paths))+" 條路徑")
    if len(paths)!=0:
        show(paths[-1])# 手動修改查看不同走迷宮方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章