標籤:c++ 演算法 吃子棋
演算法過程如下,輸入計算棋氣的起始子,檢查我方棋子其周邊的空白,並查看此空白是否已經計算過氣了,如果沒有計算過氣加一,如果已經計算則略過,進而遞迴調用計算我方棋子上下左右子的氣,最後演算法會返回棋串的子數和氣數。演算法注釋十分詳盡。
這個計算棋子氣的演算法,參考http://www.cnblogs.com/tuanzang/archive/2013/02/27/2935861.html,結合我們自身的應用需要最佳化和修改。這篇博文介紹了更多關於圍棋的演算法,有興趣的朋友可以進一步閱讀。
原文suanqi函數會重複計算已經計算過的棋串效率不高,應該對已經算過氣的函數不在重複算氣,並且我們需要知道棋串的長度。
#include <iostream>#include <utility>#define EDGE 19int go[EDGE][EDGE];//棋盤資料,0為黑棋,1為白棋,2為空白int gokong[EDGE][EDGE]; //0=該空點未曾計算過氣,1=已計算,避免重複計算公氣int gozi[EDGE][EDGE]; //0=該子未計算串氣,1=已計算,避免重複計算同一個子的氣int goqi; //此棋串氣數int goziLength;//此棋串子數int g_gozi[EDGE][EDGE]; void str_qi(int x,int y,int hb) { //本Function Compute x,y 處的hb顏色棋子的氣 gozi[x][y]=1; //標記本子已經計算過氣 goziLength++; /////////////////////////////////////////////////////右臨子 if (x+1<=19)//如果沒有超出棋盤邊線 { if ((go[x+1][y]==2)&&(gokong[x+1][y]==0)) //如果右臨點為空白並且該點未曾計算過氣則 { goqi++; //氣數加一 gokong[x+1][y]=1; //標記本空點已經計算過氣 } else if ((go[x+1][y]==hb)&&(gozi[x+1][y]==0)) //否則如果右臨點為和本子同色子並且該子未曾計算過氣則 str_qi(x+1,y,hb); //遞迴調用到右臨子 } /////////////////////////////////////////////////////左臨子 if (x-1>=1) //果沒有超出棋盤邊線 { if ((go[x-1][y]==2)&&(gokong[x-1][y]==0)) //如果左臨點為空白並且該點未曾計算過氣則 { goqi++; //氣數加一 gokong[x-1][y]=1; //標記本空點已經計算過氣 } else if ((go[x-1][y]==hb)&&(gozi[x-1][y]==0)) //否則如果左臨點為和本子同色子並且該子未曾計算過氣則 str_qi(x-1,y,hb); //遞迴調用到左臨子 } ////////////////////////////////////////////////////下臨子 if (y-1>=1)//如果沒有超出棋盤邊線 { if ((go[x][y-1]==2)&&(gokong[x][y-1]==0)) //如果下臨點為空白並且該點未曾計算過氣則 { goqi++; //氣數加一 gokong[x][y-1]=1; //標記本空點已經計算過氣 } else if ((go[x][y-1]==hb)&&(gozi[x][y-1]==0)) //否則如果下臨子點為和本子同色子並且該子未曾計算過氣則 str_qi(x,y-1,hb); //遞迴調用到下臨子 } ////////////////////////////////////////////////////上臨點 if (y+1<=19)//如果沒有超出棋盤邊線 { if ((go[x][y+1]==2)&&(gokong[x][y+1]==0)) //如果上臨點為空白並且該點未曾計算過氣則 { goqi++; //氣數加一 gokong[x][y+1]=1; //標記本空點已經計算過氣 } else if ((go[x][y+1]==hb)&&(gozi[x][y+1]==0)) //否則如果上臨點為和本子同色子並且該子未曾計算過氣則 str_qi(x,y+1,hb); //遞迴調用到上臨子 } } std::pair<int,int> str_lib(int x,int y, int hb) { for (int i = 1; i <= 19; i++) for (int j = 1; j <= 19; j++) { gozi[i][j] = 0; //初始設定變數,表示該子未計算串氣 gokong[i][j] = 0; //初始設定變數,表示該空點未計算串氣 } goqi=0; //棋串氣初值 goziLength=0;//棋串初始子數 str_qi(x,y,hb); //調用串氣子程式 for(int i=0;i<EDGE;i++) for(int j=0;j<EDGE;j++){ if(gozi[i][j]==1) g_gozi[i][j]=1; } return std::make_pair<int,int>(goqi,goziLength); } void suanqi() { int qq; for (int i = 0; i <EDGE; i++) for (int j = 0; j <EDGE; j++) { go[i][j]=qipan[i][j].color;//初始化go數組 } for (int i = 0; i <EDGE; i++) for (int j = 0; j <EDGE; j++) { if (go[i][j]!=2&&g_gozi[i][j]==0)//僅處理未計算過的棋串 { qq=str_lib(i,j,go[i][j]).first; qipan[i][j].qs=qq; } } }
轉載請標明出處,謝謝
人機博弈-吃子棋遊戲(二)算氣