1. 程式人生 > >貪吃蛇 AI 的實現 snake AI

貪吃蛇 AI 的實現 snake AI

1.首先看下這個非常在微博上很火的貪吃蛇gif

這次我們嘗試用程式碼來模擬下,說不定上面這個圖就是計算機搞的。

2.講貪吃蛇AI之前,我們先看下貪吃蛇移動的特點

物理上給人的感覺是整個貪吃蛇往右移了一步,在貪吃蛇非常長的情況下給人的感覺移一步要做很多事情。但是在計算機中我們可以簡單的考慮貪吃蛇的移動,假設用一個數組來儲存所有組成貪吃蛇的格子,那麼移動一步,就是把將來的格子插入到這個陣列的頭部,然後再去掉這個陣列的最後一個元素。我們只做兩件事情,就完成了一整條蛇的移動!往下看之前,再仔細考慮下移動這個問題。

在說貪吃蛇AI之前,我們要考慮一個問題:怎樣保證貪吃蛇永遠不死?我們知道無論往那個方向前進一步,尾巴的格子都會空出來,那麼追著貪吃蛇的尾巴移動,就能保證貪吃蛇永遠不死!

3.尋路演算法之A Star

貪吃蛇一般情況下要找一個最短路線去吃蘋果,這個時候A star尋路演算法就派上用場了,如果你對A Star 演算法還不瞭解,可以先看下這篇文章:《Cocos2d-x 尋路演算法之三 A Star》 。這裡用A Star 需要特別注意兩個問題:1.整個蛇的身體是不可接觸的格子的,要排除掉。2.因為貪吃蛇移動是一個動態的過程,所以每走一步,要重新進行尋路,而不是一次尋路完,走完路線,因為尾巴的位置會不斷的空出來。

4.單純使用尋路演算法遇到的問題

4.1會進入死衚衕

黃色的是貪吃蛇的頭部,紅色是我們要吃的東西,根據尋路演算法,黑色的就是最短路線,可以在腦子裡腦補下,吃完這個東西,貪吃蛇就掛了!

4.2 找不到路線

在貪吃蛇足夠長的情況下,蘋果可能會在蛇身體包圍的圈中,看上圖,黃色表示頭部,那麼蛇就找不到路線了!

4.3 一味的最短路線吃東西,留下太多洞

我們看下這張圖,紅色的表示現在出現的蘋果,橙色的表示吃完紅色的蘋果後,蘋果可能出現的位置,如果我們簡單的用最短路線去吃紅色的,即無腦往左走,那麼橙色的就在會出現在蛇的包圍圈中,將來要吃這個就非常不利,要走很多步。

這個時候比較好的走法是下圖:

儘可能的多繞,儘可能地把空白地方填完,而不是以最短路線去吃,要為將來打算。

5. 貪吃蛇的最佳無腦模式

一想到4.3的問題,我就覺得貪吃蛇AI是非常難的一個問題,難道還是設及到“

一筆畫問題”,那就太難了。不過還好,玩了這麼多局的貪吃蛇,我發現一個無腦模式,可以填滿整個遊戲區域。見下圖:

就是在最後一行空出來,留做逃生的路線,然後像彈簧一樣無腦向右推進,吃完後,從底部繞回最左邊,繼續這樣的策略,直到填滿整個遊戲區域。不知道讀者懂不懂這樣的策略。

6.開始講我的貪吃蛇AI實現了

一定要先理解上面的東西,才好繼續往下看。我們知道追著尾巴跑,蛇就不會死,所以我們以最短路線去吃蘋果時,要給自己留條後路,策略1.如果吃完蘋果還可以找到到自己尾巴路線的話,才去吃蘋果。

下面給出的是虛擬碼:

var canFindPath= false;                              //可以找到吃蘋果的路線
var canFindTail = false;                             //可以找到自己尾巴的路線
canFindPath = startPathFinding();                    //開始尋找路線
        if(canFindPath){                             //如果可以找到吃蘋果的路線
            moveSnake()                              //移動一條看不見的貪吃蛇去吃
            canFindTail = startPathFinding();        //嘗試找自己尾巴路線
            if(canFindTail){                         //如果可以找到自己尾巴路線
                return safePathCell;                 //返回吃蘋果路線的第一步
            }
        }

策略2.如果找不到吃蘋果路線或者吃完蘋果後,會發生找不到自己尾巴路線的話,那麼就在頭部的周圍找一個格子,這個格子要滿足兩個條件,條件1,走完這個格子要能找到到尾巴的路線,條件2,這個格子到蘋果的距離是最遠的。

策略2中的條件1,我們肯定是能找的到的,因為我們的AI的基礎都是基於策略1。

策略2的虛擬碼如下:

var canFindPath= false;                              //可以找到吃蘋果的路線
var canFindTail = false;                             //可以找到自己尾巴的路線
canFindPath = startPathFinding();                    //開始尋找路線
        if(canFindPath){                             //如果可以找到吃蘋果的路線
            moveSnake()                              //移動一條看不見的貪吃蛇去吃
            canFindTail = startPathFinding();        //嘗試找自己尾巴路線
            if(canFindTail){                         //如果可以找到自己尾巴路線
                return safePathCell;                 //返回吃蘋果路線的第一步
            }
        }
if(canFindPath == false || canFindTail == false ){
            return getACellThatIsFarthestToGoal();
   }

注意下策略2中的條件2,我們沒有用什麼高深的演算法,我們僅僅是把蛇往一個到蘋果最遠的格子移動,執行起我們的貪吃蛇,我們發現貪吃蛇AI可以工作了!!這個就有點哲學的味道了,看似在往遠離目標的方向上行動,沒有想到蛇剛好自己在繞了,繞掉了大部分的身體後,就可以用策略1找到路線了。

看了好幾遍自己貪吃蛇AI的移動,不可避免的會有4.3提到的這個問題,後期留下太多洞了,貪吃蛇要追隨自己尾巴,移動很久才能吃到一個蘋果,我們知道有標題5 提到的無腦模式,我們在想,要不後期就不要以最短路線去吃蘋果,而是無腦繞,來吃,這樣反而會快些!

怎樣才能產生無腦繞的效果呢?我們發現策略2中的條件2會產生這樣的效果,在後期,我們就走離蘋果最遠的格子且這個格子能有到達尾巴的路線,我們發現這樣走無意中就會產生這樣的無腦繞效果!有點像圓。圓心就是目標,最終還算會不斷地接近目標的!

這樣算是貪吃蛇遊戲的後期呢?我這裡就簡單如果蛇的長度等於整個遊戲格子數量的一半,就算到後期了。

7.最終貪吃蛇AI效果圖:

8.貪吃蛇AI線上試玩地址

用Cocos2d html5實現的。

9.貪吃蛇snake html5 下載

github:  https://github.com/waitingfy/snake