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

你有没有想过,自己也能写出一个能自动判断是否“胡牌”的麻将程序?不是靠运气,而是靠代码逻辑!我就带大家用Python一步步实现一个基础但功能完整的“麻将胡了”判断器,这不仅是编程爱好者的挑战,也是理解算法思维的好机会。

先说结论:一个标准的麻将胡牌规则,核心在于“四组一對”,即4个顺子或刻子 + 1对将牌,我们这个程序的目标就是输入一组牌(比如123456789万条筒),然后判断它能不能胡牌。

为什么做这个?
这是典型的回溯算法应用场景——你要遍历所有可能的组合方式来判断是否存在一种合法胡法,它融合了数据结构(列表、字典)、递归、剪枝优化等编程技巧,非常适合初学者练手,如果你是个麻将爱好者,写完后还能拿去测试朋友的牌是不是真能胡!

准备阶段:环境搭建
你需要安装Python 3.8+(推荐Anaconda),不需要额外库,纯原生代码即可运行,我会用最直观的方式写,不依赖第三方模块,保证可读性强,适合边看边敲代码。

第一步:定义牌面和基本数据结构
我们用字符串表示牌,“1万”、“5筒”、“9条”,为了方便处理,我们把所有牌按数字分组:万、条、筒各1~9,我们用一个列表存储输入的牌,["1万", "2万", "3万", "4筒", "4筒", "4筒"]。

第二步:编写判断函数
核心逻辑是“尝试拆解牌组”,用递归实现回溯:

def can_win(cards):
    if not cards:
        return True  # 所有牌都拆完了,说明胡了
    # 尝试找一对将牌(两个相同的)
    for i in range(len(cards)):
        for j in range(i+1, len(cards)):
            if cards[i] == cards[j]:
                new_cards = cards[:i] + cards[i+1:j] + cards[j+1:]
                if can_win(new_cards):  # 递归检查剩余牌是否能组成三组
                    return True
    # 如果找不到将牌,就尝试找顺子或刻子
    for i in range(len(cards)):
        card = cards[i]
        # 刻子:三个一样的
        if card in cards[:i] and card in cards[i+1:]:
            new_cards = cards[:i] + cards[i+1:]
            if can_win(new_cards):
                return True
        # 顺子:同一花色连续三张(如123)
        # 这里简化处理:只考虑同花色且数字连续
        if card.endswith("万") or card.endswith("条") or card.endswith("筒"):
            num = int(card[:-1])
            next_num = num + 1
            next_next_num = num + 2
            next_card = f"{next_num}{card[-1]}"
            next_next_card = f"{next_next_num}{card[-1]}"
            if next_card in cards and next_next_card in cards:
                new_cards = cards[:i] + cards[i+1:]
                new_cards.remove(next_card)
                new_cards.remove(next_next_card)
                if can_win(new_cards):
                    return True
    return False

这段代码虽然简洁,但逻辑完整:

  • 先找将牌(两个相同)
  • 再找刻子(三个相同)
  • 最后找顺子(连续三张)
    每次拆掉一组后,递归调用自身判断剩余牌是否还能胡。

第三步:测试你的程序
试试这个输入:["1万", "2万", "3万", "4万", "5万", "6万", "7万", "8万", "9万", "1万", "1万"]
这其实是“清一色七对子”的变体,应该能胡!
运行结果会告诉你:True ✅

再试一个反例:["1万", "2万", "3万", "4万", "5万", "6万", "7万", "8万", "9万"] —— 缺少一对将牌,不能胡!结果为 False ❌

优化建议:
目前版本性能一般,因为存在重复计算,你可以加入记忆化缓存(@lru_cache)来加速,可以扩展支持“十三幺”、“七对子”等特殊牌型,让程序更贴近真实麻将规则。


写这个程序的过程,其实是在训练我们的算法思维:如何把复杂问题分解成小步骤?如何避免无效搜索?如何通过递归来穷举所有可能性?这些能力,远比“打麻将赢钱”更重要!

如果你想进一步学习,我建议你:

  1. 把这个程序封装成类,支持多局游戏记录;
  2. 加入GUI界面(用Tkinter);
  3. 对接AI模型,让它帮你出牌建议!

别忘了动手实践!码上就是最好的学习方式,下次打麻将时,说不定你能笑着告诉朋友:“这手牌,我用Python算过,稳胡!” 😄

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