斗地主AI算法——第六章の牌型判断
本章实现了上一章提到的检查当前是否只是一手牌函数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算法——第六章の牌型判断相关推荐
- 斗地主AI算法——第四章の权值定义
第一章业务逻辑结尾部分我提到了权值的计算方法: ①每个单牌都有一个基础价值②组合牌型的整体价值与这个基础价值有关,但显然计算规则不完全一样.③整手牌可以分成若干个组合牌,但分法不唯一. 当时,我说了① ...
- 斗地主AI算法——第三章の数据处理
上一章我们定义了基本的数据结构,相信大家看到手牌类里面那么多出牌序列时一定会比较愤慨... 其实一开始写的时候我也是觉得很脑残,不过后续开发证明了这样的结构还是可以的,因为只要我封装了一层数据转换,接 ...
- 斗地主AI算法——第十三章の主动出牌(2)
上一章我们已经搭好了出牌算法的基本框架,本章主要实现优先处理的三带.飞机等牌型. 首先定义一些基本变量: //暂存最佳的价值HandCardValue BestHandCardValue;BestHa ...
- 斗地主AI算法——第十一章の被动出牌(5)
本章是被动出牌的最后一章,截止目前,我们已经解决了大部分牌型.只剩下飞机和炸弹了. 飞机无疑是最复杂的类型,他等于顺子和三带的结合体,但又增加了很多难度. 根据上一章的算法,我们可以大概想到,若是带出 ...
- 斗地主AI算法——第七章の被动出牌(1)
哎,之前扯了那么多蛋,终于讲出牌了! 本章开始讲被动出牌的逻辑算法.首先我们先把架子搭起来,被动出牌我们肯定是要知道场上目前打出的是什么牌型. 在第二章数据结构里我们定义过,游戏全局类里面有一个存放当 ...
- 斗地主AI算法——第十七章の总结整理
转载请标明出处:https://blog.csdn.net/sm9sun/article/details/70878001 文章出自:九日王朝 查看全文 http://www.taodudu.cc/ ...
- 斗地主AI算法——第十二章の主动出牌(1)
本章开始,我们介绍主动出牌的算法,和被动出牌类似,我们第一步把主要架子搭起来. 首先清空出牌序列 clsHandCardData.ClearPutCardList(); 主动出牌的策略按照优先级大体可 ...
- 斗地主AI算法——第十六章の样例分析
上一章,我们已经完成了测试模块的开发.至此我们已经可以进行整体测试了.本章主要内容就是对随机生成的对局情况进行简单的分析. 实际上整个开发过程绝大部分时间都是用在样例分析上,通过样例给出的返回操作分析 ...
- 斗地主AI算法——第十章の被动出牌(4)
上一章已经说明了单顺的实现方法,双顺.三不带顺牌型实现方法与单牌基本类似.改动的地方除了上一章说的枚举牌类型,出牌时value_nPutCardList的处理,回溯时value_aHandCardLi ...
最新文章
- render函数和redirect函数的区别+反向解析
- ios .framework动态库重签名
- linux 常用命令 (firewall,netstat)
- 领域驱动设计之PHP实现
- 文件下载--服务器端编程操作
- BeetleX实现MessagePack和Protobuf消息控制器调用websocket服务详解
- javabean与json转换(fastjson与jackson两个版本)
- java中使用几率_Java中使用蒙特卡洛算法计算德州扑克成牌概率(二)- 计算牌面分值...
- Java 借助ImageMagic实现图片编辑服务
- Redis数据类型SortedSET
- CocoStudio基础教程(6)使用CocoStudio编辑帧事件并关联到程序
- [iOS]Mac系统下安装windows共享打印机采坑记
- 文献笔记01 -- 综述 基于深度学习的入侵检测模型综述_张昊
- Android 查看应用MD5签名最简单的方法
- php是单进程语言,但是也有办法支持多进程
- 拔丝芋头的Java学习日记--Day4
- 解决AudioCont...HTMLMediaElement already connected previously to a different MediaElementSourceNode.问题
- 服务器cpu虚拟化已禁用怎样解禁,虚拟化已禁用,有办法吗
- 人民币大写转换小写数字金额 ts/es6
- 烟雨江湖小米鸿蒙,烟雨江湖小米时装怎么拿? 小米衣服获取方法详解[多图]
热门文章
- android 添加ga_android开发步步为营之70:android接入Google Analytics总结
- PyQT:This application failed to start because no Qt platform plugin could be initialized.
- python实现根据文件名找出(拷贝/剪切)同名文件的不同类型文件
- VGG19续读【精细】,为什么叫做VGG19?==>【每一层可以看做是很多个局部特征的提取器,可以用作局部特征提取】
- 4-2MapReduce的运行流程
- 上海c语言做游戏培训,0基础C语言游戏逆向课程,培训视频+项目实战
- CSS文字颜色渐变 - 案例篇
- phpcms文件夹plugin调用怎么写路径 - 代码篇
- IE浏览器 对 jquery版本的兼容性 支持
- YShout一款PHP+TXT+Ajax嵌入式在线聊天室源码