麻将胡牌算法(C++版) 您所在的位置:网站首页 麻将牌几张胡牌最好 麻将胡牌算法(C++版)

麻将胡牌算法(C++版)

2024-06-09 13:18| 来源: 网络整理| 查看: 265

麻将胡牌算法 1、麻将的基本规则2、胡牌算法解析3、麻将的表示方法一副完整的麻将表示方法手牌表示方法 4、核心代码

1、麻将的基本规则

常见的麻将一共有三种花色,万、条、筒。每种花色的牌都有1~9个数值,每种数值的牌有4张,总共有493=108张牌。胡牌时手牌必须满足(不包含特殊牌型,如对对胡,大对子等)mABC+nDDD+EE(m >=0,n>=0),即一对将牌除开,剩余的牌全能组成顺子(ABC)或者刻子(DDD)。

2、胡牌算法解析

注:以下分析不包含特殊牌型,如对对胡,大对子等。 现有以下已胡手牌,14张: 胡牌牌型 六条做将牌,剩余的牌:一条 二条 三条 + 七条 八条 九条 + 三筒 三筒 三筒 + 四筒 五筒 六筒; 剔除将牌(既一对EE),剩余的牌都是顺子加刻子的组合,并且每种花色的牌也是顺子加刻子的组合。所以剔除将牌后,只要分析每种花色牌是否都满足mABC+nDDD即可。不管是顺子还是刻子,都是3张牌一组为最小单位,所以从有序手牌牌堆每次依次取三张牌分析是否满足ABC或DDD。

3、麻将的表示方法 一副完整的麻将表示方法

一张麻将由花色+数值确定,如一万,花色是万,数值1;所以可以用两位16进制数表示一张麻将。高位表示花色,低位表示数值大小。所以一副完整的扑克用数组表示如下:

//扑克数据 const BYTE m_cbCardDataArray[108]= { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, //万子 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, //万子 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, //万子 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, //万子 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, //条子 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, //条子 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, //条子 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, //条子 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, //同子 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, //同子 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, //同子 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, //同子 }; 手牌表示方法

一副手牌正常情况下一共14张,一种是用一个数组HandCard[14]表示;如果我们用一个HandCard[14]的数组表示手牌,再实际摸牌出牌过程中就会进行频繁的增删操作,不仅浪费时间还麻烦;所以我们对手牌进行一次转换,定义一个数组m_cbCardIndex[27(3*9)],用来存储每种牌的张数,例如:手牌一万的牌有2张,则 m_cbCardIndex[0] = 2,以此类推;

//扑克数据,***每种麻将对应的下标*** const BYTE m_cbCardIndex[27]= { /*0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, //万子 下标0-8 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, //条子 下标9-17 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29*/ //同子 下标18-27 };

每种牌与下标对应的关系:例,二条Card=0x12,花色值Color=(Card&0xF0)>>4=1,数值Val=(Card&0xF0)=2;二条对应的下标Index =Color9 +Val -1=19+2-1=10 : 得出手牌HandCard[14]与m_cbCardIndex[27]扑克转换函数:

#define MASK_COLOR 0xF0 //花色掩码 #define MASK_VALUE 0x0F //数值掩码 //扑克转换函数: BYTE SwitchToCardIndex(BYTE cbCardData) { return ((cbCardData&MASK_COLOR)>>4)*9+(cbCardData&MASK_VALUE)-1; } 4、核心代码 //平胡 bool AnalyseHuCard(BYTE cbCardIndex[27]) { /* 基本思路: 分单花色判断是否时候满足n*ABC+z*EEE+DD 如果全满足并且只有一对将牌及为胡牌 */ ASSERT(cbCardIndex != nullptr); BYTE cbCardNum[3] = { 0,0 ,0}; BYTE cbAllCardNum = 0; BYTE cbCardIndexTemp1[27]; ZeroMemory(&cbCardIndexTemp1,sizeof(cbCardIndexTemp1)); CopyMemory(cbCardIndexTemp1, cbCardIndex, sizeof(cbCardIndexTemp1)); BYTE cbJiangPai = 0; //记录将牌数 //获取每种牌的数量,万 条 同 for (int i = 0;i if (cbCardNum[i] == 0) continue; //无此种花色手牌 //判断有无将牌 //牌数量3n+2,有将牌 if ((cbCardNum[i] >= 2) &&(cbCardNum[i] - 2) % 3 == 0) { for (int g = 0; g cbJiangPai++;break; //记录所有花色中可以做将牌数量 } } } //牌数量3n,无将牌 else if (cbCardNum[i] % 3 == 0) { if (!AnalysePerutCardByColor(&cbCardIndexTemp1[i * 9])) return false; } //牌数量不满足3n+2或3n一定不能胡牌 else { return false; } } //说明所有将牌组合动不能满足n*ABC+z*EEE,或者花色(万条同)能做将牌的不止一对 if (cbJiangPai != 1) return false; return true; } //扑克数目 BYTE GetCardCount(const BYTE cbCardIndex[9]) { //数目统计 BYTE cbCardCount=0; for (BYTE i=0;i //对应牌数量为零跳过 if (cbCardIndexTemp[j] == 0) { j++; continue; } /*if (j > 6 && cbCardIndexTemp[j] != 3) return false;*/ //从第一个牌数量不为0开始判断 else if (cbCardIndexTemp[j] >= 4) { //如果之后相连的两张牌数量大于0则可组成ABC形式 if (cbCardIndexTemp[j + 1] >0 && cbCardIndexTemp[j + 2] > 0) { //从牌堆中减去满足要求的牌 cbCardIndexTemp[j] -= 4; cbCardIndexTemp[j + 1] -= 1; cbCardIndexTemp[j + 2] -= 1; j++; } else { return false; } } //如果第一个牌数量>=3,只能以AAA形式存在 else if (cbCardIndexTemp[j] == 3) { //从牌堆中减去满足要求的牌 cbCardIndexTemp[j] -= 3; j++; } //如果第一个牌数量 //从牌堆中减去满足要求的牌 cbCardIndexTemp[j] -= 2; cbCardIndexTemp[j + 1] -= 2; cbCardIndexTemp[j + 2] -= 2; j++; } else { return false; } } else if (cbCardIndexTemp[j] == 1) { //如果之后相连的两张牌数量大于0则可组成ABC形式 if (j > 6) return false; if (cbCardIndexTemp[j + 1] >= 1 && cbCardIndexTemp[j + 2] >= 1) { //从牌堆中减去满足要求的牌 cbCardIndexTemp[j] -= 1; cbCardIndexTemp[j + 1] -= 1; cbCardIndexTemp[j + 2] -= 1; j++; } else { return false; } } } return true; } //分析将牌 bool AnalyseJiangCardByColor(BYTE cbCardIndexTemp[9], BYTE cbSubscript) { //判断是否可为将牌 if (cbCardIndexTemp[cbSubscript] >= 2) { //减去将牌 cbCardIndexTemp[cbSubscript] -= 2; return true; } return false; }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有