上一章已经排除了飞机、三带等牌型,那么除去炸弹王炸以外,我们只剩下单牌、对牌、三牌以及单顺、双顺、三顺了。

首先说单牌、对牌、三牌。其逻辑基本一样,只是出牌的个数有差别,即:如果该i牌数量满足这种牌型要求,即先打出,计算其剩余价值。

         //出单牌if (clsHandCardData.value_aHandCardList[i] > 0){clsHandCardData.value_aHandCardList[i]--;clsHandCardData.nHandCardCount--;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[i]++;clsHandCardData.nHandCardCount++;if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup= get_GroupData(cgSINGLE, i, 1);}}//出对牌if (clsHandCardData.value_aHandCardList[i] > 1){//尝试打出一对牌,估算剩余手牌价值clsHandCardData.value_aHandCardList[i] -= 2;clsHandCardData.nHandCardCount -= 2;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[i] += 2;clsHandCardData.nHandCardCount += 2;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgDOUBLE, i, 2);}}//出三牌if (clsHandCardData.value_aHandCardList[i] > 2){clsHandCardData.value_aHandCardList[i] -= 3;clsHandCardData.nHandCardCount -= 3;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[i] += 3;clsHandCardData.nHandCardCount += 3;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE, i, 3);}}

至于顺子的算法,和被动出牌的有一点点差别,就是因为没有了数量限制,所以需要遍历以i牌为起点可以组成的所有顺子。

//出单顺if (clsHandCardData.value_aHandCardList[i] > 0){int prov = 0;for (int j = i; j < 15; j++){if(clsHandCardData.value_aHandCardList[j]>0){prov++;}else{break;}if (prov >= 5){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] --;}clsHandCardData.nHandCardCount -= prov;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] ++;}clsHandCardData.nHandCardCount += prov;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgSINGLE_LINE, j, prov);}}}}//出双顺if (clsHandCardData.value_aHandCardList[i] > 1){int prov = 0;for (int j = i; j < 15; j++){if (clsHandCardData.value_aHandCardList[j]>1){prov++;}else{break;}if (prov >= 3){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -=2;}clsHandCardData.nHandCardCount -= prov*2;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] +=2;}clsHandCardData.nHandCardCount += prov*2;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgDOUBLE_LINE, j, prov*2);}}}}//出三顺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;}if (prov >= 2){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -= 3;}clsHandCardData.nHandCardCount -= prov * 3;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] += 3;}clsHandCardData.nHandCardCount += prov * 3;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_LINE, j, prov * 3);}}}}

因为本策略是必须解决掉至少一个i牌的,所以出牌操作放在循环内进行,也就是说,只要你不是炸3,若你手牌有3,在处理3时一定会return  就绝对不会再走到4。

if (BestCardGroup.cgType == cgERROR){}else if (BestCardGroup.cgType == cgSINGLE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgDOUBLE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgSINGLE_LINE){for (int j = BestCardGroup.nMaxCard- BestCardGroup.nCount+1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);}clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgDOUBLE_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount/2) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 3) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}clsHandCardData.uctPutCardType = BestCardGroup;}else 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;}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;}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;}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算法——第十五章の测试模块

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. nacos config基本使用
  2. 团队项目—后续阶段第一天
  3. 查找文本字母并且统计个数
  4. ActiveMQ结合Spring收发消息
  5. HDU - 4333 Revolving Digits(扩展KMP)
  6. 普通用户杜绝不请自来的邮件对策
  7. 嵌入式Linux之文件系统启动分析【原创】
  8. 编写一个Java程序,在程序中包含一个Employee类,Employee类包含name、age、salary三个成员变量
  9. 优酷用户触达平台技术大揭秘
  10. 在Visual C#中用ListView显示数据记录
  11. 趣学 C 语言(二)—— typedef 与 #define
  12. 修改本地文件存储路径
  13. Docker 方式 MySQL 主从搭建
  14. [转]哈希算法(Hash Algorithm)初探
  15. uni-app:搜索关键词并高亮显示,可重复显示
  16. Torch搭网络学习笔记(一)逻辑回归
  17. 中职计算机c语言课程,中职计算机C语言教学探讨
  18. 干掉广告和钓鱼,这款神器绝了!
  19. 【SIM卡】Sim 卡掉卡
  20. 大数据简介与大数据分析

热门文章

  1. 43 MM配置-采购-条件-定价过程-定义存取顺序
  2. Windows编译环境搭建(VS2010)
  3. docker 导出堆栈信息.hprof_JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用...
  4. OpenGL:画个水壶
  5. OpenVINO InferenceEngine之Core类
  6. pythont提示AttributeError: module ‘scipy.misc‘ has no attribute ‘imsave‘或‘imread‘
  7. webserver之定时器
  8. js 模拟点击_爬虫js逆向之无限debugger--抖音第三方数据分析平台的坑
  9. 代码管理_阿里巴巴自研代码管理平台技术解密
  10. Puma单栏博客Typecho主题