本章实现了上一章提到的检查当前是否只是一手牌函数ins_SurCardsType

/*
检查剩余的牌是否只是一手牌是:  返回手牌类型数据
不是:返回错误类型(cgERROR)
*/
CardGroupData ins_SurCardsType(int arr[]);

输入很简单,就是一个状态数组。输出是手牌类型结构

//牌型组合数据结构
struct CardGroupData
{//枚举类型CardGroupType cgType=cgERROR;//该牌的价值int  nValue=0;//含牌的个数int  nCount=0;//牌中决定大小的牌值,用于对比int nMaxCard=0;};

其中  cgType通过枚举获取,nValue计算规则参考第四章权值定义,nCount可以通过引入数组算出,nMaxCard是用于比大小的那个牌值。

首先我们要计算出剩余手牌个数,因为这样便于快速筛选分支。

 int nCount = 0;for (int i = 3; i < 18; i++){nCount += arr[i];}CardGroupData retCardGroupData;retCardGroupData.nCount = nCount;

以单牌为例,若该牌型满足单牌,则nCount==1,然后我们再找出那张牌。

 //单牌类型if (nCount == 1){//用于验证的变量int prov = 0;int SumValue = 0;for (int i = 3; i < 18; i++){if (arr[i] == 1){SumValue = i - 10;prov++;retCardGroupData.nMaxCard = i;}}if (prov == 1){retCardGroupData.cgType = cgSINGLE;retCardGroupData.nValue= SumValue;return retCardGroupData;}}

对牌,三牌,炸弹同理。

三带一的话需要设置两个验证变量,例如三带一单

if (nCount == 4){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;for (int i = 3; i < 18; i++){if (arr[i] == 3){SumValue = i - 10;prov1++;retCardGroupData.nMaxCard = i;}if (arr[i] == 1){prov2++;}}if (prov1 == 1 && prov2 == 1){retCardGroupData.cgType = cgTHREE_TAKE_ONE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}

三带一对

 if (nCount == 5){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;for (int i = 3; i < 16; i++){if (arr[i] == 3){SumValue = i - 10;prov1++;retCardGroupData.nMaxCard = i;}if (arr[i] == 2){prov2++;}}

这里我们看,循环改为3~15,因为三牌、对牌是不包括王的。

四带二同理,不过四带二要考虑到带出去的那两张牌型是不是相同

 if (nCount == 6){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;for (int i = 3; i < 18; i++){if (arr[i] == 4){SumValue = (i - 3) / 2;prov1++;retCardGroupData.nMaxCard = i;}if (arr[i] == 1|| arr[i] == 2){prov2+= arr[i];}}if (prov1 == 1 && prov2 == 2){retCardGroupData.cgType = cgFOUR_TAKE_ONE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}

判断顺子的话用一个变量记录长度,若当前i值等于0并且之前存在i大于0的情况下,即这个长度就是顺子的长度

例如单连:

 if (nCount >= 5){//用于验证的变量int prov = 0;int SumValue = 0;int i;for (i = 3; i < 15; i++){if (arr[i] == 1){prov++;}else{if (prov != 0){break;}}}SumValue = i - 10;if (prov == nCount){retCardGroupData.nMaxCard = i-1;retCardGroupData.cgType = cgSINGLE_LINE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}

王炸就更好判断了,直接判断arr[17]和arr[16]就好了

下面贴出完整代码:

/*
检查剩余的牌是否只是一手牌是:  返回手牌类型数据
不是:返回错误类型(cgERROR)
*/
CardGroupData ins_SurCardsType(int arr[])
{int nCount = 0;for (int i = 3; i < 18; i++){nCount += arr[i];}CardGroupData retCardGroupData;retCardGroupData.nCount = nCount;//单牌类型if (nCount == 1){//用于验证的变量int prov = 0;int SumValue = 0;for (int i = 3; i < 18; i++){if (arr[i] == 1){SumValue = i - 10;prov++;retCardGroupData.nMaxCard = i;}}if (prov == 1){retCardGroupData.cgType = cgSINGLE;retCardGroupData.nValue= SumValue;return retCardGroupData;}}//对牌类型if (nCount == 2){//用于验证的变量int prov = 0;int SumValue = 0;int i = 0;for (i = 3; i < 16; i++){if (arr[i] == 2){SumValue = i - 10;prov++;retCardGroupData.nMaxCard = i;}}if (prov == 1){retCardGroupData.cgType = cgDOUBLE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//三条类型if (nCount == 3){//用于验证的变量int prov = 0;int SumValue = 0;int i = 0;for (i = 3; i < 16; i++){if (arr[i] == 3){SumValue = i - 10;prov++;retCardGroupData.nMaxCard = i;}}if (prov == 1){retCardGroupData.cgType = cgTHREE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//三带一单if (nCount == 4){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;for (int i = 3; i < 18; i++){if (arr[i] == 3){SumValue = i - 10;prov1++;retCardGroupData.nMaxCard = i;}if (arr[i] == 1){prov2++;}}if (prov1 == 1 && prov2 == 1){retCardGroupData.cgType = cgTHREE_TAKE_ONE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//三带一对if (nCount == 5){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;for (int i = 3; i < 16; i++){if (arr[i] == 3){SumValue = i - 10;prov1++;retCardGroupData.nMaxCard = i;}if (arr[i] == 2){prov2++;}}if (prov1 == 1 && prov2 == 1){retCardGroupData.cgType = cgTHREE_TAKE_TWO;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//四带两单if (nCount == 6){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;for (int i = 3; i < 18; i++){if (arr[i] == 4){SumValue = (i - 3) / 2;prov1++;retCardGroupData.nMaxCard = i;}if (arr[i] == 1|| arr[i] == 2){prov2+= arr[i];}}if (prov1 == 1 && prov2 == 2){retCardGroupData.cgType = cgFOUR_TAKE_ONE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//四带两对if (nCount == 8){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;for (int i = 3; i < 16; i++){if (arr[i] == 4){SumValue = (i - 3) / 2;prov1++;retCardGroupData.nMaxCard = i;}if (arr[i] == 2|| arr[i] == 4){prov2+= arr[i]/2;}}//注意这里prov2==4因为四牌也是两个对if (prov1 == 1 && prov2 == 4){retCardGroupData.cgType = cgFOUR_TAKE_TWO;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//炸弹类型if (nCount == 4){//用于验证的变量int prov = 0;int SumValue = 0;for (int i = 3; i < 16; i++){if (arr[i] == 4){SumValue += i - 3 + 7;prov++;retCardGroupData.nMaxCard = i;}}if (prov == 1){retCardGroupData.cgType = cgBOMB_CARD;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//王炸类型if (nCount == 2){int SumValue = 0;if (arr[17] > 0 && arr[16] > 0){SumValue = 20;retCardGroupData.nMaxCard = 17;retCardGroupData.cgType = cgKING_CARD;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//单连类型if (nCount >= 5){//用于验证的变量int prov = 0;int SumValue = 0;int i;for (i = 3; i < 15; i++){if (arr[i] == 1){prov++;}else{if (prov != 0){break;}}}SumValue = i - 10;if (prov == nCount){retCardGroupData.nMaxCard = i-1;retCardGroupData.cgType = cgSINGLE_LINE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//对连类型if (nCount >= 6){//用于验证的变量int prov = 0;int SumValue = 0;int i;for (i = 3; i < 15; i++){if (arr[i] == 2){prov++;}else{if (prov != 0){break;}}}SumValue = i - 10;if (prov * 2 == nCount){retCardGroupData.nMaxCard = i - 1;retCardGroupData.cgType = cgDOUBLE_LINE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//三连类型if (nCount >= 6){//用于验证的变量int prov = 0;int SumValue = 0;int i;for (i = 3; i < 15; i++){if (arr[i] == 3){prov++;}else{if (prov != 0){break;}}}SumValue = (i - 3) / 2;if (prov * 3 == nCount){retCardGroupData.nMaxCard = i - 1;retCardGroupData.cgType = cgTHREE_LINE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//三带一连类型if (nCount >= 8){//用于验证的变量int prov1 = 0;int SumValue = 0;int i, j;for (i = 3; i < 15; i++){if (arr[i] >= 3){prov1++;}else{if (prov1 != 0){break;}}}SumValue = (i - 3)/2;if (prov1 * 4 == nCount){retCardGroupData.nMaxCard = i - 1;retCardGroupData.cgType = cgTHREE_TAKE_ONE_LINE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}//三带二连类型if (nCount >= 10){//用于验证的变量int prov1 = 0;int prov2 = 0;int SumValue = 0;int i, j;for (i = 3; i < 15; i++){if (arr[i] == 3){prov1++;}else{if (prov1 != 0){break;}}}for (j = 3; j < 16; j++){if (arr[j] == 2|| arr[j] == 4){prov2+= arr[j]/2;}}SumValue = (i - 3) / 2;if (prov1 == prov2&&prov1 * 5 == nCount){retCardGroupData.nMaxCard = i - 1;retCardGroupData.cgType = cgTHREE_TAKE_TWO_LINE;retCardGroupData.nValue = SumValue;return retCardGroupData;}}retCardGroupData.cgType = cgERROR;return retCardGroupData;
}/*
检查剩余的牌是否只是一手牌(vector重载)是:  返回手牌类型数据
不是:返回错误类型(cgERROR)
*/
CardGroupData ins_SurCardsType(vector<int>list)
{int arr[18];memset(arr, 0, sizeof(arr));for (vector<int>::iterator iter = list.begin(); iter != list.end(); iter++){arr[*iter]++;}return ins_SurCardsType(arr);
}

怎么样,这么多牌型枚举是不是很头疼?放心吧,接下来的主动出牌算法、被动出牌算法的枚举会更头疼!

所以~从下一章开始我们就要讲出牌的策略了,首先是被动出牌。

敬请关注下一章:斗地主AI算法——第七章の被动出牌(1)

斗地主AI算法——第六章の牌型判断相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. render函数和redirect函数的区别+反向解析
  2. ios .framework动态库重签名
  3. linux 常用命令 (firewall,netstat)
  4. 领域驱动设计之PHP实现
  5. 文件下载--服务器端编程操作
  6. BeetleX实现MessagePack和Protobuf消息控制器调用websocket服务详解
  7. javabean与json转换(fastjson与jackson两个版本)
  8. java中使用几率_Java中使用蒙特卡洛算法计算德州扑克成牌概率(二)- 计算牌面分值...
  9. Java 借助ImageMagic实现图片编辑服务
  10. Redis数据类型SortedSET
  11. CocoStudio基础教程(6)使用CocoStudio编辑帧事件并关联到程序
  12. [iOS]Mac系统下安装windows共享打印机采坑记
  13. 文献笔记01 -- 综述 基于深度学习的入侵检测模型综述_张昊
  14. Android 查看应用MD5签名最简单的方法
  15. php是单进程语言,但是也有办法支持多进程
  16. 拔丝芋头的Java学习日记--Day4
  17. 解决AudioCont...HTMLMediaElement already connected previously to a different MediaElementSourceNode.问题
  18. 服务器cpu虚拟化已禁用怎样解禁,虚拟化已禁用,有办法吗
  19. 人民币大写转换小写数字金额 ts/es6
  20. 烟雨江湖小米鸿蒙,烟雨江湖小米时装怎么拿? 小米衣服获取方法详解[多图]

热门文章

  1. android 添加ga_android开发步步为营之70:android接入Google Analytics总结
  2. PyQT:This application failed to start because no Qt platform plugin could be initialized.
  3. python实现根据文件名找出(拷贝/剪切)同名文件的不同类型文件
  4. VGG19续读【精细】,为什么叫做VGG19?==>【每一层可以看做是很多个局部特征的提取器,可以用作局部特征提取】
  5. 4-2MapReduce的运行流程
  6. 上海c语言做游戏培训,0基础C语言游戏逆向课程,培训视频+项目实战
  7. CSS文字颜色渐变 - 案例篇
  8. phpcms文件夹plugin调用怎么写路径 - 代码篇
  9. IE浏览器 对 jquery版本的兼容性 支持
  10. YShout一款PHP+TXT+Ajax嵌入式在线聊天室源码