本文記錄了,人工智能中簡單的搜索策略中的路徑搜索策略中的A*算法,來實現迷宮尋路的問題.(這只是一次本人的課外做業)html
完整的程序源碼已經發送到個人Git.這裏只記錄了個人思路和感想以及收穫.git
產生隨機迷宮github
迷宮求解沒有迷宮怎麼能夠呢.而本人是個懶人,每次都要手動輸入迷宮,重複性的工做讓我很不爽.你能夠在程序中用數組定義一個迷宮啊,有強迫症的我,怎麼能夠這樣隨便的要求本身的程序呢.及時求解算法的出來了,可是測試數據有限,仍是讓我很不爽的,因此,乾脆先花一些時間,寫個隨機迷宮的產生吧.算法
遇事先搜索,看看前輩有沒有經驗分享,站在前輩的肩膀上,你能夠少走不少彎路.編程
本人搜索到一篇論文:基於圖的深度遍歷產生隨機迷宮的算法研究,看了之後,發現論文中有不少的錯誤,並且算法也不簡潔,有不少地方徹底能夠很是簡化的,可是非要寫的那麼複雜,生怕別人能夠看懂似得.因此,就按照本身的理解,簡單的實現了隨機迷宮的產生.數組
參考上圖,紅色(起始位置),綠色(終點位置).而我產生隨機迷宮的方法簡單,產生的迷宮有必定的侷限性.如圖所示,從起始位置(最左上角)開始,每次隨機的選取當前節點的右邊或下邊的節點做爲擴展的節點.順便還要判斷一下下一個結點是否越界.經過這種方法會產生一條從矩形的一個點到另外一個點的最短路徑,該條路徑是沒有迴路的路徑,就這樣,當隨機選擇出一條路徑之後,其他的點任意擺佈,是牆是路均可以,最終咱們必定會獲得一條最短的路徑,個人簡單隨機迷宮誕生了.dom
至於更加完善的隨機迷宮的產生,之後有時間了再學習一下.函數
A*算法遍歷學習
若是在這裏介紹這個算法,我感受太沒意思了.人工智能的學習仍是有視頻或者專人的講授比較好,看書真的很枯燥的.這裏我只說實現的過程當中的困難和想法以及收穫.測試
A*算法中重要的由2張表,open表和close表.
open表存放的都是沒有擴展的節點,並且表裏的內容(fn=gn+hn)是按照從小到大排序的。
close表存放的都是已經擴展過的節點,也就說已經遍歷過的節點,這表裏的節點中就存在着最終的路徑。
A*算法先是利用open表和close表找到最終的目標節點,而後倒序從close表裏依次把之前遍歷過的路徑節點找出來,便可獲得完整的路徑。
就想上圖所示的簡單迷宮同樣,開始的時候,會同時擴展右邊和下面的節點,存入open表裏,而後選擇open表中f最小的值,而在這個例子中,選擇的是下面的方塊,因此就這樣沿着紅色箭頭的方向一直擴展下去,直到,發現open表中的2個節點有10和12,這時候,才調轉方向,拋棄12,選擇10((0,1)節點)繼續開始新的遍歷(藍色箭頭的方向),最終找到終點。
找到終點之後,圖中的陰影的結點都在close表裏面,而後,咱們發現路徑中的g從終點到起點是倒序的,h則是升序的。咱們就利用這個特性來實現路徑的輸出。g=10的下一個節點的特徵是(g=g-1&&節點是相鄰的)根據這個判斷,咱們就會很容易的倒序找到完整的路徑了。詳細的實現的方法參見代碼。
個人收穫
花費了一週的時間來實現這個功能,使用的C++語言,並且中間也遇到了很多的困難。當你遇到的困難實在想不起好的解決方法的時候,那麼不妨先放下,作其餘的事情.晚上睡覺的時候,或者吃放走路洗澡的時候,腦子裏想一想就能夠了.解決問題的關鍵是在一瞬間想起來的,實在不行的時候,不妨讓大腦放鬆一下,沒必要心急火燎,容易上火.
bug(1)
堆棧的溢出:之前寫程序的時候沒有遇到過這種問題,曾經都使用過上萬的數據空間,也沒有出現過問題,可是此次的二維數組QT上面使用23*23,也就是迷宮的長和寬就出現這種狀況了。長和寬23*23,那麼頂點總共529個,轉化爲邊的關係則有529*529=279841,額,確實有點大。解決方法很簡單,定義成全局變量或者結構裏面使用指針,函數裏面使用動態的malloc內存分配,就OK了。
bug(2)
翻譯過來就是算數異常,這個bug直到如今我也沒有解決,由於不妨礙我程序的運行,這個bug只在程序調試的時候纔出現。以下:
你們知道程序調試的環境和運行的環境是不同的,就那Qt來講吧,運行的時候MinGW,而調試的時候是GDB,根據圖示,這裏應該出現了k=0的狀況,random產生的隨機數的範圍是0~k-1因此,出錯了。我是這麼想的,也可能錯了,若有看法,請指點。關於此次的程序,使個人GDB也崩潰了,害得我還從新安裝了QT。
bug(3)
參考資料這麼說的:出現了Segmentation fault,基本上的緣由是,非法的內存訪問。例如數組的越界,在循環操做時循環變量的控制問題,也有字符串拷貝時長度溢出,指針指向了非法的空間,還有就是申明一個指針,但卻沒有對其初始化,就直接引用,或者沒有開闢內存空間就釋放內存,因此要檢查申請空間時間的成功。
編程習慣的改進:
說實話程序大了,代碼多了,有時候就不在乎良好的編程習慣了。此次在遇到bug的時候,請教了QQ羣的網友,雖然說最終的問題沒有解決,可是,給我提了很多寶貴的建議。
(1)變量的使用和定義儘可能額緊湊,靠在一塊兒。
(2)最重要的也就是這一句:不要在判斷語句中使用有反作用的語句。何爲反作用?會改變程序狀態的語句。以下:
if(getchar()=='Y'||getchar()=='y') {}
getchar()從緩衝區讀取一個字符,讀一個少一個,那麼讀的過程當中程序的狀態是否是改變了?
好的寫法以下:
char ch=toupper(getchar()); if('Y'==ch) {}
學習的道路艱鉅而漫長.