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

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

这个计算棋子气的算法,参考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   }
时间: 2024-10-23 19:10:58

人机博弈,吃子棋游戏(二)如何算气的相关文章

人机博弈-吃子棋游戏(二)算气

算法过程如下,输入计算棋气的起始子,检查我方棋子其周边的空白,并查看此空白是否已经计算过气了,如果没有计算过气加一,如果已经计算则略过,进而递归调用计算我方棋子上下左右子的气,最后算法会返回棋串的子数和气数.算法注释十分详尽. 这个计算棋子气的算法,参考http://www.cnblogs.com/tuanzang/archive/2013/02/27/2935861.html,结合我们自身的应用需要优化和修改.这篇博文介绍了更多关于围棋的算法,有兴趣的朋友可以进一步阅读. 原文suanqi函数

人机博弈-吃子棋游戏(三)走法生成

我们可以根据吃子棋的规则,创建走法生成器,主要的逻辑是,如果己方存在一气的棋串,则可以无需紧对方的气,也就是可以不用贴着对方的棋子落子.其他情况下,必须贴 着对方的棋子落子,考虑到某些特殊情况,当己方能提对方棋子时,己方就可以下到没有气的地方,并且一般的吃子棋,先提子者胜,无法形成劫争.所以走法生成器就相对非 常简单. 对于如何确定己方是不是存在一气的棋串,可以利用上一节介绍的算气算法. 1 int CMoveGenerator::CreatePossibleMove(BYTE position

人机博弈-吃子棋游戏(四)搜索算法

博弈树搜索技术简介: 博弈树的搜索算法,负值极大搜索,alpha-beta搜索,渴望搜索,PVS极窄窗口搜索等.通常来说,搜索算法常常和以下技术联合在一起. 如下: 1.置换表,记录已经搜索过的棋局,避免再次搜索. 2.吃子启发,优先试下能够吃对方棋子的走法. 3.杀手启发,历史启发简化版. 4.历史启发,优先试下历史统计数据得出的比较好的走法. 5.静止期搜索,继续对某些叶子结点搜索,避免水平线效应. 6.迭代加深搜索,根据搜索时间,状态.决定是否继续搜索. 有兴趣的朋友可以深入研究一下上述技

人机博弈,吃子棋游戏(一)

(1)什么是吃子棋? 吃子棋,是小孩子学围棋的入门棋,其规则部分取自于围棋,但比围棋简单很多. (2)吃子棋的行棋规则? 1.吃子棋,在行棋时,若一方棋子没有被打吃,则其必须落子在能够紧对方棋子气的位置. 2.吃子棋,当一方棋子处于被打吃的状态,则可以逃命,而不用紧对方棋子的气. 3.吃子棋,当一方棋子被吃提,则输赢即分,吃子方胜. 4.吃子棋,一般有两种赢棋方式,双打吃和征吃. 5.吃子棋,起手棋必须位于天元. (3)应用设计思路 设计此应用的总体思路如下: DATA: 1.棋盘表示 2.棋子

人机博弈-吃跳棋游戏(三)代移动

我们能够根据国际象棋的规则吃,创建移动生成器.基本逻辑是,假定一个拉伸己方蠕虫的存在,这是可能没有其他的致密气.这是不是对其他部分可以落子.在其他情况下.必须坚持 另一片落子,考虑到特殊情况,当自己可以提其他片,自己可以下到那里没有气.和一般吃跳棋.胜,无法形成劫争.所以走法生成器就相对非 常简单. 对于怎样确定己方是不是存在一气的棋串,能够利用上一节介绍的算气算法. int CMoveGenerator::CreatePossibleMove(BYTE position[GRID_NUM][G

hiho一下 第四十五周 博弈游戏&#183;Nim游戏&#183;二 [ 博弈 ]

传送门 题目1 : 博弈游戏·Nim游戏·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Alice和Bob这一次准备玩一个关于硬币的游戏:N枚硬币排成一列,有的正面朝上,有的背面朝上,从左到右依次编号为1..N.现在两人轮流翻硬币,每次只能将一枚正面朝上的硬币翻过来,并且可以随自己的意愿,在一枚硬币翻转后决定要不要将该硬币左边的任意一枚硬币也翻一次(正面翻到背面或背面翻到正面).翻最后一枚正面向上的硬币的人获胜.同样的,这次游戏里面Alice仍然先手,两人均采

博弈游戏&#183;Nim游戏&#183;二

题目1 : 博弈游戏·Nim游戏·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Alice和Bob这一次准备玩一个关于硬币的游戏: N枚硬币排成一列,有的正面朝上,有的背面朝上,从左到右依次编号为1..N.现在两人轮流翻硬币,每次只能将一枚正面朝上的硬币翻过来,并且可以随自己的意愿,在一枚硬币翻转后决定要不要将该硬币左边的任意一枚硬币也翻一次(正面翻到背面或背面翻到正面).翻最后一枚正面向上的硬币的人获胜.同样的,这次游戏里面Alice仍然先手,两人均采取最优

人工智能博弈树算法做的井字棋游戏

不会输,超碉!井字棋这个游戏真是太无聊啦! 算法大概就是,有一个给状况进行估价的函数,深搜每种状况,假设每个人都按对自己最有利的方式走(假设玩家也是不傻),最后让电脑走出最有利的一步. 代码: 1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<

人工智能之人机博弈(1)

每个程序猿的心中都有一个AI梦,而人机博弈是最简单的一种AI形式. 看了阿尔法狗和李世石之战后,就一直在研究AI的一些知识,包括传统的人机博弈算法,以及阿尔法狗的蒙特卡罗加神经网络的算法.甚至还重温了高等数学的知识. 为了给家里小朋友学棋,花了一个多月的休息的时间,开发了这个国际跳棋软件.支持人机对战,经专家们测试,AI棋力达到中等以上棋手的水平. 对国际跳棋感兴趣的朋友,可以到下面地址下载试用一下.暂时不开源,等我完善了程序,再考虑开源出来.并写一些文章总结和分享开发的过程.  下载地址: h