【Qt象棋游戏】08_人机博弈高阶算法
文章目录
- 01 - 极大极小值算法
- 02 - 电脑和人类所有走棋路径
- 03 - 走一步看两步
- 04 - 走一步看多步
- 04 - 总结
01 - 极大极小值算法
上一期博客介绍了最为简单的人机博弈算法,包括获取所有合法路径,简单的估值以及电脑走棋,本期博客在介绍估值算法上增加极大极小值算法(Minmax算法),让电脑走棋更加智能化。
极大极小值算法是一种找出失败的最大可能性中的最小值的算法,即最小化对手的最大收益。举个栗子,电脑为A,人类为B,A在走棋之前需要考虑A走了某一步之后,看看B有哪些走法,B又不傻,所以B肯定是要选择让A得分最小的走法走棋,而A就是在A的所有走法中选择B给出让A得分最小的走法中得分最多的走法。听起来比较抽象,试着多读几遍就理解了。
电脑导入极大极小值算法分以下3步:
(1)在当前局面下获取电脑所有走棋路径,并试着走一下;
(2)在电脑试着走完一步基础上获取人类所有走棋路径,并以人类的视角试着走一下,然后评估局面分(局面分是以电脑角度计算的,即电脑总分 - 人类总分),遍历完人类所有走棋路径后返回这些局面中的最小值(对电脑最不利而对人类最优利的情况);
(3)在上一步返回的局面分的最小值中,找到最大值,并且锁定与该最大值对应的走棋路径作为“步”返回值返回。
02 - 电脑和人类所有走棋路径
实现算法第一步是要获取电脑和人类的所有走棋路径,所以对getAllPossibleMove函数稍微做出以下修改:
/**** @brief : 获取所有棋子可行走的步骤** @param : steps : 保存移动棋子信息的属性(原坐标、目标坐标、ID、目标ID)** @return: 无***/
void ChessArea::getAllPossibleMove(QVector<Step *> &steps)
{int min = 16, max = 32;if(this->bRedTurn){min = 0;max = 16;}//遍历所有黑方棋子for(int i = min; i < max; i++){//如果棋子已死则直接跳过if(myChess[i].isDead)continue;// 遍历所有行坐标for(int x=0; x<9; x++){// 遍历所有列坐标for(int y=0; y<10; y++){//获取想要杀死的棋子的idint killid = this->getChessID(x, y);//若想要杀死的棋子与行走的棋子颜色相同则跳过if(sameColor(i, killid))continue;//判断某一棋子能不能行走if(canMove(i, killid, x, y)){//将可以行走的“步”存放到steps中saveStep(i, killid, x, y, steps);}}}}
}
03 - 走一步看两步
跟上一期博客相比,我们不再调用calcScore估值函数直接计算出对电脑最有利的分值而实施走棋,而是先代用getMinScore函数计算出对电脑最不利而对人类最优利的分值,并在局面分的最小值中,找到最大值,实现“走一步看两步”。
/**** @brief :获取电脑最优移动路径** @param : 无** @return: 最优棋子信息的属性(原坐标、目标坐标、ID、目标ID)***/
Step *ChessArea::getBestMove()
{QVector<Step *> steps;// 获取电脑的所有走棋路径getAllPossibleMove(steps);// 初始化比重int maxScore = -100000;Step* ret;for(QVector<Step*>::iterator it=steps.begin(); it!=steps.end(); ++it){Step* step= *it;//试着走一下fakeMove(step);//获取电脑当前走法下对自己最不利的分值int score = getMinScore(level-1);//再走回来unfakeMove(step);//取最高的分数if(score > maxScore){maxScore = score;ret = step;}}return ret;
}
/**** @brief : 获取人类下一步走法对电脑最不利的分数** @param : 无** @return: 对电脑最不利的分数值***/
int ChessArea::getMinScore()
{QVector<Step*> steps;bRedTurn = true;// 获取人类的所有走棋路径getAllPossibleMove(steps);bRedTurn = false;int minScore = 100000;for(QVector<Step*>::iterator it=steps.begin(); it!=steps.end(); ++it){Step* step=*it;// 以人类的视角试着走一下fakeMove(step);//评估局面分int score = calcScore();qDebug() << QString("红旗评分: %1").arg(score);// 再走回来unfakeMove(step);// 找到对电脑最不利的分数作为返回值返回if(score < minScore){minScore=score;}}return minScore;
}
到目前为止,电脑下棋已经变得更加智能了,大概效果如下:
从运行效果可以看出,我吃掉电脑的炮后,它出了車,我把炮放在它眼前,它反而不吃,因为它知道我在拿炮钓它的車,这个便是实现了“走一步看两步”的博弈算法智能。
04 - 走一步看多步
既然能实现“走一步看两步”,那么是不是能实现“走一步看三步”乃至更多步的人工智能呢?答案是肯定的。我们可以用递归的思想改写前面介绍的getBestMove函数和getMinScore函数,然后在家一个递归的getMaxScore函数,用Level表示递归深度,Level越大,电脑越聪明,这样就能实现“走一步看多步”。
level = 3; // widget初始化时,设置优化等级3
/**** @brief : 调用回调函数getMinScore获得局面最大分数** @param : 无** @return: 最大分数值***/
int ChessArea::getMaxScore(int level)
{if(level == 0)return calcScore();QVector<Step*> steps;getAllPossibleMove(steps);int maxScore = -100000;for(QVector<Step*>::iterator it=steps.begin();it!=steps.end(); ++it){Step* step=*it;fakeMove(step);int score = getMinScore(level-1);unfakeMove(step);if(score>maxScore){maxScore=score;}}return maxScore;
}
/**** @brief : 获取人类下一步走法对电脑最不利的分数(可回调)** @param : 无** @return: 对电脑最不利的分数值***/
int ChessArea::getMinScore(int level)
{if(level == 0)return calcScore();QVector<Step*> steps;bRedTurn = true;// 获取人类的所有走棋路径getAllPossibleMove(steps);bRedTurn = false;int minScore = 100000;for(QVector<Step*>::iterator it=steps.begin();it!=steps.end();++it){Step* step=*it;fakeMove(step);int score = getMaxScore(level-1);unfakeMove(step);if(score<minScore){minScore=score;}}return minScore;
}
/**** @brief :获取电脑最优移动路径** @param : 无** @return: 最优棋子信息的属性(原坐标、目标坐标、ID、目标ID)***/
Step *ChessArea::getBestMove()
{QVector<Step *> steps;// 获取电脑的所有走棋路径getAllPossibleMove(steps);int maxScore = -100000;Step* ret;for(QVector<Step*>::iterator it=steps.begin(); it!=steps.end(); ++it){Step* step= *it;fakeMove(step);int score = getMinScore(level-1);unfakeMove(step);if(score > maxScore){maxScore = score;ret = step;}}return ret;
}
下面看看电脑实现“走一步看三步”的下棋效果:
04 - 总结
注意Level值不要设置太大,回调深度越大消耗内存越严重,我电脑是4G内存,Level值设置为4,走棋就非常卡顿,后期基本卡死了,原因是后期棋子变少,活着的棋子行走的选择会越多,因此占用内存会越大,直到程序崩溃。
到目前为止,整个象棋的人工博弈算法算是讲完了,实际的效果不错,可以自己搭建电脑端玩一玩。
- 01_开发象棋游戏简介
- 02_绘画象棋棋盘
- 03_象棋棋子摆放
- 04_象棋走棋规则——車、炮、士
- 05_象棋走棋规则——象、马、将、兵
- 06_象棋游戏法则
- 07_人机博弈算法开端
- 08_人机博弈高阶算法
【Qt象棋游戏】08_人机博弈高阶算法相关推荐
- 【Qt象棋游戏】07_人机博弈算法开端
文章目录 01 - 人机博弈算法简述 02 - 相关成员与方法 03 - 获取电脑棋子能走路径 04 - 电脑走棋 05 - 总结 01 - 人机博弈算法简述 前面详细介绍了棋盘类的封装.棋子类的 ...
- 【Qt象棋游戏】03_象棋棋子摆放
文章目录 01 - 加载棋子UI资源 02 - 添加棋子属性类 03 - 添加棋子标签 04 - 效果 05 - 总结 棋子图片百度云链接: 01 - 加载棋子UI资源 添加制作好的棋子UI图片到 ...
- 【Qt象棋游戏】02_绘画象棋棋盘
文章目录 01 - 相关成员与方法 02 - 棋盘颜色 03 - 绘画棋盘线 04 - 添加"井"字格 05 - 总结 01 - 相关成员与方法 进行代码编写之前,在chess ...
- 【Qt象棋游戏】06_象棋游戏法则
文章目录 01 - 象棋游戏规则 02 - 鼠标移动事件 03 - 鼠标点击事件 04 - 总结 01 - 象棋游戏规则 实现上两章节的棋子走棋规则后,开始思考象棋游戏规则,比如轮到谁走,怎么判断 ...
- 【Qt象棋游戏】04_象棋走棋规则——車、炮、士
文章目录 01 - 象棋规则 02 - 棋子移动规则 03 - 車能否移动 04 - 炮能否移动 05 - 士能否移动 06 - 总结 01 - 象棋规则 经过两篇前面棋盘和棋子绘制,象棋框架基本 ...
- Python+PyQt5实现五子棋游戏(人机博弈+深搜+α-β剪枝)
Python+PyQt5实现五子棋游戏(人机博弈+深搜+α-β剪枝) 一.问题描述 1.五子棋 五子棋是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏. 五子棋的棋具与围棋通用,是一种传 ...
- 微信小游戏客服API高阶用法
为了更好的提升用户和游戏运营商的沟通,微信提供了客服API,游戏内创建一个图标按钮,点击可以打开客服会话窗口,用户可以发送文字.语言等信息,运营客服人员在后台可以看到并进行回复. 前端很简单的代码: ...
- 基于QT实现的alpha-beta剪枝算法搜索的象棋人机博弈游戏
中国象棋是一个古老的而富有智慧的游戏,而中国象棋博弈程序是将计算机知识和中国象棋知识结合起来的一种新型的游戏方式.它以一种全新的人机博弈方式突破了以往传统象棋游戏只能人与人对战的限制,使得这个古老的游 ...
- 【180629】C++版智商超高的中国象棋游戏源码
这个中国象棋游戏可谓智商比较高,有时候你就是比不过电脑,哈,不服气不行, 试着玩了一局,没有赢电脑,因时间关系没有下第二局.不过,程序中还是有一点点缺憾,希望高人能够修正,使其更完美和再次提高智商. ...
最新文章
- 解答:CF截图保存在哪
- 零基础Java学习之初级项目实践(客户信息管理软件-附源码)
- 【注意点分析】1016 Phone Bills (25 分)
- debian/ubuntu19.10下安装使用护眼软件f.lux
- android 广告弹出层,安卓广告活动弹窗控件 android-adDialog
- 李学斌:广告的罪恶与救赎
- JavaScript基本语法2
- Ubuntu sudo nopasswd方法
- 【备忘】mysql优化工具
- 群晖ds3617xs_23739虚拟机安装与半洗白教程
- 70 行 Python 代码写春联,支持行书隶书楷书!
- Adreno Profiler分析任意安卓游戏特效+抓取资源
- 网页源文件代码隐藏的代码(转)
- c++ 海战棋_GitHub - yifeitao/SimpleProgrammingProblems: 简单编程问题集中译版
- 14: PYCURL ERROR 6 - Couldn't resolve host 'mirro
- 北京交通大学计算机博士导师,董平(北京交通大学教授、博士生导师)_百度百科...
- Android获取软键盘输入内容
- 爱情智慧:结婚是什么感觉
- 数据库索引(B树,B+树,哈希)
- mysql随机生成数据并插入_python生成随机数据插入mysql
热门文章
- python调用sendcloud模板发送带附件的邮件
- 微软的“胡萝卜”会比“大棒”更有效吗
- 天涯共此双11——天猫升级港澳台“购物天堂”
- 爬山的蜗牛旅程:java内存结构
- 随机码生成器[10位字母+数字]
- 软件工程概论-- 详细设计,过程设计的6大工具:程序流程图,判定表,N-S图和判定树之间的区别, PAD图的优点?
- 中山计算机专硕不用发sci,最新!专硕发84篇SCI遭质疑,本人回应了
- 1.2 cuda相关常见错误记录(不断更新)
- 需要在计算机安装msxml版本,安装Office2010提示需要MSXML版本6.10.1129.0的解决方法...
- Matlab 基于IRLS的加权Cauchy稳健估计算法之二