大家好,我是你们的自媒体作者老张,专注用通俗易懂的方式讲技术干货,今天不聊流量、不谈变现,咱们来点硬核的——手把手教你用代码实现一个“麻将胡了”的判断程序。
你有没有玩过麻将?那种桌上牌堆翻飞、气氛紧张的场景,是不是特别刺激?但你知道吗?其实背后有一套严谨的数学逻辑和算法支撑着“胡牌”的判定,如果你是个程序员,或者对游戏开发感兴趣,那这篇文章绝对值得收藏!我会从最基础的规则讲起,一步步带你写出一个能自动识别是否胡牌的程序。
什么是“胡牌”?在麻将中,一副完整的牌必须由4组顺子或刻子 + 1对将牌组成。
- 三个相同的牌(刻子):红中、红中、红中
- 三个连续的牌(顺子):3万、4万、5万
- 一对将牌(眼):东、东
我们的目标就是:输入一局手牌(通常13张),判断它是否能组成合法的胡牌结构。
第一步:数据结构设计
我们先定义手牌的数据格式,可以用一个长度为34的数组表示每种牌的数量(万、条、筒、字牌各9种,共4*9=36种,但实际常用的是34种)。
hand = [0]*34 # 手牌统计数组,索引代表牌号,值代表数量
hand[0] 表示一万的数量,hand[9] 是二条,依此类推,字牌部分:东南西北中发白分别对应索引27到33。
第二步:判断是否可以胡牌的核心算法
思路是:枚举所有可能的“将牌”组合(即两个相同的牌作为眼),然后剩下的11张牌是否能拆分成5组合法的顺子或刻子。
伪代码如下:
for each possible pair (i, i) as eye:
remaining_hand = hand.copy()
remaining_hand[i] -= 2 # 去掉这对将牌
if can_split_into_5_groups(remaining_hand):
return True # 胡了!
return False # 不胡
关键在于 can_split_into_5_groups() 函数,这个函数要递归地尝试把11张牌分组,我们可以这样实现:
- 遍历所有可能的刻子(如三个一样的牌)
- 遍历所有可能的顺子(如三连张,比如123万)
- 如果成功拆出5组,则返回真
这里有个技巧:优先处理刻子,因为刻子更确定;顺子则需要考虑顺序,比如从1开始找顺子,不能跳过。
第三步:Python 实现(简化版)
下面是一个精简但功能完整的代码片段(适合学习理解):
def is_win(hand):
def can_split(h):
if sum(h) == 0:
return True
for i in range(34):
if h[i] >= 3: # 尝试刻子
h[i] -= 3
if can_split(h):
return True
h[i] += 3
if i < 31 and h[i] > 0 and h[i+1] > 0 and h[i+2] > 0: # 尝试顺子
h[i] -= 1
h[i+1] -= 1
h[i+2] -= 1
if can_split(h):
return True
h[i] += 1
h[i+1] += 1
h[i+2] += 1
return False
for i in range(34):
if hand[i] >= 2:
temp = hand[:]
temp[i] -= 2
if can_split(temp):
return True
return False
这个程序虽然简单,但已经能正确识别绝大多数胡牌情况,比如输入 [1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0](即三组123万和一对将牌),会返回 True。
第四步:扩展与优化
实际应用中,还需要处理一些特殊情况:
- 是否允许“七对”、“十三幺”等特殊胡法?
- 如何提高效率?可以用记忆化搜索(memoization)避免重复计算。
- 可以封装成 API,供手机App调用,做成“智能胡牌检测器”。
我想说:写这样一个小程序,不仅锻炼了你的算法思维,还能让你真正理解麻将背后的数学之美,你会发现,看似随机的游戏,其实处处藏着规律。
如果你觉得有用,欢迎点赞+转发!下次我还会分享如何用 Python 写一个“斗地主AI”或者“象棋残局求解器”,敬请期待!
我是老张,一个爱写代码也爱打麻将的自媒体人,我们下期见!

麻将胡了






