大家好,我是你们的老朋友小码哥,一个沉迷编程又热爱麻将的自媒体作者,今天不聊八卦、不讲热点,咱们来点硬核的——教你用 Python 写一个能自动判断“麻将胡了”的程序!没错,就是那个让你在牌桌上赢麻了(不是)的逻辑核心!
如果你玩过麻将,一定知道“胡牌”不是随便凑齐四组顺子加一对就能算的,它有严格的规则:必须是四个面子(顺子或刻子)加一个对子,且不能重复、不能多张,这听起来像数学题?没错,但更像算法题!而今天我们就是要用代码把它变成现实。
先说清楚我们要实现什么功能:
输入一组13张麻将牌(数字代表牌面,比如1-9表示万、筒、条),输出是否满足胡牌条件,比如输入 [1,1,2,2,3,3,4,4,5,5,6,6,7],系统应该告诉你:“可以胡!”或者“不能胡”。
第一步:数据结构设计
我们用列表模拟手牌,每张牌用数字表示,1~9代表同一种花色(如万子),重复数字代表相同牌,为了方便计算,我们先把所有牌按数字排序,再统计每种牌的数量。
第二步:枚举所有可能的“对子”
胡牌必须有一个对子,所以我们遍历所有可能的对子组合(即两个相同的数字),比如如果手上有三个1,那我们可以选其中两个作为对子,剩下的一个留着组成顺子或刻子。
第三步:检查剩余11张牌是否能组成3组面子
这个是最关键的部分!我们要从剩下的11张牌中找出3组合法的面子(顺子 or 刻子),这里有个技巧:
但问题来了:如何高效地穷举所有可能?别怕,Python 提供了 itertools 模块,我们可以用递归+回溯的方式暴力破解,但效率不高,聪明的做法是:
先尝试所有可能的刻子组合,再用贪心法处理顺子(优先从最小数字开始匹配顺子),这样既快又准。
第四步:写代码!
下面是简化版核心逻辑(完整代码可私信我获取):
def is_valid_hand(hand):
from collections import Counter
counts = Counter(hand)
# 尝试每一个可能的对子
for pair in counts:
if counts[pair] < 2:
continue
new_counts = counts.copy()
new_counts[pair] -= 2
if can_form_melds(new_counts):
return True
return False
def can_form_melds(counts):
if not any(counts.values()):
return True
# 找到第一个非零的牌
for i in range(1, 10):
if counts[i] > 0:
# 先尝试刻子
if counts[i] >= 3:
counts[i] -= 3
if can_form_melds(counts):
return True
counts[i] += 3
# 再尝试顺子
if i <= 7 and counts[i+1] > 0 and counts[i+2] > 0:
counts[i] -= 1
counts[i+1] -= 1
counts[i+2] -= 1
if can_form_melds(counts):
return True
counts[i] += 1
counts[i+1] += 1
counts[i+2] += 1
return False
第五步:测试验证
我们拿几个经典案例跑一跑:
✅ 胡牌示例:[1,1,2,2,3,3,4,4,5,5,6,6,7] → 输出 True
❌ 非胡牌:[1,1,1,2,2,2,3,3,3,4,4,4,5] → 输出 False(因为没有对子,只有四个刻子)
第六步:扩展应用
你以为这就完了?不!这个程序可以做成手机App,甚至集成进AI麻将助手,你可以让它实时分析你手中的牌,提示“你现在可以胡了吗?”、“要不要换这张牌?”——简直是牌技提升神器!
写麻将胡牌判断程序,本质是在解决一个“组合优化”问题,它考验的是你的逻辑思维和编码能力,同时也能帮你理解游戏背后的数学之美,下次打麻将时,别人还在纠结“要不要碰”,你已经默默用代码算出了最优解——那一刻,你就赢了。
如果你也喜欢这种“把生活变代码”的玩法,记得点赞+关注!下期我还会教你怎么用Python做一个“智能打麻将机器人”,让它跟你对战还能分析你的情绪(笑)!
我是小码哥,我们下期见!
