連連看演算法
-
圖片相同
-
圖片間連線的轉角數不得超過2 。
而判斷能否通過小於兩個轉角的路徑連通的演算法有兩種:
-
分類判斷法
-
以轉角數為標準的廣度優先搜尋
下面對兩種演算法分別討論。
-
分類判斷法
這裡實質上是一種遞迴的思想,要判斷圖片A與圖片B能否通過一條有N個轉角的路徑相連,可以轉化為判斷能否找到圖片C,C與A能直線相連,且C與B能用一條有N-1個轉角的路徑相連。若這樣的圖片C存在,那麼A與B就可以通過一條有N個轉角的路徑相連。
根據轉角數不得超過2個的規則,我們可以分為轉角數分別為0個、1個、2個這三種情況分別討論。
(1)0轉角連通(直線連通):兩個圖片的縱座標或橫座標相等,且兩者連線間沒有其他圖案阻隔。
(2)一個轉角連通:其實相當於兩個圖片劃出一個矩形,這兩個圖片是一對對角頂點,另外兩個頂點如果可以同時和這兩個棋子直連,那就說明可以"一折連通"。見下圖兩個紅色棋子的連通情況,右上角打叉的位置就是折點。
圖1.一個轉角連通
(3)兩個轉角連通: 判斷圖片A與圖片B能否經過有兩個轉角的路徑連通實質上可以轉化為判斷能否找到一個點C,這個C點與A可以直線連通,且C與B可以通過有一個轉角的路徑連通。若能找到這樣一個C點,那麼A與B就可以經過有兩個轉角的路徑連通 。
判斷是否經兩個轉角連通的演算法需要做兩個方向上的掃描:水平掃描和垂直掃描。
水平掃描。如下圖所示,為了判斷A,B能否通過2個轉角連通,則從A開始在水平方向上向左右掃描,並判斷經過的點能否與B點經過1個轉角連通。顯然C點能與B點經1個轉角連通,故A,B能經2個轉角連通。
圖2.兩個轉角連通的判斷
垂直掃描。如下圖所示,為了判斷A,B能否通過2個轉角連通,則從A開始在垂直方向上下掃描,並判斷經過的點能否與B點經過1個轉角連通。顯然C點能與B點經1個轉角連通,故A,B能經2個轉角連通。
圖3 .兩個轉角連通的判斷
詳細程式碼如下:
//棋盤基地址
PCHAR pBase=NULL;
//棋盤X軸數量 Y軸數量
const int nNumberX=19, nNumberY=11;
//得到陣列值的巨集
#define GETVALUE(point) (*(pBase + point.x +point.y * nNumberX))
//檢視兩個塊是否可以直連
BOOL MatchBlock(POINT st1, POINT st2)
{
if(!(st1.x==st2.x || st1.y==st2.y))
{
return FALSE;
}
POINT stMin, stMax;
//如果是豎線直連
if(st1.x==st2.x)
{
//由於這裡會被 一折連 遞迴呼叫 所以必須判斷大小
stMin=st1.y<st2.y?st1:st2;
stMax=st1.y>st2.y?st1:st2;
for(stMin.y++; stMin.y<stMax.y; stMin.y++)
{
if(GETVALUE(stMin)!=0)
{
return FALSE;
}
}
}
//如果是橫線直連
else
{
stMin=st1.x<st2.x?st1:st2;
stMax=st1.x>st2.x?st1:st2;
for(stMin.x++; stMin.x<stMax.x; stMin.x++)
{
if(GETVALUE(stMin)!=0)
{
return FALSE;
}
}
}
return TRUE;
}
//檢視兩個塊是否可以一折連
BOOL MatchBlockOne(POINT st1, POINT st2)
{
//以st1 st2為矩形對角 尋找矩形另外2點
POINT a1, a2;
a1.x=st1.x;
a1.y=st2.y;
a2.x=st2.x;
a2.y=st1.y;
/*示意圖如下:
st1 a2
a1 st2
*/
//矩形另外2點都不會空 則跳過這種情況
if((GETVALUE(a1)!=0) && (GETVALUE(a2)!=0))
{
return FALSE;
}
//如果a1為空
if(GETVALUE(a1)==0)
{
//測試 a1-st1直連 a1-st2直連
if(!(MatchBlock(a1, st1) && MatchBlock(a1, st2)))
{
return FALSE;
}
}
//如果a2為空
else
{
//測試 a2-st1直連 a2-st2直連
if(!(MatchBlock(a2, st1) && MatchBlock(a2, st2)))
{
return FALSE;
}
}
return TRUE;
}
//檢視兩個塊是否可以兩折連
BOOL MatchBlockTwo(POINT st1, POINT st2)
{
/*同樣把st1,st2想成一個矩形的兩個對角, 依次從st1的X軸 Y軸每次+1/-1尋找為空的點C/D
再由C/D和st2進行一折連判斷 示意圖如下:
st1 C
D st2
由於st1和st2的相對位置不確定所以 需要把st1分4種情況討論
*/
POINT stTmp;
//判斷st1的X軸+1
if(st1.x!=nNumberX-1)
{
stTmp.x=st1.x+1;
stTmp.y=st1.y;
for(; stTmp.x<=nNumberX-1; stTmp.x++)
{
if(GETVALUE(stTmp)==0)
{
if(MatchBlockOne(stTmp, st2))
{
return TRUE;
}
}
else
{
break;
}
}
}
//判斷st1的X軸-1
if(st1.x!=0)
{
stTmp.x=st1.x-1;
stTmp.y=st1.y;
for(; stTmp.x>=0; stTmp.x--)
{
if(GETVALUE(stTmp)==0)
{
if(MatchBlockOne(stTmp, st2))
{
return TRUE;
}
}
else
{
break;
}
}
}
//判斷st1的Y軸+1
if(st1.y!=nNumberY-1)
{
stTmp.x=st1.x;
stTmp.y=st1.y+1;
for(; stTmp.y<=nNumberY-1; stTmp.y++)
{
if(GETVALUE(stTmp)==0)
{
if(MatchBlockOne(stTmp, st2))
{
return TRUE;
}
}
else
{
break;
}
}
}
//判斷st1的Y軸-1
if(st1.y!=0)
{
stTmp.x=st1.x;
stTmp.y=st1.y-1;
for(; stTmp.y>=0; stTmp.y--)
{
if(GETVALUE(stTmp)==0)
{
if(MatchBlockOne(stTmp, st2))
{
return TRUE;
}
}
else
{
break;
}
}
}
return FALSE;
}
2.以轉角數為基準的廣度優先搜尋法
這種演算法參考《程式設計之美》。
這種演算法的動機:若能將所有與圖片A經過不多於2個轉角的路徑相連的圖片找出來,加入一個集合S中。那麼判斷B與A能否相連只需判斷B是否存在於集合S中即可。採用廣度優先搜尋演算法可以方便的實現這一構想。演算法的思路如下:
(1)定義空集S與T,將A加入集合S
(2)找出所有與A能直接相連的點,將其加入集合S
(3)找出與集合S中的點能直接相連的點,加入集合T,然後將T中所有元素加入到集合S中,清空集合T
(4)找出與集合S中的點能直接相連的點,加入集合T,然後將T中所有元素加入到集合S中
(5)若B在集合S中,則A,B可以相連。否則A,B不能相連
模仿圖論中廣度優先搜尋的演算法,可以寫出以轉角為基準的廣度優先搜尋的虛擬碼如下:
//判斷圖片A與圖片B能否經過不多於2個轉角的路徑相連的演算法bool Match( Picture A,Picture B )
{
Set< picture > S ;//已經搜尋到的點的集合,集合S中每個元素與A都可以通過不多於個轉角的路徑連通
Set< picture > T ;//臨時儲存搜尋到的點
將A加入到S中
int crossNum = 0 ;//用於記錄當前搜尋到節點的最大轉角數
While( B 不在S 中&& crossNum < 3 )
{
for( S 中每個元素e )
{
將所有與e能直線連通的點加入到集合T中
}
T中的所有元素加入到S中
crossNum ++ ;
}
if( B 在S中)
returntrue ;
else
returnfalse ;
}
實際程式設計實現這一演算法時可以採取優化措施,不一定要搜尋出所有與A轉角不超過2的點。
相關文章
- hdu 1175 連連看 搜尋
- 《天天連連看》隱私策略
- Java遊戲開發——連連看Java遊戲開發
- c#(WPF)實現連連看C#
- 《連連看》走過的這些年
- 【180620】VC++連連看遊戲原始碼C++遊戲原始碼
- 程式設計師玩連連看的正確姿勢程式設計師
- 看動畫理解「連結串列」實現LRU快取淘汰演算法動畫快取演算法
- 排序演算法-大型連續劇1(連載中....)排序演算法
- 演算法-連結串列演算法
- 把玩演算法 | 連結串列演算法
- airpods pro連線win10如何看電量_airpods pro連線win10怎麼看電量AIWin10
- 強連通分量(Tarjan演算法)演算法
- 初級演算法-連結串列演算法
- 力扣--連結串列演算法力扣演算法
- 演算法題——冗餘連線演算法
- 連通圖與Tarjan演算法演算法
- 短連結生成的演算法演算法
- MySQL不能從外部連線?速看解決MySql
- 看圖輕鬆理解資料結構與演算法系列(單向連結串列)資料結構演算法
- 看圖輕鬆理解資料結構與演算法系列(雙向連結串列)資料結構演算法
- 演算法面試(一) 連結串列演算法面試
- Tarjan演算法(強連通分量分解)演算法
- 【LeetCode】初級演算法:連結串列LeetCode演算法
- 演算法題中的連結串列演算法
- 演算法 - 連結串列操作思想 && case演算法
- 演算法基礎~連結串列~排序連結串列的合併(k條)演算法排序
- 【小白學演算法】5.連結串列(linked list)、連結串列的新增演算法
- 《奇怪的連連看》登頂iOS的背後是波克城市在努力轉型iOS
- 結構與演算法(03):單向連結串列和雙向連結串列演算法
- 不一樣的連連看 創新手遊《懸浮世界》7月12日雙端上線
- 資料結構與演算法——連結串列 Linked List(單連結串列、雙向連結串列、單向環形連結串列-Josephu 問題)資料結構演算法
- 圖論——強連通分量(Tarjan演算法)圖論演算法
- 演算法141. 環形連結串列演算法
- 演算法:排序連結串列:歸併排序演算法排序
- 內連線、左連線、右連線
- 演算法題:反轉一個單連結串列&判斷連結串列是否有環演算法
- 連結串列還會用嗎?用連結串列實現棧(附演算法原始碼)演算法原始碼
- [Golang]力扣LeetBook—初級演算法—連結串列—迴文連結串列(快慢指標)Golang力扣演算法指標