牌面表示,用数字代表花色和点数(如 1-9 万,10-18 筒,19-27 条)

从零开始教你写一个“麻将胡了”程序:用代码还原中国人的牌桌智慧

你有没有想过,为什么在街边茶馆、家庭聚会甚至手机App里,麻将总是那么受欢迎?它不仅是娱乐,更是一种融合策略、概率和心理博弈的复杂游戏,我作为一位自媒体作者,带你走进编程的世界,用Python手把手教你写一个“麻将胡了”的判断程序——不是模拟打牌,而是真正理解“胡牌”背后的逻辑!

我们要明确什么是“胡牌”,在标准麻将中,一副牌由13张牌组成,玩家通过摸牌或吃碰杠后凑成4组顺子或刻子+1对将牌(即“听牌”),就可以胡牌。“123万、456筒、789条、一对红中、一对白板”,这就是合法的胡牌组合。

我们用Python实现这个逻辑,先定义数据结构:

import itertools
# 为了简化,我们只处理万、筒、条三种花色(不含字牌)
def is_valid_hand(cards):
    # 检查是否正好14张牌
    if len(cards) != 14:
        return False
    # 将牌分组统计:每种花色单独处理
    suits = {}
    for card in cards:
        suit = (card - 1) // 9 + 1  # 1=万, 2=筒, 3=条
        rank = (card - 1) % 9 + 1   # 1~9
        if suit not in suits:
            suits[suit] = []
        suits[suit].append(rank)
    # 对每个花色分别检查是否能组成有效组合
    for suit_cards in suits.values():
        if not can_form_groups(suit_cards):
            return False
    # 检查是否有且仅有一对将牌(两个相同的数字)
    pairs = [c for c in cards if cards.count(c) == 2]
    if len(pairs) != 1:
        return False
    return True
def can_form_groups(cards):
    # 排序便于处理
    cards.sort()
    # 使用递归穷举所有可能的分组方式(顺子/刻子)
    def backtrack(hand, groups):
        if not hand:
            return True
        # 尝试组成顺子(3连)
        for i in range(len(hand)):
            for j in range(i+1, len(hand)):
                for k in range(j+1, len(hand)):
                    if hand[i] + 1 == hand[j] and hand[j] + 1 == hand[k]:
                        new_hand = hand[:i] + hand[i+1:j] + hand[j+1:k] + hand[k+1:]
                        if backtrack(new_hand, groups + [(hand[i], hand[j], hand[k])]):
                            return True
        # 尝试组成刻子(三个相同)
        for i in range(len(hand)):
            if hand.count(hand[i]) >= 3:
                new_hand = [x for x in hand if x != hand[i]]
                if backtrack(new_hand, groups + [[hand[i]] * 3]):
                    return True
        return False
    return backtrack(cards, [])

这段代码的核心在于“回溯法”:尝试所有可能的组合方式,直到找到一种合法的胡牌结构,虽然效率不高(指数级复杂度),但非常适合教学演示。

举个例子: 输入:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13] 输出:True(说明这副牌可以胡!)

真实麻将还有更多规则,比如七对、十三幺、混一色等特殊牌型,这些都可以扩展为独立函数来处理。

写这个程序的意义不止是“让电脑能识牌”,更重要的是帮助我们理解麻将的本质:它是一种数学游戏,也是一种文化符号,当你用代码还原出“胡牌”的逻辑时,你会发现——原来那些看似玄乎的“听牌感觉”,其实都藏在排列组合之中。

如果你喜欢这种“编程+生活”的内容,请点赞关注,下期我会讲如何用AI预测对手出牌习惯,让你在牌桌上真正“赢麻了”!

牌面表示,用数字代表花色和点数(如 1-9 万,10-18 筒,19-27 条)