用栈、回溯算法设计迷宫程序
目錄
1、走迷宮與回溯算法
2、迷宮設計棧扮演的角色
3、Python實現走迷宮
棧的應用有許多,本篇博文著重將棧與回溯(Backtracking)算法結合,設計走迷宮程序。其實回溯算法也是人工智能的一環,通常又稱試錯(try and error)算法,早期設計的計算機象棋游戲、五子棋游戲,大都是使用回溯算法。
1、走迷宮與回溯算法
假設一個簡單的迷宮圖形如下圖所示:
一個迷宮基本上由4種空格組成:
入口:迷宮的入口,筆者上圖用綠色表示。通道:迷宮的通道,筆者上圖用黃色表示。墻壁:迷宮的墻壁,不可通行,筆者上圖用灰色表示。出口:迷宮的出口,筆者上圖用藍色表示。
在走迷宮時,可以上、下、左、右行走,如下圖所示:
走迷宮時每次可以走一步,如果碰到墻壁不能穿越必須走其他方向。
第1步:假設目前位置在入口處,可以參考下圖所示:
第2步:如果依照上、下、左、右原則,應該向上走,但是往上是墻壁,所以必須往下走,然后必須將走過的路標記,此例是用淺綠色標記,所以上述右圖是在迷宮中的新位置,如下圖所示:
第3步:接下來可以發現往上是走過的路,所以只能往下發(依據上、下、左、右原則,先不考慮左、右是墻壁),下方左圖是新的迷宮位置,如下圖所示:
第4步:接下來可以發現往上是走過的路,所以只能往下(依據上、下、左、右原則,先不考慮左、右),下方右圖是新的迷宮位置,如下圖所示:
第5步:現在下、左、右皆是墻壁,所以回到前面走過的路,這一步就是回溯的關鍵,可參考下方左圖,在此圖中筆者將造成回溯的路另外標記,以防止再次造訪,如下圖所示:
第6步:現在上、下皆是走過的路,左邊是墻壁,所以往右走,如下圖所示:
第7步:接下來上、下是墻壁,左邊是走過的路,所以往右走,如下圖所示:
第8步:由于上方有路所以往上走,如下圖所示:
第9步:由于上方有路所以往上走,如下圖所示:
第10步:由于上、左、右皆是墻壁,所以回溯到前一個位置,如下圖所示:
第11步:由于上、下是走過的路,左邊是墻壁,所以往右走,如下圖所示:
第12步:由于上、下、右是墻壁,所以回溯到先前位置,如下圖所示:
第13步:由于左邊是墻壁,所以回溯到先前走過的位置,如下圖所示:
第14步:下方有通道,所以往下走,如下圖所示:
第15步:上方是走過的位置,左方和下方是墻壁,所以往右走,如下圖所示:
2、迷宮設計棧扮演的角色
上面介紹到,在第2步使用淺綠色標記走過的路,真實程序設計可以用棧存儲走過的路。
第5步使用回溯算法,所謂的回溯就是走以前走過的路,因為是將走過的路使用棧(stack)存儲,基于后進先出原則,可以pop出前一步路徑,這也是回溯的重點。當走完第4步時,
迷宮與棧圖形如下所示:
上述迷宮位置使用程序語言的(row,column)標記,所以第5步要使用回溯時,可以從棧pop出(3,1)坐標,回到(3,1)位置,結果如下所示所示:
3、Python實現走迷宮
使用Python設計走迷宮可以使用二維的列表,0代表通道、1代表墻壁,至于起點和終點也可以用0代表。
使用上述第一部分的迷宮實例,其中所經過的路徑用2表示,經過會造成無路可走的路徑用3表示。程序第41行前2個參數是迷宮的入口,后2個參數是迷宮的出口,實現代碼如下所示:
# ch11_1.py
from pprint import pprint
maze = [ # 迷宮地圖[1, 1, 1, 1, 1, 1],[1, 0, 1, 0, 1, 1],[1, 0, 1, 0, 0, 1],[1, 0, 0, 0, 1, 1],[1, 0, 1, 0, 0, 1],[1, 1, 1, 1, 1, 1]]
directions = [ # 使用列表設計走迷宮方向lambda x, y: (x-1, y), # 往上走lambda x, y: (x+1, y), # 往下走lambda x, y: (x, y-1), # 往左走lambda x, y: (x, y+1), # 往右走 ]
def maze_solve(x, y, goal_x, goal_y):''' 解迷宮程序 x, y是迷宮入口, goal_x, goal_y是迷宮出口'''maze[x][y] = 2stack = [] # 建立路徑棧stack.append((x, y)) # 將路徑push入棧print('迷宮開始')while (len(stack) > 0):cur = stack[-1] # 目前位置if cur[0] == goal_x and cur[1] == goal_y:print('抵達出口')return True # 抵達出口返回True for dir in directions: # 依上, 下, 左, 右優先次序走此迷宮next = dir(cur[0], cur[1])if maze[next[0]][next[1]] == 0: # 如果是通道可以走stack.append(next)maze[next[0]][next[1]] = 2 # 用2標記走過的路breakelse: # 如果進入死路, 則回溯maze[cur[0]][cur[1]] = 3 # 標記死路stack.pop() # 回溯 else:print("沒有路徑")return Falsemaze_solve(1, 1, 4, 4)
pprint(maze) # 跳行顯示元素
運行效果如下所示:
項目源碼下載:用棧、回溯算法設計迷宮程序
本文來源:清華計算機學堂
總結
以上是生活随笔為你收集整理的用栈、回溯算法设计迷宫程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python+OpenCV检测灯光亮点
- 下一篇: 力扣(LeetCode)刷题,简单+中等