改为,1,1,2,3,4,2,3,4,5,6,7,5,6,7]可以拆成顺子(123)456)789)刻子(222)将(11)不对

从零开始教你写一个“麻将胡了”程序:用Python实现经典游戏逻辑!

大家好,我是你们的自媒体作者小智,今天不聊八卦、不讲情感,咱们来点硬核的——手把手带你用 Python 写一个能判断“麻将胡了”的程序!没错,就是那种你打麻将时最关心的“我到底能不能胡?”的问题,别笑,这看似简单的判断,背后其实藏着一套复杂的算法逻辑,如果你是程序员小白,看完这篇,你会惊讶原来麻将也能这么“代码化”;如果你是进阶玩家,说不定还能帮你优化自己的牌局策略。

我们要明确什么是“胡牌”,在标准麻将中(以国标规则为例),胡牌必须满足以下条件:

  1. 有且仅有一个将(一对相同的牌);
  2. 其余牌组成四组顺子或刻子(三张相同牌);
  3. 总共14张牌。

比如你手里有:🀇🀇🀈🀈🀉🀉🀊🀊🀋🀋🀌🀌🀍🀍🀎🀎(四个对子),那显然不能胡,因为没有将和顺/刻组合。 但如果变成:🀇🀇🀈🀈🀉🀉🀊🀊🀋🀋🀌🀌🀍🀍🀎🀎🀏🀏(两个对子 + 一组顺子?不对,这还是不行),这时候你要找的是“四组顺子或刻子 + 一个将”。

所以问题本质是:给定14张牌,能否拆分成合法组合?

我们用 Python 来实现这个判断逻辑,整个过程分为三步:

第一步:数据结构设计
我们把麻将牌用数字表示(简化版,只考虑万、筒、条三种花色,每种1-9):

  • 万:1~9
  • 筒:10~18
  • 条:19~27

这样,一张牌可以用一个整数表示,一万”是1,“二筒”是11,“三条”是20。

第二步:核心算法 —— 回溯法
我们要枚举所有可能的组合方式,具体做法是:

  1. 遍历每一张牌,尝试把它作为“将”;
  2. 剩下的12张牌,看是否能被拆成4组顺子或刻子;
  3. 如果能,说明胡了!

关键在于如何判断剩下的牌能否组成顺子或刻子:

  • 刻子:同一数字出现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)不对