首页 > 代码库 > 人机博弈,吃子棋游戏(二)如何算气

人机博弈,吃子棋游戏(二)如何算气

算法过程如下,输入计算棋气的起始子,检查我方棋子其周边的空白,并查看此空白是否已经计算过气了,如果没有计算过气加一,如果已经计算则略过,进而递归调用计算我方棋子上下左右子的气,最后算法会返回棋串的子数和气数。算法注释十分详尽。

这个计算棋子气的算法,参考http://www.cnblogs.com/tuanzang/archive/2013/02/27/2935861.html,结合我们自身的应用需要优化和修改。这篇博文介绍了更多关于围棋的算法,有兴趣的朋友可以进一步阅读。

原文suanqi函数会重复计算已经计算过的棋串效率不高,应该对已经算过气的函数不在重复算气,并且我们需要知道棋串的长度。

 

  1 #include <iostream>  2 #include <utility>  3   4 #define EDGE 19  5 int go[EDGE][EDGE];//棋盘数据,0为黑棋,1为白棋,2为空白  6 int gokong[EDGE][EDGE]; //0=该空点未曾计算过气,1=已计算,避免重复计算公气  7 int gozi[EDGE][EDGE]; //0=该子未计算串气,1=已计算,避免重复计算同一个子的气  8 int goqi; //此棋串气数  9 int goziLength;//此棋串子数 10 int g_gozi[EDGE][EDGE]; 11  12  void str_qi(int x,int y,int hb) 13   { 14     //本函数计算 x,y 处的hb颜色棋子的气 15     gozi[x][y]=1; //标记本子已经计算过气 16     goziLength++; 17     /////////////////////////////////////////////////////右临子 18     if (x+1<=19)//如果没有超出棋盘边线 19     { 20       if ((go[x+1][y]==2)&&(gokong[x+1][y]==0)) 21       //如果右临点为空并且该点未曾计算过气则 22       { 23         goqi++; //气数加一 24         gokong[x+1][y]=1; //标记本空点已经计算过气 25       } 26       else if ((go[x+1][y]==hb)&&(gozi[x+1][y]==0)) 27       //否则如果右临点为和本子同色子并且该子未曾计算过气则 28       str_qi(x+1,y,hb); //递归调用到右临子 29     } 30     /////////////////////////////////////////////////////左临子 31     if (x-1>=1) //果没有超出棋盘边线 32     { 33       if ((go[x-1][y]==2)&&(gokong[x-1][y]==0)) 34       //如果左临点为空并且该点未曾计算过气则 35       { 36         goqi++; //气数加一 37         gokong[x-1][y]=1; //标记本空点已经计算过气 38       } 39       else if ((go[x-1][y]==hb)&&(gozi[x-1][y]==0)) 40       //否则如果左临点为和本子同色子并且该子未曾计算过气则 41       str_qi(x-1,y,hb); //递归调用到左临子 42     } 43     ////////////////////////////////////////////////////下临子 44     if (y-1>=1)//如果没有超出棋盘边线 45     { 46       if ((go[x][y-1]==2)&&(gokong[x][y-1]==0)) 47       //如果下临点为空并且该点未曾计算过气则 48       { 49         goqi++; //气数加一 50         gokong[x][y-1]=1; //标记本空点已经计算过气 51       } 52       else if ((go[x][y-1]==hb)&&(gozi[x][y-1]==0)) 53       //否则如果下临子点为和本子同色子并且该子未曾计算过气则 54       str_qi(x,y-1,hb); //递归调用到下临子 55     } 56     ////////////////////////////////////////////////////上临点 57     if (y+1<=19)//如果没有超出棋盘边线 58     { 59       if ((go[x][y+1]==2)&&(gokong[x][y+1]==0)) 60       //如果上临点为空并且该点未曾计算过气则 61       { 62         goqi++; //气数加一 63         gokong[x][y+1]=1; //标记本空点已经计算过气 64       } 65       else if ((go[x][y+1]==hb)&&(gozi[x][y+1]==0)) 66       //否则如果上临点为和本子同色子并且该子未曾计算过气则 67       str_qi(x,y+1,hb); //递归调用到上临子 68     } 69   } 70  71   std::pair<int,int> str_lib(int x,int y, int hb) 72   { 73  74     for (int i = 1; i <= 19; i++) 75       for (int j = 1; j <= 19; j++) 76       { 77         gozi[i][j] = 0; //初始化变量,表示该子未计算串气 78         gokong[i][j] = 0; //初始化变量,表示该空点未计算串气 79       } 80     goqi=0; //棋串气初值 81     goziLength=0;//棋串初始子数 82     str_qi(x,y,hb); //调用串气子程序 83     for(int i=0;i<EDGE;i++) 84      for(int j=0;j<EDGE;j++){ 85       if(gozi[i][j]==1) 86       g_gozi[i][j]=1; 87      } 88     return std::make_pair<int,int>(goqi,goziLength); 89   } 90  91   void suanqi() 92   { 93     int qq; 94     for (int i = 0; i <EDGE; i++) 95       for (int j = 0; j <EDGE; j++) 96       { 97         go[i][j]=qipan[i][j].color;//初始化go数组 98       } 99     for (int i = 0; i <EDGE; i++)100       for (int j = 0; j <EDGE; j++)101       {102         if (go[i][j]!=2&&g_gozi[i][j]==0)//仅处理未计算过的棋串103         {104 105           qq=str_lib(i,j,go[i][j]).first;106           qipan[i][j].qs=qq;107         }108       }109   }

 

人机博弈,吃子棋游戏(二)如何算气