隔了一年才把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的思路的更多相关文章

  1. 五子棋AI大战OC实现

    Gobang 五子棋AI大战,该项目主要用到MVC框架,用算法搭建AI实现进攻或防守 一.项目介绍 1.地址: github地址:Gobang 2.效果图: 二.思路介绍 大概说下思路,具体看代码实现 ...

  2. 使用QT creator实现一个五子棋AI包括GUI实现(8K字超详细)

    五子棋AI实现 五子棋游戏介绍 五子棋的定义 五子棋是全国智力运动会竞技项目之一,是具有完整信息的.确定性的.轮流行动的.两个游戏者的零和游戏.因此,五子棋是一个博弈问题. 五子棋的玩法 五子棋有两种 ...

  3. 五子棋AI清月连珠开源

    经过差不多两年的业余时间学习和编写,最近把清月连珠的无禁手部分完善得差不多了.这中间进行了很多思考,也有很多错误认识,到现在有一些东西还没有全面掌握,所以想通过开源于大家共同交流. 最近一直发表一些五 ...

  4. 五子棋AI教程

    https://github.com/Chuck-Ai/gobang 我写了非常详细的中文教程,教你如何一步步编写自己的五子棋AI: 五子棋AI设计教程第二版一:前言 五子棋AI设计教程第二版二:博弈 ...

  5. 【五子棋AI循序渐进】——开局库

    首先,对前面几篇当中未修复的BUG致歉,在使用代码时请万分小心…………尤其是前面关于VCF\VCT的一些代码和思考,有一些错误.虽然现在基本都修正了,但是我的程序还没有经过非常大量的对局,在这之前,不 ...

  6. 【五子棋AI循序渐进】关于VCT,VCF的思考和核心代码

    前面几篇发布了一些有关五子棋的基本算法,其中有一些BUG也有很多值得再次思考的问题,在框架和效果上基本达到了一个简单的AI的水平,当然,我也是初学并没有掌握太多的高级技术.对于这个程序现在还在优化当中 ...

  7. 人机ai五子棋 ——五子棋AI算法之Java实现

    人机ai五子棋 下载:chess.jar (可直接运行) 源码:https://github.com/xcr1234/chess 其实机器博弈最重要的就是打分,分数也就是权重,把棋子下到分数大的地方, ...

  8. C++ 之 简单的五子棋AI程序

    本人是大一新生,寒假无聊,抱着试试看的心态(没有想到可以完成),写了C++的简单五子棋程序,开心.     下面是效果图:     一.首先讲讲大致思路.            五子棋实现的基础:  ...

  9. 五子棋 AI(AIpha-beta算法)

    博弈树 下过五子棋的人都应该知道,越厉害的人,对棋面的预测程度越深.换句话讲,就是当你下完一步棋,我就能在我的脑海里假设把我所有可能下的地方都下一遍,然后考虑我下完之后你又会下在哪里,最后我根据每次预 ...

随机推荐

  1. tcpdump命令使用详解

    阅读(226) 一:命令介绍: tcpdump,用简单的语言概括就是dump the traffic on a network,是一个运行在linux平台可以根据使用者需求对网络上传输的数据包进行捕获 ...

  2. HDU 1875 畅通project再续 (最小生成树 水)

    Problem Description 相信大家都听说一个"百岛湖"的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其它的小岛时都要通过划小船来实现. 如今政府决定大力发展百岛 ...

  3. 数组方式使用jQuery对象

    一. 使用jQuery选择器获取结果是一个jQuery对象.然而,jQuery类库会让你感觉你正在使用一个定义了索引和长度的数组.在性能方面,建议使用简单的for或者while循环来处理,而不是$.e ...

  4. Javascript模式(二) 发布者/订阅者模式

    var publisher = { // 订阅者数组 subscribers : { "any" : [] }, // 增加订阅者 on : function(type, fn, ...

  5. java 内存与内存溢出

    学习自:http://www.codeceo.com/article/jvm-memory-overflow.html 讲的很清楚

  6. C打印函数printf的一种实现原理简要分析

    [0]README 0.1)本文旨在对 printf 的 某一种 实现 原理进行分析,做了解之用: 0.2) vsprintf 和 printf.c 的源码,参见 https://github.com ...

  7. WPF自定义选择年月控件详解

    本文实例为大家分享了WPF自定义选择年月控件的具体代码,供大家参考,具体内容如下 封装了一个选择年月的控件,XAML代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  8. mysql 5.5主从复制配置

    首先将主库现有的要实现主从的数据库原原本本地复制到从库上,目的是一开始就让主从同步,让binlog日志从最新的记录开始同步! 备份: 方法1:快捷导出所要的库如(库goods)[注意:该方法仅适合My ...

  9. 开源项目Universal Image Loader for Android 说明文档 (1) 简单介绍

     When developing applications for Android, one often facesthe problem of displaying some graphical ...

  10. Mysql代码建外键问题

    用下面代码建外键 运行之后 没有提示错误 但是打开建好的表格 外键并没有建立上 打开外键栏 里面并没有外键 在从表设置了外键列里面输入东西没有任何限制 成功建立应该是下面这样 什么情况???????? ...