大家好,我是你们的自媒体作者小智,今天不聊八卦、不讲段子,来点硬核干货——教大家用Python写一个“麻将胡了”的判断程序!是不是听着就很酷?别急,我保证看完这篇,你不仅能理解麻将胡了的底层逻辑,还能亲手写出一个能自动判断是否胡牌的小工具。
先说重点:麻将胡了的本质是什么?不是运气,是组合数学!只要你的手牌满足特定的牌型结构,就能“胡”!我们今天的目标,就是让电脑帮你判断:“你这手牌,能不能胡?”
麻将基本规则简化版(只讲胡牌部分)
在标准中国麻将中,一副完整的胡牌必须由以下结构组成:
- 四个顺子 + 一个刻子(对子)
- 顺子:三张连续数字牌,3万、4万、5万
- 刻子:三张相同牌,7筒、7筒、7筒
- 对子:两张相同牌,2条、2条(作为将牌)
注意:有些地方还有“七对”、“十三幺”等特殊牌型,但我们今天先聚焦最常见、最容易实现的“四组顺子+一对将”。
如何用代码实现?
我们要做的第一步是:把玩家的手牌变成计算机能处理的数据结构。
假设输入是一个字符串列表,
hand = ['1万', '1万', '2万', '3万', '4万', '5万', '6万', '7万', '8万', '9万', '1筒', '1筒', '2筒', '2筒']
(这里我故意凑了一个“胡”的手牌:两对1筒、2筒,加上一个顺子和两个顺子,还有一个对子)
第一步:数据清洗与分类
我们需要把每张牌按花色和数字分组,我们可以用字典来存储:
def parse_hand(hand):
suits = {'万': [], '筒': [], '条': []}
for card in hand:
suit = card[-1] # 最后一个字符是花色
rank = int(card[:-1]) # 前面的是数字
suits[suit].append(rank)
return suits
这样,suits['万'] 就是所有“万”牌的数字列表,[1,1,2,3,4,5,6,7,8,9]。
第二步:检查是否能组成合法胡牌结构
核心思路是:尝试所有可能的配对方式,看看有没有一种组合能让手牌被完全拆解成“四组顺子 + 一个对子”。
我们可以写一个递归函数来暴力枚举所有可能性(虽然效率不高,但适合教学):
def is_valid_hu(suits):
# 先统计总牌数,必须是14张
total = sum(len(cards) for cards in suits.values())
if total != 14:
return False
# 尝试每个花色中的牌组合
for suit in suits:
ranks = sorted(suits[suit])
if not can_form_groups(ranks):
return False
return True
然后是关键函数 can_form_groups() —— 这里才是真正的逻辑所在:
def can_form_groups(ranks):
if not ranks:
return True
# 尝试取一个对子(如果存在)
for i in range(len(ranks)):
for j in range(i+1, len(ranks)):
if ranks[i] == ranks[j]:
# 取出这对,剩下的继续递归
new_ranks = ranks[:i] + ranks[i+1:j] + ranks[j+1:]
if can_form_groups(new_ranks):
return True
# 如果没找到对子,就尝试组成顺子(1,2,3)
for i in range(len(ranks)):
if ranks[i] + 1 in ranks and ranks[i] + 2 in ranks:
# 找到顺子,去掉这三个数
new_ranks = ranks[:i] + ranks[i+1:] # 暂时简化处理
# 实际上需要更复杂地删除三个元素
# 为了简化,这里可以用集合操作或标记法
pass
return False
⚠️ 注意:上面这个版本还不够严谨,因为要精确删除三个元素而不影响其他匹配,实际开发中,建议用回溯法或者动态规划优化,但为了小白友好,我们先理解思想即可。
实战演示:测试我们的程序
我们拿之前那个例子跑一下:
hand = ['1万', '1万', '2万', '3万', '4万', '5万', '6万', '7万', '8万', '9万', '1筒', '1筒', '2筒', '2筒']
if is_valid_hu(parse_hand(hand)):
print("恭喜!你胡了!")
else:
print("还没胡,再摸一张吧~")
输出应该是:“恭喜!你胡了!”
为什么?因为你有:
- 顺子:2万3万4万
- 顺子:5万6万7万
- 顺子:8万9万?不对,等等……哦!其实是:1万2万3万 是顺子,4万5万6万 是顺子,7万8万9万 是顺子,剩下两个1万和两个2筒是将牌!完美!
扩展建议(给想进阶的同学)
如果你觉得这个程序太简单,可以挑战这些方向:
- 支持“七对”、“十三幺”等特殊胡法;
- 加入“杠”、“碰”等操作;
- 把整个过程做成网页版,让用户上传手牌直接判断;
- 甚至接入AI模型预测最佳胡牌策略!
编程不是玄学,而是把生活里的规则翻译成代码的过程,麻将胡了,不只是靠运气,更是靠逻辑和耐心,希望今天的分享让你对编程更有信心,也对麻将更有兴趣!
下次我想讲《用Python做个扑克牌游戏》,欢迎关注我,一起玩转代码世界!🎉







