[7 – 遊戲邏輯] 電腦搜尋路徑



判斷是否存在任一條路徑

在這個連連看遊戲中,是有可能存在死局的,也就是沒有任何兩個圖案可以用兩個轉彎內的線連接起來時。這時我們需要讓電腦能夠自動判斷這種狀況並做出反應,讓玩家可以更明確知道是否有可行的路徑。
那要如何判斷是否存在任一可能路徑呢?有幾個條件:

  • 第一點:電腦能夠判斷連線是否合法
  • 第二點:遍歷所有可能的圖案去確認是否存在可能路徑

第一點在上一篇我們已經做到了,因此在這一篇,我們要找到一個較省時的方式去遍歷所有可能的連線是否存在。

搜尋方法構思

下圖是我在思考電腦自動搜尋時的搜尋邏輯:

因為我希望電腦在搜尋時,能夠避免搜尋已搜尋過的路徑,因此應要紀錄已搜尋過的組合有那些。
為了方便紀錄與判別是否已搜尋過,我決定以圖案來做搜尋依據,由最盤面最左上開始,每遇到一個符號,就判別該符號是否有任何可能可以連線的兩個圖案。
所以我們會需要下面幾件事情:

  • 遍歷盤面,並在找到路徑時停止搜尋
  • 紀錄已搜尋過的符號並避免重複搜尋
  • 列出現有符號可能兩兩連線的所有排列組合
  • 判別兩點間能否連線

程式實作

第四點我們在上一篇文章裡已經完成該功能,因此現在我們應該要做的有1~3項,這部份的程式碼如下:

getPositionByValue這個函數主要是要取得盤面上所有這個符號的位置,方法內容如下:

getPairNumPermutations這個函數則是在列出,相同圖案任選2個所有可能的排列組合
如果傳入的是4,也就是C4取2=6,一共會有六種排序的可能性。
查一下維基百科,裡面有相關的解釋:排列組合
因為兩點間的路徑不會受到先後順序的影響而影響是否能連線,並且相同的點不可連線,這邊我一律讓第一個數字(index)小於第二個數字(index),因此用這個判斷式i != j && i <= j來排除重覆的組合。
用下面的函數,若是同樣的符號有4個,則輸入值為4,輸出值會是[[0,1],[0,2],[0,3],[1,2],[1,3],[2,3]]


可行路徑提示

上面做完了電腦自動搜尋路徑的功能,可以使用在兩個地方,第一個地方是,當盤面沒有任何路徑可以走時,要自動重整盤面。
這部份的程式碼如下:

而重整盤面的程式碼如下:

首先先把現有的所有圖案都搜集起來放在一個陣列裡,也就是getAllValueInBoard()所做的事情。
然後再隨機打亂陣列排序,再依序填入盤面上所有有圖案的格子內,就可以達到重整盤面但是不影響到空格的位置。

今日成果

連連看遊戲邏輯至此已大致完成囉!下一篇開始我們會實際開始製作一款實際上具有畫面、音效、特效等真正的網頁連連看遊戲

LIVE DEMO: 今日成果展示
完整程式碼可由此下載:ironman20181022

[6 – 遊戲邏輯] 連線消除程式撰寫

主要遊戲流程

連連看點選兩個圖案後,可消除的邏輯是:

  • 兩個所點擊到的圖案相同
  • 連線不超過兩個轉彎

因此我們先來寫遊戲主流程的部份,玩家會先點第一個圖案,代表他想要消除這個圖案,接著再消第二個圖案,這時再來判斷是否符合可消除,這部份的流程圖如下:

撰寫的程式碼如下

判斷所選圖案是否相同

在上面的程式碼中,可以看到我們用board.hasSameValue($scope.select1, $scope.select2)來判斷所選的圖是是否相同。我們可以Board的類別增加public hasSameValue(point1: Point, point2: Point): boolean如下:

連線邏輯撰寫

新建一個類別Path內容如下

新增類別Board

今日成果:

Live Demo:今日成果展示
今天的專案可至此下載:ironman20181021

[5 – 遊戲邏輯] 圖形連線消除邏輯發想

搜尋邏輯思考

在連連看裡面,連線的線條不可超過兩個轉彎處,兩個轉彎處的意思,代表連接的線最多只能由三條直線來組成。

這時候我們來思考該如何找出這兩點間所存在的那條線。先觀察一下棋盤,最多三條直線,代表有可能是一條直線、兩條直線或三條直線來做連接的。
不論如何,兩個點之間的那條線,一定一邊是從第一個點(A)開始,到另一個點(B)結束,因此,可以視為這兩個點之中,有可能存在A點連出的的(C)點B點連出的(D)點,來形成連線。

由上圖我們可以觀察出,A點連出的的(C)點絕對是和開始的(A)點在同一行或同一列,B點連出的(D)點絕對是和結束的點(B)點在同一行或同一列

尋找可能的線的模型

首先,我們來畫出所有有可能連出來的線圖形狀,再來思考該如何去撰寫消除邏輯。

判斷是否存在此圖形的連線

從上面的圖型我們先來分析向左、上、下、右的邊消的情況,要如何去搜尋可能存在的路徑。
讓我們先看這張圖

圖中的(A)為起始點,(B)為終點,(C)為(A)點最左能走到的點,(D)為(B)點最左能走到的點。則淡紅色漸層的部份,就是存在著可能的路徑。
這個可能連線的區塊的座標應為: 左上(A.x,D.y)、右上(A.x, B.y)、右下(D.x,D.y)、左下(B.x,B.y)。
我們應該要取A_C與B_D的橫向座標(y)中,有交集的部份。

因此這部份的邏輯程式應為

同樣的模型可以套用在向左、向上、向右、向下。
我們可以發現,左右直連可視為A點與C點相疊、B點與D點相疊的向上/向下消除,上下直連亦同。轉折連接可視為A與C或者B與D其中有兩個相疊,另兩個不相疊。都可以用相同的演算法來找出路徑

無法用相同的方式找出來的圖形有這兩個

先來繪製出有可能可以連線的區域

由上圖可知,我們需要找A、B點之間在左邊的(A)點往右可走最多的那個(C)點,然後找A、B點之間在右邊的(B)點往左走最多的(D)點。
然後取出A_C與B_D中y有交集的地方,為有可能可以連線的區域

這部份的邏輯程式碼為