从零开始教你写一个“麻将胡了”程序:用Python实现经典游戏逻辑!
大家好,我是你们的自媒体作者小智,今天不聊八卦、不讲情感,咱们来点硬核的——手把手带你用 Python 写一个能判断“麻将胡了”的程序!没错,就是那种你打麻将时最关心的“我到底能不能胡?”的问题,别笑,这看似简单的判断,背后其实藏着一套复杂的算法逻辑,如果你是程序员小白,看完这篇,你会惊讶原来麻将也能这么“代码化”;如果你是进阶玩家,说不定还能帮你优化自己的牌局策略。
我们要明确什么是“胡牌”,在标准麻将中(以国标规则为例),胡牌必须满足以下条件:
- 有且仅有一个将(一对相同的牌);
- 其余牌组成四组顺子或刻子(三张相同牌);
- 总共14张牌。
比如你手里有:🀇🀇🀈🀈🀉🀉🀊🀊🀋🀋🀌🀌🀍🀍🀎🀎(四个对子),那显然不能胡,因为没有将和顺/刻组合。 但如果变成:🀇🀇🀈🀈🀉🀉🀊🀊🀋🀋🀌🀌🀍🀍🀎🀎🀏🀏(两个对子 + 一组顺子?不对,这还是不行),这时候你要找的是“四组顺子或刻子 + 一个将”。
所以问题本质是:给定14张牌,能否拆分成合法组合?
我们用 Python 来实现这个判断逻辑,整个过程分为三步:
第一步:数据结构设计
我们把麻将牌用数字表示(简化版,只考虑万、筒、条三种花色,每种1-9):
- 万:1~9
- 筒:10~18
- 条:19~27
这样,一张牌可以用一个整数表示,一万”是1,“二筒”是11,“三条”是20。
第二步:核心算法 —— 回溯法
我们要枚举所有可能的组合方式,具体做法是:
- 遍历每一张牌,尝试把它作为“将”;
- 剩下的12张牌,看是否能被拆成4组顺子或刻子;
- 如果能,说明胡了!
关键在于如何判断剩下的牌能否组成顺子或刻子:
- 刻子:同一数字出现3次;
- 顺子:连续三个数字(如1,2,3 或 10,11,12)各出现一次。
第三步:代码实现(精简版)
def is_valid_hu(cards):
from collections import Counter
# 统计每张牌的数量
count = Counter(cards)
# 尝试每一张牌作为将(对子)
for card in count:
if count[card] < 2:
continue
# 暂时去掉两张该牌
count[card] -= 2
if can_form_groups(count):
return True
# 还原
count[card] += 2
return False
def can_form_groups(count):
if not count:
return True
# 找到第一张还有剩余的牌
card = next(iter(count))
if count[card] == 0:
del count[card]
return can_form_groups(count)
# 尝试形成刻子(三张相同)
if count[card] >= 3:
count[card] -= 3
if can_form_groups(count):
return True
count[card] += 3
# 尝试形成顺子(连续三张)
# 注意:顺子只能在同花色内形成(这里假设输入已经是统一花色)
if card <= 7 and count[card+1] > 0 and count[card+2] > 0:
count[card] -= 1
count[card+1] -= 1
count[card+2] -= 1
if can_form_groups(count):
return True
count[card] += 1
count[card+1] += 1
count[card+2] += 1
return False
是不是很清晰?这就是一个典型的回溯算法,暴力但有效,你甚至可以扩展它支持更多规则(如七对、十三幺等)。
测试一下:
hand = [1,1,2,2,3,3,4,4,5,5,6,6,7,7] # 两对 + 五组顺子?等等,不对 print(is_valid_hu(hand)) # 输出 False(不是标准胡法)
再试一个真正的胡牌例子:
hand = [1,1,2,2,3,3,4,4,5,5,6,6,7,7] # 七个对子 → 不符合``` 真正写完这个程序后你会发现:很多看似“能胡”的牌型,其实并不满足基本规则,这就是为什么专业玩家要靠经验判断,而我们程序员靠代码验证! 1. “麻将胡了”不是简单数个数,而是组合数学问题; 2. 用回溯法可以穷举所有可能的分组方式; 3. 这个程序不仅能帮你判断胡牌,还能用于开发麻将AI或自动理牌功能! 下次你打麻将时,不妨打开手机记事本,写下你的手牌,跑一跑这个程序,看看是不是真的“胡”了?欢迎留言告诉我你的结果,或者分享你写的版本!我是小智,专注用代码讲生活,下期见!
![改为,1,1,2,3,4,2,3,4,5,6,7,5,6,7]可以拆成顺子(123)456)789)刻子(222)将(11)不对 改为,1,1,2,3,4,2,3,4,5,6,7,5,6,7]可以拆成顺子(123)456)789)刻子(222)将(11)不对](https://m.global-pg-mahjong.com/zb_users/upload/2025/12/20251230222814176710489481619.png)






