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

来源:互联网 发布:淘宝上小提琴教学视频 编辑:程序博客网 时间:2024/06/09 19:23

本章实现了上一章提到的检查当前是否只是一手牌函数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)

1 0
原创粉丝点击