用数字代替麻将中的所有牌:

一万~九万    1~9

一筒~九筒    11~19

一条~九条    21~29

东、南、西、北、中、发、白    31~37

胡牌的种类:对对胡、十三幺和33332

判断胡牌的过程(以下所说的规则,都是针对手牌已经按从小到大的顺序排序):

1、首先判断手牌的总数是否为3n+2,如果不是肯定不是胡牌。

2、先从特殊的下手,如果手牌为14张的时候,就有可能是“对对胡”或者“十三幺”,先判断是否为这两种特殊胡牌,如果不是,再继续下面的判断。
排除特殊情况,那么要胡,就只能是“33332”。

3、遍历所有的手牌,找到一种牌的数量>=2的,那么“33332”中的“2”就有可能从这种牌中抽取2张作为这个“2”,然后把这2张去掉,剩下的手牌就是3n张,再判断剩下的3n张牌是否能组成顺子或者是暗刻,如果可以全部组成,那么说明这牌就胡了。否则需要找下一种牌当成“2”,再重复上面的判断,直到找到为止,找不到就是不胡啦。

判断剩下的3n张牌是否能组成顺子或者是暗刻,是通过判断第一种牌的数量:

①如果是1张或2张,要胡牌的话,它必须和后面的牌组成顺子,否自不能胡。如果可以,将组成顺子的牌移除,接着处理剩下的牌。

②如果是3张,要胡牌有两种可能,一种是把3张当做是暗刻,另一种是这3张都与后面的牌组成顺子。如果只是判断胡不胡牌,这两种任意一种都是一样的,如果要计算分数,就要自己分开算了。

③如果是4张,要胡牌的话,有1张要和后面的牌组成顺子,剩下的3张牌又可以继续②操作。

整个过程可以通过函数的递归调用,每次处理一张,如果不能凑成顺子或者暗刻就不能胡,直接返回错误,如果可以则继续判断,直到牌数为0,则就是胡了,返回成功即可。

下面是我用OC写的胡牌算法,初步验证可以,可能有漏洞,以后遇到再修改,如果你们发现问题,也可以留言,我再修复更新。

// 检查手牌是否符合胡牌规则 - (BOOL)checkHuWithHandCards:(NSArray *)handCards { //
只有手牌是14张,才有可能是“对对胡”或者“十三幺” if (handCards.count == 14) { // 对对胡 BOOL isDuiDuiHu
= true; NSMutableArray *ArrM1 = [NSMutableArray arrayWithArray:handCards];
while (ArrM1.count && isDuiDuiHu) { if (ArrM1[0] == ArrM1[1]) { [ArrM1
removeObjectAtIndex:0]; [ArrM1 removeObjectAtIndex:0]; } else { isDuiDuiHu =
false; break; } } if (isDuiDuiHu) { return true; } // 十三幺 BOOL isShiSanYao =
false; NSArray *shiSanYaoArr = @[@1, @9, @11, @19, @21, @29, @31, @32, @33,
@34, @35, @36, @37]; NSMutableArray *arrM2 = [NSMutableArray
arrayWithArray:handCards]; for (int j = 0; j < handCards.count - 1; ++j) { if
(handCards[j] == handCards[j + 1]) { [arrM2 removeObjectAtIndex:j]; break; } }
for (int i = 0; i < shiSanYaoArr.count; ++i) { isShiSanYao = false; if
([arrM2[i] intValue] == [shiSanYaoArr[i] intValue]) { isShiSanYao = true; }
else { break; } } if (isShiSanYao) { return true; } } // 其他胡牌(3、3、3、3、2) return
[self checkHu33332WithCards:[self changeHandCards:handCards]]; } //
其他胡牌(3、3、3、3、2) - (BOOL)checkHu33332WithCards:(NSArray *)cards { for (int i =
0; i < cards.count; ++i) { if ([cards[i][1] intValue] >= 2) { NSMutableArray
*arrM = [NSMutableArray arrayWithArray:cards]; // 先把一对牌找出来,排除掉之后继续下面的判断 if
([cards[i][1] intValue] == 2) { [arrM removeObjectAtIndex:i]; } else { [arrM
replaceObjectAtIndex:i withObject:@[cards[i][0], [NSNumber
numberWithInt:[cards[i][1] intValue] - 2]]]; } if ((arrM.count && [self
checkForCards:arrM]) || !arrM.count) return true; } } return false; } //
按照第一张牌的数量,分类检查 - (BOOL)checkForCards:(NSArray *)cards { switch ([cards[0][1]
intValue]) { case 1: case 2: if (![self checkFirstCard1Or2:cards]) return
false; break; case 3: if (![self checkFirstCard3:cards]) return false; break;
case 4: if (![self checkFirstCard4:cards]) return false; break; default: break;
} return true; } // 第一张牌的数量是1或2 - (BOOL)checkFirstCard1Or2:(NSArray *)cards {
// 只能与后面的牌组成顺子,不然就胡不了了 if (cards.count >= 3 && [cards[0][0] intValue] ==
[cards[1][0] intValue] - 1 && [cards[0][0] intValue] == [cards[2][0] intValue]
- 2) { NSMutableArray *arrM = [NSMutableArray arrayWithArray:cards]; for (int i
= 2; i >= 0; --i) { if ([cards[i][1] intValue] > 1) { [arrM
replaceObjectAtIndex:i withObject:@[cards[i][0], [NSNumber
numberWithInt:[cards[i][1] intValue] - 1]]]; } else { [arrM
removeObjectAtIndex:i]; } } if ((arrM.count && [self checkForCards:arrM]) ||
!arrM.count) return true; } return false; } // 第一张牌的数量是3 -
(BOOL)checkFirstCard3:(NSArray *)cards { // 可以与后面的牌组成顺子,这里为了方便,只是统一成暗刻
NSMutableArray *arrM = [NSMutableArray arrayWithArray:cards]; [arrM
removeObjectAtIndex:0]; if ((arrM.count && [self checkForCards:arrM]) ||
!arrM.count) return true; return false; } // 第一张牌的数量是4 -
(BOOL)checkFirstCard4:(NSArray *)cards { // 先把3张当成暗刻,再继续下一步判断 NSMutableArray
*arrM = [NSMutableArray arrayWithArray:cards]; [arrM replaceObjectAtIndex:0
withObject:@[cards[0][0], [NSNumber numberWithInt:1]]]; return [self
checkForCards:arrM]; } // 将手牌数组转化为二维数组,0、值 1、数量 - (NSArray
*)changeHandCards:(NSArray *)handCards { NSMutableArray *cardsArrM =
[NSMutableArray array]; int count = 1; for (int i = 0; i < handCards.count;
++i) { if (i == handCards.count - 1) { [cardsArrM addObject:@[handCards[i],
[NSNumber numberWithInt:count]]]; break; } if (handCards[i] == handCards[i +
1]) { count++; } else { [cardsArrM addObject:@[handCards[i], [NSNumber
numberWithInt:count]]]; count = 1; } } return cardsArrM; } // 计算数组中有多少张牌 -
(int)cardsCount:(NSArray *)cards { int count = 0; for (int i = 0; i <
cards.count; ++i) { count = count + [cards[i][1] intValue]; } return count; }

检查的牌:

NSArray *arr1 = @[@1, @9, @11, @19, @21, @21, @29, @31, @32, @33, @34, @35,
@36, @37]; NSArray *arr2 = @[@1, @1, @11, @11, @21, @21, @31, @31, @33, @33,
@35, @35, @37, @37]; NSArray *arr3 = @[@1, @1,
@21,@22,@23,@24,@25,@26,@27,@28,@29,@13,@14,@15]; NSArray *arr4 = @[@7, @8, @9,
@21, @22, @23, @23, @23, @24, @25, @26, @13, @14, @15]; NSLog(@"----%@", [self
checkHuWithHandCards:arr1]?@"胡":@"不胡"); NSLog(@"----%@", [self
checkHuWithHandCards:arr2]?@"胡":@"不胡"); NSLog(@"----%@", [self
checkHuWithHandCards:arr3]?@"胡":@"不胡"); NSLog(@"----%@", [self
checkHuWithHandCards:arr4]?@"胡":@"不胡");

技术
©2019-2020 Toolsou All rights reserved,
jmeter-while控制器使用总结(精华)2020年6月26日 C#类库 Enum(扩展方法)keras数据生成器--数据增强mybatis系列之返回结果映射【答学员问】你们从培训机构毕业后都找到什么工作?指定位置输出字符串--PTAvue使用THREE.js创建一个可以控制的立方体python获取excel的一列或者一行的数据vue 获取el-select选中项的label值华为鸿蒙操作系统有哪些特点和优势?余承东《全场景时代 新体验与新生态》演讲全文