更多精彩,请点击上方蓝字关注我们!

今天我想要分享一下我做五子棋AI的思路。因为在做这个之前,我没有接触过任何像这种类似的东西。通过这一次,我也算是有所了解,我的思路也是来自很多网络上的博客,看了很多,最终总结出了自己的这样一个。

那我的五子棋是15*15的大小(一般也就是这样的一个大小)。我的AI算法要求每一次落子之后都要去计算每一个空暇的位置的“分值”,简单的说,我们需要一个存放棋子的数组,表示是否存放了棋子,还要一个计算每一个空格的数组来记录“分数”,这个分数是后期AI用来运算的基础,也是你AI难度控制的点。

我现有的思路就是分两部分。首先是如果是玩家先落子,那么要求电脑AI随即在你落子的地方的任意一个方向,随机落子,这是第一步。接下来以后就正式进入到算法中去。

首先初始化你的分数数组,让他们全部为零。然后在每一次落子之后进行全盘的遍历,如果发现该处为空白,于是检查其四周八个方向(当然如果是边缘位置就相对修改,判断是否出了边界)。若在空白处,且发现在某一对角线方向发现有一个其他颜色的棋子,那么相对的给这个空白区域的分数数组加上一定的分值,然后继续往这个方向检测是否还有连续的同一颜色的棋子,若没有则检查其他方向或者检测下一个空白位置。若是还在同一方向上面找到了相同颜色的棋子,那么第二个棋子的出现,你可以给改空白处加上双倍的分值,表明这个空白位置更加重要。一次类推,继续检测。(PS:因为最终AI棋子落在什么地方,依靠的是最后遍历整个分数数组,然后根据分数的高低来进行判断落子落在哪里的,在下面讲)。

经过上一遍的遍历,每一次落子都会使得分数数组得到一些变化,每一次都会导致AI判断的变化。在这个基础上,每一次落子还要进行一次对自己本身棋子颜色的一个遍历,判断自己的情况,同时加分加在分数数组之中,这样一来,电脑就会根据自己的棋子的情况以及玩家的落子情况进行判断,哪一个地方更加适合落子。

因为我是第一次做AI,网络上搜到的一些思想一般也是这种类似的遍历思想。理解了以后写代码就比较方便。最后可能会有一些点的分数是相同的,所以还有设置一下随机落子。把分数相同的地点随机落子。

个人感觉AI的强弱是根据你每一次给他增加分数的多少来确定的。这个我的AI有时候也会抽风,不过一般情况比较正常,可能运气也占了一部分,当初设计加分的时候其实没想那么多,现在却发现好像还不错。

大家要多去实践练习,多改改分数可能就会出来不错的AI了,o(^▽^)o。

下面贴上我的代码!

void GameScene::Robot(int *x, int *y, int *Sum)
{ExWhile1 = true;if (*Sum == 1){while (ExWhile1){ChessOne(*x, *y);if (ch[*x][*y] == 2){ ExWhile1 = false; }}ch[*x][*y] = tp;   //记录这个点printpart(*x, *y, tp);     //打印出电脑AI第一次落子isTouch = true;tp++;tp = tp % 2;}else      //从第2步开始,使用评分系统{Findscore(*x, *y);}
}void GameScene::Findscore(int &x, int &y)   //查找评分最高的坐标
{srand((unsigned)time(NULL));int i, j, x1, x2, y1, y2, lx;int Max = 0;ChessScore();      //调用评分函数for (i = 0; i<15; i++){for (j = 0; j<15; j++){if (Score[i][j]>Max){Max = Score[i][j];  //获取所有点中,评分最高的x1 = i;y1 = j;}}}x2 = x1; y2 = y1;for (i = 0; i<15; i++)    //可能的话,有评分相同的多个点{for (j = 0; j<15; j++){if (Score[i][j] == Max&&i != x2&&j != y2)   //在这么多个相同分数的点中,随机找一个{lx = rand() % 10;if (lx<5){x2 = i, y2 = j;break;}}}}if (x2 != x1 || y2 != y1)   //棋盘上有2个最高分{lx = rand() % 10;    //随机一个if (lx>6){x = x1, y = y1;}else{x = x2, y = y2;}}else    //棋盘上只有一个最高分{x = x1, y = y1;}Max = 0;    //清空最大值ch[x][y] = tp;       //记录这个点printpart(x, y, tp);    //打印出电脑AI落子if (winerValue==2){isTouch = true;}tp++;tp = tp % 2;
}inline void GameScene::ChessOne(int &x, int &y)   //玩家走第1步时的落子
{int i, j;srand((unsigned)time(NULL));    //随机数随着时间的改变而改变for (i = 0; i<15; i++){for (j = 0; j<15; j++){if (ch[i][j] == 0)  //如果找到了玩家的棋子,在它的8个方的任意一点落子{int lx = rand() % 7;if (lx == 0){x = i + 1; y = j + 1;if (ch[x][y] == 2){ break; }}else if (lx == 1){x = i + 1; y = j - 1;if (ch[x][y] == 2){ break; }}else if (lx == 2){x = i - 1; y = j - 1;if (ch[x][y] == 2){ break; }}else if (lx == 3){x = i - 1; y = j + 1;if (ch[x][y] == 2){ break; }}else if (lx == 4){x = i - 1; y = j;    //上if (ch[x][y] == 2){ break; }}else if (lx == 5){x = i; y = j - 1;   //左if (ch[x][y] == 2){ break; }}else if (lx == 6){x = i; y = j + 1;   //右if (ch[x][y] == 2){ break; }}else{x = i + 1; y = j;    //下if (ch[x][y] == 2){ break; }}}}}
}void GameScene::ChessScore()
{int x, y, i, j, k;      //循环变量int number1 = 0, number2 = 0;   //number用来统计玩家或电脑棋子连成个数int empty = 0;    //empty用来统计空点个数memset(Score, 0, sizeof(Score));                    //把评分数组先清零for (x = 0; x<15; x++){for (y = 0; y<15; y++){if (ch[x][y] == 2)    //如果这个点为空  {for (i = -1; i <= 1; i++){for (j = -1; j <= 1; j++)   //判断8个方向  {if (i != 0 || j != 0)   //若是都为0的话,那不就是原坐标嘛{//对玩家落点评分for (k = 1; i <= 4; k++)   //循环4次{                        //这点没越界  且这点存在黑子(玩家)if (x + k*i >= 0 && x + k*i <= 14 &&  y + k*j >= 0 && y + k*j <= 14 &&  ch[x + k*i][y + k*j] == 0){  number1++;}else if (ch[x + k*i][y + k*j] == 2)     //这点是个空点,+1后退出{  empty++;  break;  }    else                    //否则是墙或者对方的棋子了  {  break;  }     }for (k = -1; k >= -4; k--)            //向它的相反方向判断  {                        //这点没越界  且这点存在黑子(玩家)if (x + k*i >= 0 && x + k*i <= 14 &&y + k*j >= 0 && y + k*j <= 14 &&  ch[x + k*i][y + k*j] == 0){  number1++;}else if (ch[x + k*i][y + k*j] == 2)     //这点是个空点,+1后退出{  empty++;  break;  }   else{  break;}}if (number2 == 1)   //2个棋子  {  Score[x][y] += 1;  }   else if (number1 == 2)   //3个棋子  {if (empty == 1)     {Score[x][y] += 5;   //有一个空点+5分 死3  }      else if (empty == 2)  {  Score[x][y] += 10;  //有两个空点+10分 活3}  }else if (number1 == 3)   //4个棋子  {if (empty == 1)    {  Score[x][y] += 20;  //有一个空点+20分 死4  }   else if (empty == 2){  Score[x][y] += 100;  //有2个空点+100分 活4}   }else if (number1 >= 4)   {  Score[x][y] += 1000;  //对方有5个棋子,分数要高点,先堵}   empty = 0;   //统计空点个数的变量清零  //对电脑落点评分for (k = 1; i <= 4; k++)   //循环4次{       //这点没越界  且这点存在白子(电脑)if (x + k*i >= 0 && x + k*i <= 14 &&  y + k*j >= 0 && y + k*j <= 14 &&  ch[x + k*i][y + k*j] == 1){  number2++;}else if (ch[x + k*i][y + k*j] == 2){  empty++; break;   //空点}  else{break;}}for (k = -1; k >= -4; k--)   //向它的相反方向判断  {if (x + k*i >= 0 && x + k*i <= 14 &&y + k*j >= 0 && y + k*j <= 14 &&  ch[x + k*i][y + k*j] == 1){  number2++;}else if (ch[x + k*i][y + k*j] == 2){  empty++; break;}else{  break;   //注释与上面玩家版相同}       }if (number2 == 0)    {  Score[x][y] += 1;    //1个棋子}  else if (number2 == 1)   {Score[x][y] += 2;    //2个棋子  }    else if (number2 == 2)   //3个棋子{if (empty == 1)    {  Score[x][y] += 8;  //死3}   else if (empty == 2)  {  Score[x][y] += 30;  //活3  }  }else if (number2 == 3)   //4个棋子{if (empty == 1)    {  Score[x][y] += 50;   //死4}   else if (empty == 2)  {  Score[x][y] += 200;   //活4}   }else if (number2 >= 4)  {  Score[x][y] += 10000;   //自己落在这点能形成5个,也就能胜利了,分数最高}  number1 = 0;     //清零,以便下次重新统计number2 = 0;                   empty = 0;}}}}}}
}

它,

不仅仅是一个码

扫码关注

C++资源免费送

基于C++实现五子棋AI算法思想相关推荐

  1. 基于博弈树的五子棋 AI 算法及其 C++ 实现

    基于博弈树的五子棋 AI 算法及其 C++ 实现 摘要 一   五子棋的游戏规则 二   五子棋对弈的算法描述 2.1 博弈树搜索算法 2.2 α ─ β 剪枝 2.3 估价函数 三   五子棋对弈的 ...

  2. java五子棋AI算法人机对战(春物彩羽版可下载试玩PC端)

    五子棋AI算法 前言: 坐标西安,写于疫情封城期间.改进了之前写的基于极大极小值策略AI五子棋游戏,是用java实现的,采用了java老旧的jframe窗体和绘图类.写好之后整理成了这篇博客. 游戏采 ...

  3. 基于单层决策树的adaBoost算法思想分析和源代码解析

    基于单层决策树的AdaBoost算法思想分析和源代码解析 前言: 上一篇SVM可是废了我好鼻子劲,这一篇咱们来点愉快的东西.我们一定听说过这句俗语:"三个臭皮匠,顶个诸葛亮!" 大 ...

  4. 基于openGauss的五子棋AI项目

    目录 1 前言 2 方案意义 3 架构设计 4 数据表设计 5 代码结构 6 项目演示 7 总结 1 前言 openGauss是一款全面友好开放的企业级开源关系型数据库.openGauss采用木兰宽松 ...

  5. 基于 openGauss 的五子棋 AI 项目,openGauss 设计一个 AI 小 demo

    目录 1 前言 2 方案意义 3 架构设计 4 数据表设计 5 代码结构 6 项目演示 7 总结 1 前言 openGauss 是一款全面友好开放的企业级开源关系型数据库.openGauss 采用木兰 ...

  6. (只此一篇便绝b能懂的)五子棋AI算法原理,博弈树、极大极小搜索、αβ剪枝

    我在最近撰写五子棋AI程序设计报告时,翻阅了很多的资料博客,但却发现大佬们的博客,没有一篇是能让我只看它就能理解全部的AI算法.在看了众多博客后,我终于对博弈树.极大极小搜索.αβ剪枝恍然大悟,其实这 ...

  7. 五子棋AI算法第三篇-Alpha Beta剪枝

    剪枝是必须的 五子棋AI教程第二版发布啦,地址:https://github.com/lihongxun945/myblog/labels/%E4%BA%94%E5%AD%90%E6%A3%8BAI% ...

  8. Cocos2d-x制作跳棋第三步:棋子动作实现及AI算法思想

     上周跟大家分享了Cocos2d-x跳棋制作如何建立工程和界面编写,今天来      跟大家分享一下如何实现棋子相关动作及AI思想.             在跳棋中棋子有两种动作:移动.跳跃.   ...

  9. 课程设计书五子棋AI算法及其实现

    五子棋AI,能根据棋盘局势判断棋子应落在何处获胜,主要算法有权值法和博弈树法两种实现方案. 权值法 在数理统计中,有一种名为蒙特卡洛法的方法常被使用,其主要内容为:根据事件出现的概率估计某些特征,并将 ...

最新文章

  1. Intellij IDEA 添加jar包
  2. 第四次作业,孙保平034
  3. 计算机应用技术概括,计算机应用技术学科各学科方向简介
  4. ZABBIX 3.2 基础安装
  5. 基线_Origin入门教程(九):扣除基线常用小妙招
  6. gin-控制器分组:
  7. threejs - uv 映射 简要
  8. 模拟斗地主发牌, 把54张牌发给三个玩家, 地主多三张, 对每个玩家的牌进行排序
  9. 第一次使用Maven,新建Maven项目时更新出错出现Unable to update maven configuration following project...
  10. 腾讯受邀参加2019世界移动通信大会5G论坛,分享5G技术探索
  11. Axure RP 9.0.0.3719 更新日志 授权码
  12. 写一篇2万字的大学生消费情况调查报告
  13. 淘宝arduino虚拟键盘开发环境及对应键盘按键代码
  14. ORB-SLAM2的源码阅读(十一):LoopClosing类
  15. 使用 CSS 构建自定义粘性导航栏
  16. android 小米字体大小,Android仿小米巨无霸字体调整控件
  17. 如何下载SOLIDWORKS块库?
  18. 利用PhotoShop自定义艺术字体
  19. 机房对拷软件使用随记 非ABC类IP能作为局域网吗?
  20. 从IBM、甲骨文、SAP合作中分析,互操作网络的重要性

热门文章

  1. aes256加密java_使用Java和JCEKS进行AES-256加密
  2. 八位图 16位图_了解位图
  3. 休眠面试问答-最终清单
  4. Java Iterator到Java 8 Stream
  5. 占用内存的Enum.values()方法
  6. jboss eap 7.0_创建委托登录模块(用于JBoss EAP 6.1)
  7. Kafka的Spring Cloud Stream
  8. [MEGA DEAL]完整的Java编程训练营(94%)
  9. 使用Java扫描DynamoDB项目
  10. 带有Netflix Ribbon的Spring Cloud Rest Client-基础知识