本章开始,我们介绍主动出牌的算法,和被动出牌类似,我们第一步把主要架子搭起来。

首先清空出牌序列

clsHandCardData.ClearPutCardList();

主动出牌的策略按照优先级大体可以分为三类:

【一】能直接一手牌出去,优先出。

【二】两手牌出去且有绝对大牌,先出绝对大牌。

【三】出一手牌使得接下来自己手牌价值最大化。

//剪枝:如果能出去最后一手牌直接出CardGroupData SurCardGroupData = ins_SurCardsType(clsHandCardData.value_aHandCardList);//如果能一次性出去且没有炸弹,因为有炸弹的话权值可能会更大if (SurCardGroupData.cgType != cgERROR&&!HasBoom(clsHandCardData.value_aHandCardList)){Put_All_SurCards(clsHandCardData, SurCardGroupData);return;}

然后是【二】:目前2.0版本我们暂时不考虑记牌功能,所以绝对大牌只支持王炸,以后在这里可以做更多智能的处理。

/*王炸——当前策略只处理王炸作为倒数第二手的优先出牌逻辑,后续版本会在此基础上优化*/if (clsHandCardData.value_aHandCardList[17] > 0 && clsHandCardData.value_aHandCardList[16] > 0){clsHandCardData.value_aHandCardList[17] --;clsHandCardData.value_aHandCardList[16] --;clsHandCardData.nHandCardCount -= 2;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[16] ++;clsHandCardData.value_aHandCardList[17] ++;clsHandCardData.nHandCardCount += 2;if (tmpHandCardValue.NeedRound == 1){clsHandCardData.value_nPutCardList.push_back(17);clsHandCardData.value_nPutCardList.push_back(16);clsHandCardData.uctPutCardType = get_GroupData(cgKING_CARD, 17, 2);return;}}

接下来就是第三步, 就是我们选择打出一手牌尽量使得接下来自己手牌价值最大化。

与被动出牌不一样的是,主动出牌我们没有限制条件,我也尝试过全部枚举,不过时间消耗肯定是爆炸的。于是我定制了一个基本的出牌优先级策略:

①三带一、飞机等牌优先打出,因为这种牌型可以把小牌带出。其实这里对比较大的三带一不是很公平,后续版本可以在此处做分支处理,比如说三带一的话只循环到10,J以上先不着急打出。飞机倒还好说,那玩意基本管不到别人,所以出了就出了。至于四带二嘛。。。四带二是个什么东西?我不知道,我眼里只有炸弹。

所以,这部分的架子应该是这样的。

若可以出这几种牌型,选择一种价值最高的打出。因为要枚举所有的牌,所以在循环外根据最佳策略进行出牌处理。

②没有上述牌型后,优先处理当前最小的一张牌。若是该牌有四张,先不处理。

这里出牌处理就放在循环内了,因为当确定了这个i值后无论如何都是要打出一手牌的,且打完牌就可以return了。

③如果没有从3到2的非炸牌,那么看看有没有单王,如果有,可以出。

 //如果没有3-2的非炸牌,则看看有没有单王if (clsHandCardData.value_aHandCardList[16] == 1 && clsHandCardData.value_aHandCardList[17] == 0){clsHandCardData.value_nPutCardList.push_back(16);clsHandCardData.uctPutCardType = get_GroupData(cgSINGLE, 16, 1);return;}if (clsHandCardData.value_aHandCardList[16] == 0 && clsHandCardData.value_aHandCardList[17] == 1){clsHandCardData.value_nPutCardList.push_back(17);clsHandCardData.uctPutCardType = get_GroupData(cgSINGLE, 17, 1);return;}

④单王也没有,出炸弹。

//单王也没有,出炸弹for (int i = 3; i < 16; i++){if (clsHandCardData.value_aHandCardList[i] == 4){clsHandCardData.value_nPutCardList.push_back(i);clsHandCardData.value_nPutCardList.push_back(i);clsHandCardData.value_nPutCardList.push_back(i);clsHandCardData.value_nPutCardList.push_back(i);clsHandCardData.uctPutCardType = get_GroupData(cgBOMB_CARD, i, 4);return;}}

这里可能有人会想,需不需要再加上炸弹也没有,出王炸呢?其实不存在的,因为如果你真的没牌打了就剩王炸了,早在前面剪枝部分就处理了。

所以如果走到这里都没有返回的话,肯定是出现错误了。

把上述的各个模块连接起来,即构成主动出牌的基本架子:

void get_PutCardList_2(HandCardData &clsHandCardData)
{clsHandCardData.ClearPutCardList();//剪枝:如果能出去最后一手牌直接出CardGroupData SurCardGroupData = ins_SurCardsType(clsHandCardData.value_aHandCardList);//如果能一次性出去且不是四带二,因为主动出牌若手上剩四带二牌的话可以考虑先打一手然后炸,获得双倍积分if (SurCardGroupData.cgType != cgERROR&&SurCardGroupData.cgType!=cgFOUR_TAKE_ONE&&SurCardGroupData.cgType !=cgFOUR_TAKE_TWO){}/*王炸——当前策略只处理王炸作为倒数第二手的优先出牌逻辑,后续版本会在此基础上优化*/if (clsHandCardData.value_aHandCardList[17] > 0 && clsHandCardData.value_aHandCardList[16] > 0){}//暂存最佳的价值HandCardValue BestHandCardValue;BestHandCardValue.NeedRound = 20;BestHandCardValue.SumValue = MinCardsValue;//我们认为不出牌的话会让对手一个轮次,即加一轮(权值减少7)便于后续的对比参考。BestHandCardValue.NeedRound += 1;//暂存最佳的组合CardGroupData BestCardGroup;//带出去的牌int tmp_1 = 0;int tmp_2 = 0;int tmp_3 = 0;int tmp_4 = 0;//优先处理三牌、飞机等牌for (int i = 3; i < 16; i++){       }//这部分出牌处理放到循环外if (BestCardGroup.cgType == cgTHREE_TAKE_ONE){}else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO){}else if (BestCardGroup.cgType == cgTHREE_TAKE_ONE_LINE){}else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO_LINE){}//次之处理当前价值最低的牌,现在不必再考虑这张牌可能被三牌带出等情况for (int i = 3; i < 16; i++) {}//如果没有3-2的非炸牌,则看看有没有单王if (clsHandCardData.value_aHandCardList[16] == 1 && clsHandCardData.value_aHandCardList[17] == 0){      }if (clsHandCardData.value_aHandCardList[16] == 0 && clsHandCardData.value_aHandCardList[17] == 1){}//单王也没有,出炸弹for (int i = 3; i < 16; i++){}//异常错误clsHandCardData.uctPutCardType = get_GroupData(cgERROR, 0, 0);return;}

至此主动出牌的架子就搭好了,且除了三带牌型出牌策略及解决最小值牌出牌策略这两个大部分,其他部分代码本章均已给出,下一章我们开始实现三带牌型的出牌策略。

敬请关注下一章:斗地主AI算法——第十三章の主动出牌(2)

斗地主AI算法——第十二章の主动出牌(1)相关推荐

  1. 斗地主AI算法——第十四章の主动出牌(3)

    上一章已经排除了飞机.三带等牌型,那么除去炸弹王炸以外,我们只剩下单牌.对牌.三牌以及单顺.双顺.三顺了. 首先说单牌.对牌.三牌.其逻辑基本一样,只是出牌的个数有差别,即:如果该i牌数量满足这种牌型 ...

  2. 斗地主AI算法——第十五章の测试模块

    前面几章已经把整个斗地主AI算法工程完成的差不多了,接下来进入整合联调以及模拟测试模块. 测试模块主要任务就是代替服务器给出我们需要的数据.因为我们本来的计划是封装成类库通过服务器调用获取,其调用的接 ...

  3. 斗地主AI算法——第十六章の样例分析

    上一章,我们已经完成了测试模块的开发.至此我们已经可以进行整体测试了.本章主要内容就是对随机生成的对局情况进行简单的分析. 实际上整个开发过程绝大部分时间都是用在样例分析上,通过样例给出的返回操作分析 ...

  4. 斗地主AI算法——第十三章の主动出牌(2)

    上一章我们已经搭好了出牌算法的基本框架,本章主要实现优先处理的三带.飞机等牌型. 首先定义一些基本变量: //暂存最佳的价值HandCardValue BestHandCardValue;BestHa ...

  5. Android版数据结构与算法汇总十二章

    Android版数据结构与算法(一):基础简介 https://www.cnblogs.com/leipDao/p/9140726.html Android版数据结构与算法(二):基于数组的实现Arr ...

  6. 斗地主AI算法——第十一章の被动出牌(5)

    本章是被动出牌的最后一章,截止目前,我们已经解决了大部分牌型.只剩下飞机和炸弹了. 飞机无疑是最复杂的类型,他等于顺子和三带的结合体,但又增加了很多难度. 根据上一章的算法,我们可以大概想到,若是带出 ...

  7. 斗地主AI算法——第六章の牌型判断

    本章实现了上一章提到的检查当前是否只是一手牌函数ins_SurCardsType /* 检查剩余的牌是否只是一手牌是: 返回手牌类型数据 不是:返回错误类型(cgERROR) */ CardGroup ...

  8. 斗地主AI算法——第四章の权值定义

    第一章业务逻辑结尾部分我提到了权值的计算方法: ①每个单牌都有一个基础价值②组合牌型的整体价值与这个基础价值有关,但显然计算规则不完全一样.③整手牌可以分成若干个组合牌,但分法不唯一. 当时,我说了① ...

  9. 斗地主AI算法——第一章の业务逻辑

    转眼间快到了五月,帝都的天气也变的非常梦幻. 时而酷暑炎热,时而狂风席卷. 而不管外面如何,我们也只能在办公室里茕茕无依的撸着代码,无可奈何的负着韶华. 世界是寂寞的,寂寞到不只是寂寞,而是死一般的寂 ...

最新文章

  1. topcoder srm 706 div1
  2. Java实现仿百度文库文档在线阅读
  3. 乘法运算-快速傅里叶变换
  4. Dell Caps Lock 切换大小写被窃取焦点问题解决办法
  5. 前后端配合实现密码找回功能思路
  6. 移动的宽带真的很垃圾
  7. TF目标检测API-Error: Argument must be a dense tensor: range(0, 3) - got shape [3], but wanted []....
  8. windows 搭建HTTP文件服务器(Nginx 方式)
  9. 联想电脑杜比音效--低音炮配置图
  10. 5个必看的Docker视频
  11. 谷粒商城笔记 + 完整代码 + 课件资料(基础篇)(学习记录)
  12. myeclipse linux 安装,安装MyEclipse
  13. 图之查找关键路径(python)实现
  14. 2014年个人工作愿景
  15. 米家接入HomeKit系列五:Sir控制米家设备
  16. Day215.课程详细页面功能完善、Echarts统计分析模块[生成统计数据+生成图表]前后端整合 -谷粒学院
  17. 人工智能、机器学习与深度学习的区别与联系
  18. 基于一道ctf 引发的 TP链分析
  19. 爬虫_urllib2库的使用
  20. 当年明月、袁腾飞、阎崇年三人的专业水平的比较以及由此想到的一些学习方法、品书原则

热门文章

  1. java的课后作业咋写_写的简单的java第三季的课后作业
  2. 我的世界最危险的服务器生存系列,《我的世界》极具危险的服务器
  3. 协同过滤算法_基于Mahout的协同过滤推荐算法
  4. 如何查阅资料?(找数据集,文献...)
  5. a标签的href传递信息
  6. 数据库加一列,cursor:pointer
  7. Win10快查、关闭开机自启动软件 - 教程篇
  8. 门户网站新闻资讯整站打包带全自动采集
  9. gulimall(谷粒商城) 是一个综合性的B2C平台,包括前台商城系统以及后台管理系统
  10. 百度SEO百度站长提交工具 v0.2