五子棋AI的思路
隔了一年才把AI思路给写了。。。
需求分析与设计方案:http://www.cnblogs.com/songdechiu/p/4951634.html
如需整个工程,移步http://download.csdn.net/detail/sdzuiaidanpianji/9452789
如没有积分,可在百度网盘下载:
链接: https://pan.baidu.com/s/1UXzhEDWXfsb6EbFOzRVuqg 提取码: ezm6
注:全文,都默认以黑方为己方。
一、五子棋基本棋型
参考资料:http://game.onegreen.net/wzq/HTML/142336.html
最常见的基本棋型大体有以下几种:连五,活四,冲四,活三,眠三,活二,眠二。
①连五:顾名思义,五颗同色棋子连在一起,不需要多讲。
图2-1
②活四:有两个连五点(即有两个点可以形成五),图中白点即为连五点。
稍微思考一下就能发现活四出现的时候,如果对方单纯过来防守的话,是已经无法阻止自己连五了。
图2-2
③冲四:有一个连五点,如下面三图,均为冲四棋型。图中白点为连五点。
相对比活四来说,冲四的威胁性就小了很多,因为这个时候,对方只要跟着防守在那个唯一的连五点上,冲四就没法形成连五。
图2-3 图2-4 图2-5
④活三:可以形成活四的三,如下图,代表两种最基本的活三棋型。图中白点为活四点。
活三棋型是我们进攻中最常见的一种,因为活三之后,如果对方不以理会,将可以下一手将活三变成活四,而我们知道活四是已经无法单纯防守住了。所以,当我们面对活三的时候,需要非常谨慎对待。在自己没有更好的进攻手段的情况下,需要对其进行防守,以防止其形成可怕的活四棋型。
图2-6 图2-7
其中图2-7中间跳着一格的活三,也可以叫做跳活三。
⑤眠三:只能够形成冲四的三,如下各图,分别代表最基础的六种眠三形状。图中白点代表冲四点。眠三的棋型与活三的棋型相比,危险系数下降不少,因为眠三棋型即使不去防守,下一手它也只能形成冲四,而对于单纯的冲四棋型,我们知道,是可以防守住的。
图2-8 图2-9 图2-10
2-11 图2-12 图2-13
如上所示,眠三的形状是很丰富的。对于初学者,在下棋过程中,很容易忽略不常见的眠三形状,例如图2-13所示的眠三。
有新手学了活三眠三后,会提出疑问,说活三也可以形成冲四啊,那岂不是也可以叫眠三?
会提出这个问题,说明对眠三定义看得不够仔细:眠三的的定义是,只能够形成冲四的三。而活三可以形成眠三,但也能够形成活四。
此外,在五子棋中,活四棋型比冲四棋型具有更大的优势,所以,我们在既能够形成活四又能够形成冲四时,会选择形成活四。
温馨提示:学会判断一个三到底是活三还是眠三是非常重要的。所以,需要好好体会。
后边禁手判断的时候也会有所应用。
⑥活二:能够形成活三的二,如下图,是三种基本的活二棋型。图中白点为活三点。
活二棋型看起来似乎很无害,因为他下一手棋才能形成活三,等形成活三,我们再防守也不迟。但其实活二棋型是非常重要的,尤其是在开局阶段,我们形成较多的活二棋型的话,当我们将活二变成活三时,才能够令自己的活三绵绵不绝微风里,让对手防不胜防。
图2-14 图2-15 图2-16
⑦眠二:能够形成眠三的二。图中四个为最基本的眠二棋型,细心且喜欢思考的同学会根据眠三介绍中的图2-13找到与下列四个基本眠二棋型都不一样的眠二。图中白点为眠三点。
图2-17 图2-18
图2-19 图2-20
二、打分机制
1、打分思路
(1)先对整个棋盘形势进行打分,存在两个矩阵(二维数组)上
(2)一个为我方的形势分数,一个为敌方的形势分数
(3)找出我方形势分数的最大值mymaxscore及其对应的位置,找出敌方形势的最大值hismaxscore及其对应的位置
(4)判断是进攻还是防守:
如果mymaxscore>=hismaxscore,则进攻,下我方形势最大值mymaxscore对应的位置;如果有多个mymaxscore相等,则下这几个对应位置上hismaxscore最大的位置。
否则,防守,下敌方形势最大值hismaxscore对应的位置。如果有多个hismaxscore相等,则下这几个对应位置上mymaxscore最大的位置。
2、打分方法
(1)在棋盘空位置上预添加要判断放的棋子
(2)取出以空位置为中心的4个方向(上,下,左,右),每个方向以该位置为中心两边各取4个格子信息。如下所示:
注:中心位置都是预放置,当前判断的时候位置还是空的
(3)四个方向都判断其棋型,是否连五,活四,冲四,活三,眠三,活二,眠二等中的一种
(4)最后综合四个方向的棋型,对该位置进行打分。
3、打分规定
注:机器方即为本方,人方即为敌方
综合四个方向后:
判断是否能成5, 如果是机器方的话给予100000分,如果是人方的话给予100000 分;
判断是否能成活4或者是双死4或者是死4活3,如果是机器方的话给予10000分,如果是人方的话给予10000分;
判断是否已成双活3,如果是机器方的话给予5000分,如果是人方的话给予5000 分;
判断是否成死3活3(高级),如果是机器方的话给予1000分,如果是人方的话给予1000 分;
判断是否能成死4,如果是机器方的话给予500分,如果是人方的话给予500分;
判断是否能成低级死4,如果是机器方的话给予400分,如果是人方的话给予400分;
判断是否能成单活3,如果是机器方的话给予100分,如果是人方的话给予100分;
判断是否能成跳活3,如果是机器方的话给予90分,如果是人方的话给予90分;
判断是否能成双活2,如果是机器方的话给予50分,如果是人方的话给予50分;
判断是否能成活2,如果是机器方的话给予10分,如果是人方的话给予10分;
判断是否能成低级活2,如果是机器方的话给予9分,如果是人方的话给予9分;
判断是否能成死3,如果是机器方的话给予5分,如果是人方的话给予5分;
判断是否能成死2,如果是机器方的话给予2分,如果是人方的话给予2分。
判断是否其他情况(nothing),如果是机器方的话给予1分,如果是人方的话给予1分。
有棋子,则直接0分。
4、棋型判断方法
(1)在空位置上添加要判断色的棋子
(2)取出以空位置为中心的,要判断单个方向(上,下,左,右中的一种)上的,两边各4个位置信息,形成
(3)先找出与中心点相连而成的连续子有多少个
(4)再进行下一步判断
注:以下说明都以黑方为例子
- 中心点相连而成的连续子有5个:不管哪种情况,都可以直接判断为成5:
- 中心点相连而成的连续子有4个:
- 两边均空,活4
- 1、2均非空,则nothing
- 1、2只有一个为空,则死4
- 中心点相连而成的连续子有3个:
- 2,3均空时:
- 1,4均为白子,则为死3
- 1,4只要有一个空,则为活3
- 1,4只要有一个黑,则为死4
以此类推,根据第一部分中的五子棋棋型去判断棋型类型。
具体可直接查看源码部分。
单个方向的棋型判断:
if (count >= )//中心线5连
return WIN5;//5连珠 if (count == )//中心线4连
{
if (colorleft == NOTHINGFLAG && colorright == NOTHINGFLAG)//两边断开位置均空
return ALIVE4;//活四
else if (colorleft == hiscolor && colorright == hiscolor)//两边断开位置均非空
return NOTHREAT;//没有威胁
else if (colorleft == NOTHINGFLAG || colorright == NOTHINGFLAG)//两边断开位置只有一个空
return DIE4;//死四
} if (count == ) {//中心线3连
int colorleft1 = chess[left - ];
int colorright1 = chess[right + ]; if (colorleft == NOTHINGFLAG && colorright == NOTHINGFLAG)//两边断开位置均空
{ if (colorleft1 == hiscolor && colorright1 == hiscolor)//均为对手棋子
return DIE3;
else if (colorleft1 == mycolor || colorright1 == mycolor)//只要一个为自己的棋子
return LOWDIE4;
else if (colorleft1 == NOTHINGFLAG || colorright1 == NOTHINGFLAG)//只要有一个空
return ALIVE3; }
else if (colorleft == hiscolor && colorright == hiscolor)//两边断开位置均非空
{
return NOTHREAT;//没有威胁
}
else if (colorleft == NOTHINGFLAG || colorright == NOTHINGFLAG)//两边断开位置只有一个空
{ if (colorleft == hiscolor) {//左边被对方堵住
if (colorright1 == hiscolor)//右边也被对方堵住
return NOTHREAT;
if (colorright1 == NOTHINGFLAG)//右边均空
return DIE3;
if (colorright1 == mycolor)
return LOWDIE4; }
if (colorright == hiscolor) {//右边被对方堵住
if (colorleft1 == hiscolor)//左边也被对方堵住
return NOTHREAT;
if (colorleft1 == NOTHINGFLAG)//左边均空
return DIE3;
if (colorleft1 == mycolor)//左边还有自己的棋子
return LOWDIE4;
}
}
} if (count == ) {//中心线2连
int colorleft1 = chess[left - ];
int colorright1 = chess[right + ];
int colorleft2 = chess[left - ];
int colorright2 = chess[right + ]; if (colorleft == NOTHINGFLAG && colorright == NOTHINGFLAG)//两边断开位置均空
{
if ((colorright1 == NOTHINGFLAG && colorright2 == mycolor) ||
(colorleft1 == NOTHINGFLAG && colorleft2 == mycolor))
return DIE3;//死3
else if (colorleft1 == NOTHINGFLAG && colorright1 == NOTHINGFLAG)
return ALIVE2;//活2 if ((colorright1 == mycolor && colorright2 == hiscolor) ||
(colorleft1 == mycolor && colorleft2 == hiscolor))
return DIE3;//死3 if ((colorright1 == mycolor && colorright2 == mycolor) ||
(colorleft1 == mycolor && colorleft2 == mycolor))
return LOWDIE4;//死4 if ((colorright1 == mycolor && colorright2 == NOTHINGFLAG) ||
(colorleft1 == mycolor && colorleft2 == NOTHINGFLAG))
return TIAO3;//跳活3
//其他情况在下边返回NOTHREAT
}
else if (colorleft == hiscolor && colorright == hiscolor)//两边断开位置均非空
{
return NOTHREAT;
}
else if (colorleft == NOTHINGFLAG || colorright == NOTHINGFLAG)//两边断开位置只有一个空
{
if (colorleft == hiscolor) {//左边被对方堵住
if (colorright1 == hiscolor || colorright2 == hiscolor) {//只要有对方的一个棋子
return NOTHREAT;//没有威胁
}
else if (colorright1 == NOTHINGFLAG && colorright2 == NOTHINGFLAG) {//均空
return DIE2;//死2
}
else if (colorright1 == mycolor && colorright2 == mycolor) {//均为自己的棋子
return LOWDIE4;//死4
}
else if (colorright1 == mycolor || colorright2 == mycolor) {//只有一个自己的棋子
return DIE3;//死3
}
}
if (colorright == hiscolor) {//右边被对方堵住
if (colorleft1 == hiscolor || colorleft2 == hiscolor) {//只要有对方的一个棋子
return NOTHREAT;//没有威胁
}
else if (colorleft1 == NOTHINGFLAG && colorleft2 == NOTHINGFLAG) {//均空
return DIE2;//死2
}
else if (colorleft1 == mycolor && colorleft2 == mycolor) {//均为自己的棋子
return LOWDIE4;//死4
}
else if (colorleft1 == mycolor || colorleft2 == mycolor) {//只有一个自己的棋子
return DIE3;//死3
}
}
}
} if (count == ) {//中心线1连
int colorleft1 = chess[left - ];
int colorright1 = chess[right + ];
int colorleft2 = chess[left - ];
int colorright2 = chess[right + ];
int colorleft3 = chess[left - ];
int colorright3 = chess[right + ]; if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
colorleft2 == mycolor && colorleft3 == mycolor)
return LOWDIE4;
if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
colorright2 == mycolor && colorright3 == mycolor)
return LOWDIE4; if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
colorleft2 == mycolor && colorleft3 == NOTHINGFLAG && colorright == NOTHINGFLAG)
return TIAO3;
if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
colorright2 == mycolor && colorright3 == NOTHINGFLAG && colorleft == NOTHINGFLAG)
return TIAO3; if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
colorleft2 == mycolor && colorleft3 == hiscolor && colorright == NOTHINGFLAG)
return DIE3;
if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
colorright2 == mycolor && colorright3 == hiscolor && colorleft == NOTHINGFLAG)
return DIE3; if (colorleft == NOTHINGFLAG && colorleft1 == NOTHINGFLAG &&
colorleft2 == mycolor && colorleft3 == mycolor)
return DIE3;
if (colorright == NOTHINGFLAG && colorright1 == NOTHINGFLAG &&
colorright2 == mycolor && colorright3 == mycolor)
return DIE3; if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
colorleft2 == NOTHINGFLAG && colorleft3 == mycolor)
return DIE3;
if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
colorright2 == NOTHINGFLAG && colorright3 == mycolor)
return DIE3; if (colorleft == NOTHINGFLAG && colorleft1 == mycolor &&
colorleft2 == NOTHINGFLAG && colorleft3 == NOTHINGFLAG && colorright == NOTHINGFLAG)
return LOWALIVE2;
if (colorright == NOTHINGFLAG && colorright1 == mycolor &&
colorright2 == NOTHINGFLAG && colorright3 == NOTHINGFLAG && colorleft == NOTHINGFLAG)
return LOWALIVE2; if (colorleft == NOTHINGFLAG && colorleft1 == NOTHINGFLAG &&
colorleft2 == mycolor && colorleft3 == NOTHINGFLAG && colorright == NOTHINGFLAG)
return LOWALIVE2;
if (colorright == NOTHINGFLAG && colorright1 == NOTHINGFLAG &&
colorright2 == mycolor && colorright3 == NOTHINGFLAG && colorleft == NOTHINGFLAG)
return LOWALIVE2; //其余在下边返回没有威胁 }
return NOTHREAT;//返回没有威胁
综合四个方向评分:
if (situation.win5 >= )
return LevelOne;//赢5 if (situation.alive4 >= || die4 >= || (die4 >= && alive3 >= ))
return Leveltwo;//活4 双死4 死4活3 if (alive3 >= )
return Levelthree;//双活3 if (situation.die3 >= && situation.alive3 >= )
return Levelfour;//死3高级活3 if (situation.die4 >= )
return Levelfive;//高级死4 if (situation.lowdie4 >= )
return Levelsix;//低级死4 if (situation.alive3 >= )
return Levelseven;//单活3 if (situation.tiao3 >= )
return LevelEight;//跳活3 if (alive2 >= )
return LevelNight;//双活2 if (situation.alive2 >= )
return LevelTen;//活2 if (situation.lowalive2 >= )
return LevelEleven;//低级活2 if (situation.die3 >= )
return LevelTwelve;//死3 if (situation.die2 >= )
return LevelThirteen;//死2 return LevelFourteen;//没有威胁
五子棋AI的思路的更多相关文章
- 五子棋AI大战OC实现
Gobang 五子棋AI大战,该项目主要用到MVC框架,用算法搭建AI实现进攻或防守 一.项目介绍 1.地址: github地址:Gobang 2.效果图: 二.思路介绍 大概说下思路,具体看代码实现 ...
- 使用QT creator实现一个五子棋AI包括GUI实现(8K字超详细)
五子棋AI实现 五子棋游戏介绍 五子棋的定义 五子棋是全国智力运动会竞技项目之一,是具有完整信息的.确定性的.轮流行动的.两个游戏者的零和游戏.因此,五子棋是一个博弈问题. 五子棋的玩法 五子棋有两种 ...
- 五子棋AI清月连珠开源
经过差不多两年的业余时间学习和编写,最近把清月连珠的无禁手部分完善得差不多了.这中间进行了很多思考,也有很多错误认识,到现在有一些东西还没有全面掌握,所以想通过开源于大家共同交流. 最近一直发表一些五 ...
- 五子棋AI教程
https://github.com/Chuck-Ai/gobang 我写了非常详细的中文教程,教你如何一步步编写自己的五子棋AI: 五子棋AI设计教程第二版一:前言 五子棋AI设计教程第二版二:博弈 ...
- 【五子棋AI循序渐进】——开局库
首先,对前面几篇当中未修复的BUG致歉,在使用代码时请万分小心…………尤其是前面关于VCF\VCT的一些代码和思考,有一些错误.虽然现在基本都修正了,但是我的程序还没有经过非常大量的对局,在这之前,不 ...
- 【五子棋AI循序渐进】关于VCT,VCF的思考和核心代码
前面几篇发布了一些有关五子棋的基本算法,其中有一些BUG也有很多值得再次思考的问题,在框架和效果上基本达到了一个简单的AI的水平,当然,我也是初学并没有掌握太多的高级技术.对于这个程序现在还在优化当中 ...
- 人机ai五子棋 ——五子棋AI算法之Java实现
人机ai五子棋 下载:chess.jar (可直接运行) 源码:https://github.com/xcr1234/chess 其实机器博弈最重要的就是打分,分数也就是权重,把棋子下到分数大的地方, ...
- C++ 之 简单的五子棋AI程序
本人是大一新生,寒假无聊,抱着试试看的心态(没有想到可以完成),写了C++的简单五子棋程序,开心. 下面是效果图: 一.首先讲讲大致思路. 五子棋实现的基础: ...
- 五子棋 AI(AIpha-beta算法)
博弈树 下过五子棋的人都应该知道,越厉害的人,对棋面的预测程度越深.换句话讲,就是当你下完一步棋,我就能在我的脑海里假设把我所有可能下的地方都下一遍,然后考虑我下完之后你又会下在哪里,最后我根据每次预 ...
随机推荐
- es6 - 箭头
class User { constructor(name, age) { this.name = name; this.age = age; } changeName(name) { this.na ...
- UNP学习笔记(第三十章 客户/服务器程序设计范式)
TCP测试用客户程序 #include "unp.h" #define MAXN 16384 /* max # bytes to request from server */ in ...
- java equals与==区别
java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(== ...
- web前端的一些实用技能
如今我们使用的互联网,客户端与服务器端的交互无时无刻不在发生.比如我们在浏览器打开网页,浏览器就是客户端,将网页数据发过来的也就是服务器.其实服务器,并没有什么特别的,也就是一台昼夜不停运转的电脑罢了 ...
- 【甘道夫】Hadoop2.2.0 NN HA具体配置+Client透明性试验【完整版】
引言: 前面转载过一篇团队兄弟[伊利丹]写的NN HA实验记录,我也基于他的环境实验了NN HA对于Client的透明性. 本篇文章记录的是亲自配置NN HA的具体全过程,以及全面測试HA对clien ...
- DataTable去除空行
protected void removeEmpty(DataTable dt) { List<DataRow> removelist = new List<DataRow>( ...
- Rate Monotonic Scheduling algorithm
这篇文章写得不错 http://barrgroup.com/embedded-systems/How-To/RMA-Rate-Monotonic-Algorithm 另外rtems的官方文档也有类似说 ...
- 未加载Microsoft.SqlServer.management.sdk.sfc version......
这个问题卡了我好久,于是决定记录下来,我这里缺失的是Microsoft.SqlServer.management.sdk.sfc version 12.0.0,当然你也可能后面是11开头的, 这个是由 ...
- 爬虫学习一系列:urllib2抓取网页内容
爬虫学习一系列:urllib2抓取网页内容 所谓网页抓取,就是把URL地址中指定的网络资源从网络中读取出来,保存到本地.我们平时在浏览器中通过网址浏览网页,只不过我们看到的是解析过的页面效果,而通过程 ...
- 嵌入式c语言笔试
1 读程序段,回答问题int main(int argc,char *argv[]){int c=9,d=0;c=c++%5;d=c;printf("d=%d\n",d);retu ...