上一章我们已经搭好了出牌算法的基本框架,本章主要实现优先处理的三带、飞机等牌型。

首先定义一些基本变量:

 //暂存最佳的价值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;

因为枚举了牌型,所以实际和被动出牌逻辑都差不多,且没有nMaxCard的限制,所以我们要从3开始遍历。且上一章我们提到,不考虑炸弹拆分的情况。故value_aHandCardList[i]不能等于4。

for (int i = 3; i < 16; i++){//2.0版本策略主动出牌不拆分炸弹,朕自己从来就不打四带二,因为浪if (clsHandCardData.value_aHandCardList[i] != 4){//出三带一if (clsHandCardData.value_aHandCardList[i] > 2){clsHandCardData.value_aHandCardList[i] -= 3;for (int j = 3; j < 18; j++){if (clsHandCardData.value_aHandCardList[j] > 0 ){clsHandCardData.value_aHandCardList[j] -= 1;clsHandCardData.nHandCardCount -= 4;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[j] += 1;clsHandCardData.nHandCardCount += 4;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE, i, 4);tmp_1 = j;}}}clsHandCardData.value_aHandCardList[i] += 3;}//出三带二if (clsHandCardData.value_aHandCardList[i] > 2){for (int j = 3; j < 16; j++){clsHandCardData.value_aHandCardList[i] -= 3;if (clsHandCardData.value_aHandCardList[j] > 1){clsHandCardData.value_aHandCardList[j] -= 2;clsHandCardData.nHandCardCount -= 5;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[j] += 2;clsHandCardData.nHandCardCount += 5;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_TAKE_TWO, i, 5);tmp_1 = j;}}clsHandCardData.value_aHandCardList[i] += 3;}}//出四带二单if (clsHandCardData.value_aHandCardList[i] > 3){//2.0版本策略主动出牌不拆分炸弹,朕自己从来就不打四带二,因为浪}//出四带二对if (clsHandCardData.value_aHandCardList[i] > 3){//2.0版本策略主动出牌不拆分炸弹,朕自己从来就不打四带二,因为浪}//出三带一单连if (clsHandCardData.value_aHandCardList[i] > 2){int prov = 0;for (int j = i; j < 15; j++){if (clsHandCardData.value_aHandCardList[j] > 2){prov++;}else{break;}/*本来想做全排列选取带出的牌然后枚举出最高价值的,但考虑到当飞机长度也就是在2-4之间所以干脆做三个分支处理算了*///为两连飞机if (prov == 2){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -= 3;}clsHandCardData.nHandCardCount -= prov * 4;for (int tmp1 = 3; tmp1 < 18; tmp1++){if (clsHandCardData.value_aHandCardList[tmp1] > 0 ){clsHandCardData.value_aHandCardList[tmp1] -= 1;for (int tmp2 = tmp1; tmp2 < 18; tmp2++){if (clsHandCardData.value_aHandCardList[tmp2] > 0 ){clsHandCardData.value_aHandCardList[tmp2] -= 1;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE_LINE, j, prov * 4);tmp_1 = tmp1;tmp_2 = tmp2;}clsHandCardData.value_aHandCardList[tmp2] += 1;}}clsHandCardData.value_aHandCardList[tmp1] += 1;}}for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] += 3;}clsHandCardData.nHandCardCount += prov * 4;}//为三连飞机if (prov == 3){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -= 3;}clsHandCardData.nHandCardCount -= prov * 4;for (int tmp1 = 3; tmp1 < 18; tmp1++){if (clsHandCardData.value_aHandCardList[tmp1] > 0 ){clsHandCardData.value_aHandCardList[tmp1] -= 1;for (int tmp2 = tmp1; tmp2 < 18; tmp2++){if (clsHandCardData.value_aHandCardList[tmp2] > 0 ){clsHandCardData.value_aHandCardList[tmp2] -= 1;for (int tmp3 = tmp2; tmp3 < 18; tmp3++){if (clsHandCardData.value_aHandCardList[tmp3] > 0 ){clsHandCardData.value_aHandCardList[tmp3] -= 1;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE_LINE, j, prov * 4);tmp_1 = tmp1;tmp_2 = tmp2;tmp_3 = tmp3;}clsHandCardData.value_aHandCardList[tmp3] += 1;}}clsHandCardData.value_aHandCardList[tmp2] += 1;}}clsHandCardData.value_aHandCardList[tmp1] += 1;}}for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] += 3;}clsHandCardData.nHandCardCount += prov * 4;}//为四连飞机if (prov == 4){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -= 3;}clsHandCardData.nHandCardCount -= prov * 4;for (int tmp1 = 3; tmp1 < 18; tmp1++){if (clsHandCardData.value_aHandCardList[tmp1] > 0 ){clsHandCardData.value_aHandCardList[tmp1] -= 1;for (int tmp2 = tmp1; tmp2 < 18; tmp2++){if (clsHandCardData.value_aHandCardList[tmp2] > 0 ){clsHandCardData.value_aHandCardList[tmp2] -= 1;for (int tmp3 = tmp2; tmp3 < 18; tmp3++){if (clsHandCardData.value_aHandCardList[tmp3] > 0 ){clsHandCardData.value_aHandCardList[tmp3] -= 1;for (int tmp4 = tmp3; tmp4 < 18; tmp4++){if (clsHandCardData.value_aHandCardList[tmp4] > 0 ){clsHandCardData.value_aHandCardList[tmp4] -= 1;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE_LINE, j, prov * 4);tmp_1 = tmp1;tmp_2 = tmp2;tmp_3 = tmp3;tmp_4 = tmp4;}clsHandCardData.value_aHandCardList[tmp4] += 1;}}clsHandCardData.value_aHandCardList[tmp3] += 1;}}clsHandCardData.value_aHandCardList[tmp2] += 1;}}clsHandCardData.value_aHandCardList[tmp1] += 1;}}for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] += 3;}clsHandCardData.nHandCardCount += prov * 4;}//若prov==5,则是地主可以直接出去,在剪枝部分已经处理}}//出三带一双连if (clsHandCardData.value_aHandCardList[i] > 2){int prov = 0;for (int j = i; j < 15; j++){if (clsHandCardData.value_aHandCardList[j] > 2 ){prov++;}else{break;}/*本来想做全排列选取带出的牌然后枚举出最高价值的,但考虑到当飞机长度也就是在2-4之间所以干脆做三个分支处理算了*///为两连飞机if (prov == 2){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -= 3;}clsHandCardData.nHandCardCount -= prov * 5;for (int tmp1 = 3; tmp1 < 16; tmp1++){if (clsHandCardData.value_aHandCardList[tmp1] > 1 ){clsHandCardData.value_aHandCardList[tmp1] -= 2;for (int tmp2 = tmp1; tmp2 < 16; tmp2++){if (clsHandCardData.value_aHandCardList[tmp2] > 1 ){clsHandCardData.value_aHandCardList[tmp2] -= 2;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_TAKE_TWO_LINE, j, prov * 5);tmp_1 = tmp1;tmp_2 = tmp2;}clsHandCardData.value_aHandCardList[tmp2] += 2;}}clsHandCardData.value_aHandCardList[tmp1] += 2;}}for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] += 3;}clsHandCardData.nHandCardCount += prov * 5;}//为三连飞机if (prov == 3){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -= 3;}clsHandCardData.nHandCardCount -= prov * 5;for (int tmp1 = 3; tmp1 < 16; tmp1++){if (clsHandCardData.value_aHandCardList[tmp1] > 1 ){clsHandCardData.value_aHandCardList[tmp1] -= 2;for (int tmp2 = tmp1; tmp2 < 16; tmp2++){if (clsHandCardData.value_aHandCardList[tmp2] > 1 ){clsHandCardData.value_aHandCardList[tmp2] -= 2;for (int tmp3 = tmp2; tmp3 < 16; tmp3++){if (clsHandCardData.value_aHandCardList[tmp3] > 1 ){clsHandCardData.value_aHandCardList[tmp3] -= 2;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_TAKE_TWO_LINE, j, prov * 5);tmp_1 = tmp1;tmp_2 = tmp2;tmp_3 = tmp3;}clsHandCardData.value_aHandCardList[tmp3] += 2;}}clsHandCardData.value_aHandCardList[tmp2] += 2;}}clsHandCardData.value_aHandCardList[tmp1] += 2;}}for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] += 3;}clsHandCardData.nHandCardCount += prov * 5;}//若prov==4,则是地主可以直接出去,在剪枝部分已经处理}}}}

这个循环结束后,若有好的选择,则BestCardGroup会保留出牌的类型,在循环外进行出牌处理。

if (BestCardGroup.cgType == cgTHREE_TAKE_ONE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.uctPutCardType = BestCardGroup;return;}else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.uctPutCardType = BestCardGroup;return;}else if (BestCardGroup.cgType == cgTHREE_TAKE_ONE_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 4) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}if (BestCardGroup.nCount / 4 == 2){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);}if (BestCardGroup.nCount / 4 == 3){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_3);}if (BestCardGroup.nCount / 4 == 4){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_3);clsHandCardData.value_nPutCardList.push_back(tmp_4);}clsHandCardData.uctPutCardType = BestCardGroup;return;}else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 5) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}if (BestCardGroup.nCount / 5 == 2){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_2);}if (BestCardGroup.nCount / 5 == 3){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_3);clsHandCardData.value_nPutCardList.push_back(tmp_3);}clsHandCardData.uctPutCardType = BestCardGroup;return;}

因为回溯遍历部分与被动出牌完全一样,这里就不再赘述。飞机在出牌阶段的处理比较麻烦,要根据牌数进行判断是几连飞机。

下一章,我们将实现打出当前最小值牌部分。

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

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

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

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

  2. 斗地主AI算法——第七章の被动出牌(1)

    哎,之前扯了那么多蛋,终于讲出牌了! 本章开始讲被动出牌的逻辑算法.首先我们先把架子搭起来,被动出牌我们肯定是要知道场上目前打出的是什么牌型. 在第二章数据结构里我们定义过,游戏全局类里面有一个存放当 ...

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

    本章开始,我们介绍主动出牌的算法,和被动出牌类似,我们第一步把主要架子搭起来. 首先清空出牌序列 clsHandCardData.ClearPutCardList(); 主动出牌的策略按照优先级大体可 ...

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

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

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

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

  6. 斗地主AI算法——第三章の数据处理

    上一章我们定义了基本的数据结构,相信大家看到手牌类里面那么多出牌序列时一定会比较愤慨... 其实一开始写的时候我也是觉得很脑残,不过后续开发证明了这样的结构还是可以的,因为只要我封装了一层数据转换,接 ...

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

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

  8. 斗地主AI算法——第十七章の总结整理

    转载请标明出处:https://blog.csdn.net/sm9sun/article/details/70878001  文章出自:九日王朝 查看全文 http://www.taodudu.cc/ ...

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

    上一章已经说明了单顺的实现方法,双顺.三不带顺牌型实现方法与单牌基本类似.改动的地方除了上一章说的枚举牌类型,出牌时value_nPutCardList的处理,回溯时value_aHandCardLi ...

最新文章

  1. 条件语句,while循环语句:完整的温度转换程序
  2. 开源API网关Kong基本介绍和安装验证
  3. cpucores_CPUCores怎么用 CPUCores使用方法指南_3DM单机
  4. mysql执行过程五步_简单五步教你搭建MySQL主从复制
  5. Python--网络编程
  6. centos 安装mysql5.6.20_Linux学习15-CentOS安装mysql5.6环境
  7. 双击计算机桌面误删,手提电脑双击界面自动删除是哪里问题
  8. version for mac 破那啥版
  9. kepware mysql_Kepware EX6与MySQL数据库通讯(上篇)
  10. Kafka权威指南,Kafka消费者
  11. java 高效的 httpclient_使用httpclient下载zip的有效方法
  12. 微软官方的SQLHelper类(含完整中文注释)
  13. Qt中通过Qpixmap设置图片透明度
  14. Hibernate基础知识整理(三)
  15. 2022BUAA数据结构期末大作业的一些想法
  16. 使用MACD指标在上证指数000001.SH上开发单边多头策略
  17. Gather-Excite:Exploiting Feature Context in Convolutional Neural Networks
  18. Mycat安装与配置详解
  19. 关于Mac共享WiFi网络,看这里就够了(2 4G,5G , ipv6)
  20. 在电脑上显示未知发布者怎么办_Win7无法验证发行者、未知发布者的解决方法...

热门文章

  1. InceptionNet V2整理总结
  2. 如何保证消息队列的高可用
  3. 2021.08.24学习内容torch.utils.data.DataLoader以及CUDA与GPU的关系
  4. Docker 镜像使用(拉取、查看、使用、删除)
  5. IDEA自动勾选显示类型(specify type)
  6. 常见HTTP状态(404,500等)
  7. 判断域名来源的操作【window.location.host.indexOf(‘域名关键词‘)】 - 代码篇
  8. android 推送的小图标,android - 推送通知中没有声音并且没有自定义的小图标 - 堆栈内存溢出...
  9. listary什么意思_listary使用心得
  10. 电脑格式化后需要重装系统吗_重装系统后c盘文件丢失,电脑重装系统后c盘文件能恢复吗...