从代码到牌局,手把手教你用Python实现麻将胡了判断程序

bba47115568 2026-02-09 麻将胡了PG 104 0

大家好,我是你们的自媒体作者小麻,一个喜欢用代码玩转生活的技术宅,今天不聊短视频、不讲流量密码,咱们来点硬核的——用Python写一个能自动判断“麻将是否胡了”的程序!是不是听着就有点热血沸腾?别急,我带你一步步拆解逻辑,从零开始搭建你的第一个麻将AI裁判。

你得明白什么叫“胡了”?在麻将中,“胡”是指玩家手中的13张牌(加上最后一张摸来的)刚好组成4组顺子或刻子 + 1对将牌。

  • 三组刻子(如三个5万、三个红中)
  • 两组顺子(如一二三条、四五六筒)
  • 一对将牌(比如两个白板)

这个规则看似简单,实则非常考验算法设计能力,很多人一上来就想暴力枚举所有组合,结果效率低到爆炸,那我们怎么高效解决这个问题呢?

第一步:数据结构设计
我们要把一张牌用数字表示,

  • 数字1~9代表一万到九万
  • 10~18代表一条到九条
  • 19~27代表一筒到九筒
  • 28~34是风牌(东南西北中发白),每种只有一张,不能重复

这样,一手牌就可以表示成一个长度为13的列表(或者更优地,用字典统计每种牌的数量)。 hand = [1,1,1,2,3,4,5,6,7,8,9,9,9] 表示有三个一万、一个二万、一个三万……等等。

第二步:核心逻辑——回溯法 + 剪枝优化
我们需要遍历所有可能的组合方式,看能否恰好分成4组+1对,关键在于“剪枝”——如果当前组合已经不可能成功,就立刻放弃,避免无效计算。

具体步骤如下:

  1. 先找一对将牌(任意两张相同的牌)
  2. 然后递归地尝试把剩下的11张牌分成3组合法的组合(顺子或刻子)
  3. 如果能找到这样的分法,说明这手牌可以胡!

怎么判断一组牌是否合法?

  • 刻子:同一张牌出现3次(如三个5万)
  • 顺子:连续三张相同花色(如一万、二万、三万)

第三步:写代码实现
以下是简化版伪代码(完整代码可私信我获取):

def is_valid_hand(hand):
    # 统计每种牌的数量
    count = {}
    for card in hand:
        count[card] = count.get(card, 0) + 1
    def can_form_groups(cards_left, groups_needed):
        if groups_needed == 0:
            return len(cards_left) == 0  # 所有牌都用完了
        # 尝试找一对将牌(先处理掉)
        for card in cards_left:
            if cards_left[card] >= 2:
                cards_left[card] -= 2
                if can_form_groups(cards_left, groups_needed - 1):
                    return True
                cards_left[card] += 2  # 回溯
        # 尝试找顺子或刻子(优先处理刻子)
        for card in range(1, 28):  # 只考虑数字牌
            if cards_left.get(card, 0) >= 3:
                cards_left[card] -= 3
                if can_form_groups(cards_left, groups_needed - 1):
                    return True
                cards_left[card] += 3
            # 顺子:从1到7(因为要连续三张)
            if card <= 7 and cards_left.get(card, 0) > 0 \
               and cards_left.get(card+1, 0) > 0 \
               and cards_left.get(card+2, 0) > 0:
                cards_left[card] -= 1
                cards_left[card+1] -= 1
                cards_left[card+2] -= 1
                if can_form_groups(cards_left, groups_needed - 1):
                    return True
                cards_left[card] += 1
                cards_left[card+1] += 1
                cards_left[card+2] += 1
        return False
    return can_form_groups(count, 3)

这段代码的核心思想就是:先找将牌,再不断尝试构造顺子/刻子,直到分完为止,通过回溯法确保不会漏掉任何可能的组合。

第四步:测试验证
我们可以手动输入几组经典胡牌案例来验证程序正确性:

  • ✅ 胡牌例子:[1,1,1,2,3,4,5,6,7,8,9,9,9] → 可以组成三个刻子(111, 999)+ 一对将牌(234? 不对……哦,其实这是错的!) 等等,我发现了一个坑——上面这个例子其实是不能胡的!因为它没有形成有效的顺子或刻子组合,真正的胡牌必须严格符合规则。

我们还要增加边界条件和调试输出,比如打印每一步的分组过程,帮助理解程序行为。

最后总结一下:
这个“麻将胡了”程序不仅是个好玩的小工具,更是学习递归、回溯、剪枝等经典算法的绝佳案例,它教会我们如何把现实生活中的复杂问题抽象成数学模型,再用代码精准还原。

如果你也想开发自己的麻将游戏、智能打牌助手,或者只是单纯想挑战逻辑思维,不妨动手试试这个项目吧!关注我,下期分享如何让AI自动出牌、模拟真人对战,让你真正拥有一个会“思考”的麻将机器人!

我是小麻,一个用代码玩转生活的人,我们下次见!

从代码到牌局,手把手教你用Python实现麻将胡了判断程序