接前文(專題:連連看-戊-核心算法(一)),開始動手寫代碼后就會發現實際上上面一篇的偽碼還是有很多問題的,我們一步步的來。先來個圖。
看圖一中甲元素要消元的情況。甲的出路有兩條,向右或向下,也就是說如果甲是發起方它可以發起向右或向下的探路。再看乙丙,乙有三條出路,丙四個方向都可以走,不過要注意,以上說的都是對發起方來講的,想想,如果是接收方情況還如此嗎?不是。比如對丙來說吧,它是個接收方,比如從它的上方來了一次探路,丙又是空元素,那麼他就還要繼續走,往哪裡走?就只有三個方向可以選擇了,下、左、右。不能往上走,因為是從上來的,上是回頭路。這樣一看對於接收方就要記錄來源方向了。
於是乎這裡又有個問題:對於發送方有一個探路方向,接收方有個來源方向,這兩個方向怎麼處理?
比如說吧,上圖中的乙是個黃色元素,它打算向下發起探路,那麼乙的探路方向是下,走到丙這兒丙接收了這個探路,他的接收方向對於他自己就是上了——從我的上方來的探路。可見這一對方向正好是相反的,這樣記錄一個方向,然後寫個函數轉換一下就可以得到另一個方向了。
現在我們來研究研究探路的步驟。第一步選定一個元素,從它開始找與它相同的符合消元條件的元素。那麼這個起點元素肯定要記下來,比如是A(x1, y1),A是元素類型,x1、y1分別為橫、縱坐標。第二步,根據元素A(x1, y1)在棋盤上的位置判斷有哪些出口方向,記錄之。比如在邊緣上就不能往外走了。第三步,根據預設的順序往外走,比如圖一中的甲元素有兩個出路:向右或向下,那麼根據預設的尋找順序就先向右走(比如),走不通再向下走。於是乎有第四步,根據行走方向確定下一個點的坐標Next Locator。這一步很重要,基本上現在就可以想出這麼一個函數來完成之:
坐標f(當前點坐標, 行走方向)
這樣有了下一個點坐標我們就可以遞歸判斷了,如果有元素:是不是同種元素;不是同種元素就擋住了路,這一條路就死了。如果沒有元素就步進。當然還要判斷所謂下一個點有沒有出界等等,這都要結合棋盤來。
如果限定了一個元素和探路方向,所謂下一個點坐標當然就是確定的一個,可是在下面的實際編程中為了便於遞歸我們用的是另一種稍微不同的方式:不限定探路方向得到下一個所有的可能點的坐標,這樣對於圖一的甲來說就有兩個坐標,乙也有兩個,丙有三個。可以定義一個結構NextLocator,包含這三個坐標。
下面我們來研究這麼一種情況,如圖三。
從甲開始向下探路,走到了乙處,乙處是空的所以還得繼續探。怎麼操作?如果不出意外這時因該調用那個函數得到下一個點的坐標了,注意我們現在設計的方法是得到“下三個點”的坐標,如圖四。
我們看一看這個結構:








其中Locator是一個已經定義了的坐標聲明。這裡有ForwardLocator、LeftLocator和RightLocator三個變量,我是這樣安排的:ForwardLocator放“前面”一個點的坐標,LeftLocator和RightLocator放另兩個點的坐標。所謂“前面”是指直走方向的坐標,也就是圖四中丙的坐標,而LeftLocator和RightLocator並不一定就是放左邊的和右邊的點位的坐標,因為有些情況下探路沒有左右,取而代之的是上下,這種情況下就要約定,比如上坐標放在LeftLocator中,下放在RightLocator中,我後面的程序好像就是這麼約定的,自己都記不清了…汗!
好,我們得到了這三個坐標,就要往下走了。通常情況下我們找路都是先直走,找不到了再一步步地退、轉彎,ForwardLocator就是放直行的坐標,所以每次都是先取ForwardLocator,在LeftLocator、RightLocator。這個都是自己規定的,你當然完全/也可以一來就拐彎,或者先拐彎再直走在拐彎。
OK,問題討論的查不多了,下一篇放代碼吧!