c++ 五子棋AI 算法及实现 详细解析

2020.11.17日更新

今天我看到有人fork了我的这个项目,其实怪不好意思的,因为现在看来,这个项目写的实在不咋地。我后来又用java swing写了一个人工智能五子棋,并对算法进行了优化,如果想fork的话,还是fork这个新的项目吧 😃
Github链接:gobang-ver4.0-JavaSwing




前言

  这次的五子棋AI是我写的第三版,前两版因为自己的开发项目不充足,导致最后写出的程序Bug众多,无法修改,第三版重新设计了算法,并使用了多文件结构,最后顺利完成了。
  根据之前查询的资料我了解到,要想写出无可匹敌的五子棋AI,要用到博弈树、AlphaBeta减枝法、机器学习等知识,但是因为个人水平的原因,这些都无法实现,不过我的算法起码能保证玩家稍不留神,就会被打败,这和五子棋新手博弈、OJ霸榜,都足够了。等到日后自己的知识量增加了,再来对这个程序进行完善吧。

效果展示

这里先展示一下最后的效果
在这里插入图片描述
程序下棋的水平还是可以的,日常拿来消遣一下也没什么问题。

五子棋棋型介绍

  在设计五子棋算法之前,要对五子棋的算法有基本的了解,这里我借用别人的文章来介绍。原文链接

  最常见的基本棋型大体有以下几种:连五,活四,冲四,活三,眠三,活二,眠二。

连五:顾名思义,五颗同色棋子连在一起,不需要多讲。


图1-1

活四:有两个连五点(即有两个点可以形成五),图中白点即为连五点。
稍微思考一下就能发现活四出现的时候,如果对方单纯过来防守的话,是已经无法阻止自己连五了。


图2-1

冲四:有一个连五点,如下面三图,均为冲四棋型。图中白点为连五点。
相对比活四来说,冲四的威胁性就小了很多,因为这个时候,对方只要跟着防守在那个唯一的连五点上,冲四就没法形成连五。


图3-1

图3-2

图3-3

活三:可以形成活四的三,如下图,代表两种最基本的活三棋型。图中白点为活四点。
活三棋型是我们进攻中最常见的一种,因为活三之后,如果对方不以理会,将可以下一手将活三变成活四,而我们知道活四是已经无法单纯防守住了。所以,当我们面对活三的时候,需要非常谨慎对待。在自己没有更好的进攻手段的情况下,需要对其进行防守,以防止其形成可怕的活四棋型。


图4-1

图4-2

眠三:只能够形成冲四的三,如下各图,分别代表最基础的六种眠三形状。图中白点代表冲四点。眠三的棋型与活三的棋型相比,危险系数下降不少,因为眠三棋型即使不去防守,下一手它也只能形成冲四,而对于单纯的冲四棋型,我们知道,是可以防守住的。


图5-1

图5-2

图5-3

图5-4

图5-5

图5-6

如上所示,眠三的形状是很丰富的。对于初学者,在下棋过程中,很容易忽略不常见的眠三形状,例如图5-6所示的眠三。

有新手学了活三眠三后,会提出疑问,说活三也可以形成冲四啊,那岂不是也可以叫眠三?
会提出这个问题,说明对眠三定义看得不够仔细:眠三的的定义是,只能够形成冲四的三。而活三可以形成眠三,但也能够形成活四。

此外,在五子棋中,活四棋型比冲四棋型具有更大的优势,所以,我们在既能够形成活四又能够形成冲四时,会选择形成活四。

温馨提示:学会判断一个三到底是活三还是眠三是非常重要的。所以,需要好好体会。
后边禁手判断的时候也会有所应用。

活二:能够形成活三的二,如下图,是三种基本的活二棋型。图中白点为活三点。
活二棋型看起来似乎很无害,因为他下一手棋才能形成活三,等形成活三,我们再防守也不迟。但其实活二棋型是非常重要的,尤其是在开局阶段,我们形成较多的活二棋型的话,当我们将活二变成活三时,才能够令自己的活三绵绵不绝微风里,让对手防不胜防。


图6-1

图6-2

图6-3

眠二:能够形成眠三的二。图中四个为最基本的眠二棋型,细心且喜欢思考的同学会根据眠三介绍中的图2-13找到与下列四个基本眠二棋型都不一样的眠二。图中白点为眠三点。


图7-1

图7-2

图7-3

图7-4

算法解析

基本概念

  在介绍算法之前,要将程序里的一些基本概念介绍一下。
  标准五子棋棋盘一般是15X15的大小(当然程序里可以随意改)。
  我后面会将连五,活四,冲四,活三,眠三,活二,眠二称为特殊棋型,这样可以节约博客字数。
  对于棋盘上的排成直线的一串棋子,有横、竖、左上到右下,左下到右上四种方向,我将其命名为 横(LAY)、竖(STAND)、主对角(MAIN)、副对角(VICE)
  对于某一个方向上的排成一条直线的棋子,我称其为棋链,如下方的图就是一个棋链
在这里插入图片描述
这个棋链是竖向(STAND)的,当然,棋链也可以是横向(LAY)、主对角向(MAIN)的副对角向(VICE)的
  程序中有当前棋子上一个、下一个的概念,LAY的后一个是右一个;STAND的后一个是往下一个;MAIN的下一个是往右下一个;VICE的下一个是往右上一个。

算法

简略介绍

  程序的算法概括起来讲,是找到棋盘上的空位,首先假设该空位上放上棋子,然后计算这个位置四个方向上的连五,活四,冲四,活三,眠三,活二,眠二的个数,并根据这些棋型由高到低进行赋分。
  当为所有空位赋完分后,遍历所有空位,找到分值最大的空位,并在该空位上放上棋子。

详细介绍

下面对算法的细节进行更为详细的介绍:
  在获取空位四个方向的棋子时不但要注意获得的棋子长度,还要注意该空位在棋链中的位置,拿一个长度为5的连5棋链来说,该空位可能位于第1或2或…第5个位置,也就是说,判断一个空位在四个方向、五个位置是否为连5,要取得4X5共20个棋链,,而一条棋链最长长度为7,也就是说,获取一个空位的棋型数,最坏一共要取得4X7=28条棋链。下面我通过代码形象地展示全过程。

getChessChain()返回空位棋子ce、LAY,STAND,MAIN,VICE四个方向、长度为n,棋链位置为loc的四条棋链

std::vector<std::vector<Chess>> getChessChain(Chess ce,int n,int loc);

下面四个函数分别返回长度为four,five,six,seven;空位棋子为ce、方向为dir、位置为loc的一条棋链

std::vector<Chess> fourChain(Chess ce, int dir, int loc);
std::vector<Chess> fiveChain(Chess ce, int dir, int loc);
std::vector<Chess> sixChain(Chess ce, int dir, int loc);
std::vector<Chess> sevenChain(Chess ce, int dir, int loc);

下面7个函数分别返回长度为one,two,three,four,five,six,seven;空位棋子为ce、长度为n,方向为dir的的一条棋链

std::vector<Chess> inDirOne(Chess ce,int n,int dir);
std::vector<Chess> inDirTwo(Chess ce,int n,int dir);
std::vector<Chess> inDirThree(Chess ce,int n,int dir);
std::vector<Chess> inDirFour
  • 71
    点赞
  • 377
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
五子棋AI算法C是一个用于实现五子棋AI的程序代码。它包含了一系列函数和算法来评估棋局、选择最佳下棋位置以及实现自动下棋。 在这个算法中,棋盘一般是15x15的大小,但可以根据需要进行修改。为了简化描述,作者将连五、活四、冲四、活三、眠三、活二、眠二等特殊棋型统称为特殊棋型。 对于棋盘上的一串棋子,有横向、竖向、左上到右下和左下到右上四种方向,分别命名为横(LAY)、竖(STAND)、主对角(MAIN)和副对角(VICE)。 在程序中,有当前棋子的上一个和下一个的概念,例如在横向上,上一个是左边一个,下一个是右边一个。 该算法还包括函数getChessChain(),用于返回某个空位棋子ce周围长度为n的横向、竖向、主对角和副对角的棋链。 总的来说,五子棋AI算法C通过评估棋局、分析棋型和选择最佳下棋位置来实现自动下棋。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [c++ 五子棋AI 算法实现 详细解析](https://blog.csdn.net/weixin_44062380/article/details/105881036)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FARO_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值