本章实现了上一章提到的检查当前是否只是一手牌函数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)
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦