隔了這麼久終於有時間來研究以前連連看的算法問題了,說來也慚愧。(前文請參看《專題:連連看-甲-乙-概述-建模》及《專題-連連看-丙-丁-算法(一)-矩陣梳理(一) 》)
我們來考慮連連看自動找牌自動找路的問題,先看看下圖。
棋盤中卡片1與卡片2可以消元,相鄰的兩個同種元素可以消元。現在就有個問題:給定一個元素甲,我們先從哪個方向“探路”呢?這裡必須有個約定,比如從右方向起順時針。那麼在圖一中的探路方向就是:右 -> 下 -> 左 -> 上。當然由於圖一中的元素1在棋盤的邊緣,所以不能實施左和上方向的探查,這個可以通過檢查元素在期盼中的位置加以判斷。
如果把卡片2在X、Y方向那遠一點,如圖二,一樣可以消元:直行、無遮擋、同種元素。比如我們確定探測順序是從右方向起順時針,那麼現在實施的步驟就是:
1、檢查右方向的一個元素,能消元就返回;
2、前進;
3、重復步驟1;
4、重復步驟2;
……
1、檢查右方向的一個元素,能消元就返回;
2、前進;
3、重復步驟1;
4、重復步驟2;
……
那麼於是乎就多了一個前進的過程,一次前進一格也就是步進一。如何實施前進呢?必須記錄原始點坐標,然後根據原始點坐標和前進方向算出下一個點的坐標,再跳到下一個點探測。
這裡很容易看出所謂“跳到下一個點探測”的步驟又同第一步是相同的,前進的過程可能是漫長的,只要沒找到能消元的元素、只要路沒封死就會步進。如此一來就很容易然人想到了遞歸,遞歸正是解決這個問題的“好方法”,為了使問題的簡單化,這裡我們先用遞歸來研究研究問題,待會兒再說遞歸的壞話,我本人是從來不用遞歸的,這是第一次:-)。
探路的過程很簡單,我們先寫出第一趟偽碼:
布爾 探路函數(若干參數)
{
如果(下一個點元素的花色 == 當前點元素的花色)
{
記錄下一個點元素的坐標;
返回成功;
}
否則
{
如果(前進一步調用探路函數)
{
返回成功;
}
返回失敗;
}
}
這是第一趟的偽碼,裡面有些問題:
1、沒有考慮拐點限制,顯然不符合連連看的規則;
2、“如果(下一個點元素的花色 == 當前點元素的花色)”有問題,如果這個條件不滿足則會步進,然而如果下一個點位有元素(不同元素),則造成了遮擋,不能步進。
下面是第二趟偽碼:
布爾 探路函數(坐標 當前點坐標,無符號整數 當前拐點數,若干參數)
{
如果(當前拐點數 > 2)
{
返回失敗;
}
如果(下一個點有元素)
{
如果(下一個點元素的花色 == 當前點元素的花色)
{
記錄下一個點元素的坐標;
返回成功;
}
//有元素,花色又不同
//則遮擋,需要換方向探路
如果(換方向前進一步調用探路函數(下一個點的坐標, 當前拐點數 + 1, 參數若干))
{
返回成功;
}
返回失敗;
}
否則
//無元素情況
{
如果(前進一步調用探路函數)
{
返回成功;
}
返回失敗;
}
}
仔細審查一番,這段偽碼基本上沒什麼問題了,現在需要豐富它,比如下一個點是什麼個點,方向的確定等,下一篇再說吧,累了。。。