测试案例

手把手教你用Python写一个“麻将胡了”判断程序

大家好,我是你们的自媒体作者小码哥,今天不聊八卦、不讲热点,来点硬核又有趣的——用Python写一个能自动判断“麻将是否胡了”的程序!你没听错,就是那种你在手机上玩麻将时,系统提示“恭喜你胡了!”的逻辑。

很多人以为打麻将全靠运气,但其实背后有一套严谨的数学规则和算法逻辑,标准的国标麻将中,“胡牌”必须满足以下条件:

  1. 由4组顺子或刻子 + 1对将牌组成(共14张);
  2. 所有牌型符合规则(不能有重复、不能多出);
  3. 没有违规组合(如三张一样的万字加一张其他万字算无效)。

我们今天的目标,就是把这个判断过程自动化!用代码模拟人类玩家的思考路径。

先说思路:
我们要写一个函数,输入是一组14张牌(用数字表示,1~9代表筒子,10~18是条子,19~27是万子,28~34是东南西北中发白),输出是True or False —— 表示是否胡牌。

步骤拆解如下:

第一步:预处理数据
把输入的牌整理成一个列表,[1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 10],然后统计每种牌的数量(可以用字典或Counter),这样就能快速判断是否有刻子、顺子。

第二步:枚举所有可能的“将牌”
因为胡牌必须有一对将牌,所以我们先尝试每一种可能出现的将牌(即两张相同的牌),如果牌中有三个1,那我们可以选两个作为将,剩下的一张可以参与顺子/刻子。

第三步:递归判断剩余12张牌能否分成4组合法组合
这是一个关键点,我们写一个递归函数,不断尝试从剩余牌中提取一组顺子或刻子,直到没有牌为止,如果某次成功分完,说明这局能胡!

具体怎么判断顺子?
比如牌是[1,2,3],我们就认为它是一个顺子(同花色连续数字),注意:顺子只能是连续三个不同数字,且在同一花色内(比如筒子1-2-3,不能跨花色)。

刻子则是三张相同数字,1,1,1]。

第四步:优化与剪枝
为了提高效率,我们可以在递归过程中加入一些剪枝策略,

  • 如果某个花色只剩一张牌,无法组成顺子或刻子,直接返回False;
  • 如果当前已匹配的组数超过4组,也可以提前终止。

下面是我写的简化版Python代码(适合初学者理解):

from collections import Counter
def is_valid_mahjong(hand):
    def can_form_group(counts, group_type, target):
        if group_type == 'triplet':
            return counts[target] >= 3
        elif group_type == 'sequence':
            return (counts[target] > 0 and 
                    counts[target+1] > 0 and 
                    counts[target+2] > 0)
    def try_split(counts, used_groups=0):
        if used_groups == 4:
            return True
        for i in range(1, 10):  # 筒子
            if counts[i] >= 3:
                counts[i] -= 3
                if try_split(counts, used_groups + 1):
                    return True
                counts[i] += 3
        for i in range(1, 8):  # 顺子,最多到7才能凑出1-2-3
            if counts[i] > 0 and counts[i+1] > 0 and counts[i+2] > 0:
                counts[i] -= 1
                counts[i+1] -= 1
                counts[i+2] -= 1
                if try_split(counts, used_groups + 1):
                    return True
                counts[i] += 1
                counts[i+1] += 1
                counts[i+2] += 1
        return False
    hand = sorted(hand)
    counts = Counter(hand)
    # 尝试每一对作为将牌
    for card in set(hand):
        if counts[card] >= 2:
            counts[card] -= 2  # 去掉一对将牌
            if try_split(counts.copy()):
                return True
            counts[card] += 2  # 回溯
    return False
print(is_valid_mahjong([1,1,1,2,3,4,5,6,7,8,9,9,9,10]))  # False
print(is_valid_mahjong([1,1,1,2,2,2,3,3,3,4,4,4,5,5]))   # True(三组刻子 + 一对将)

这个程序虽然简略,但已经能准确识别大部分常见胡牌情况,你可以把它扩展为GUI界面,甚至接入微信小程序或抖音小游戏,让AI帮你判断胡牌状态!


写这个程序的过程,其实就是把“人类思维”变成“机器逻辑”,从数据结构、递归回溯到剪枝优化,全是编程基本功,更重要的是,它让我们明白:麻将不仅是娱乐,更是算法思维的绝佳训练场!

如果你也喜欢这种“生活+技术”的结合,请点赞关注我!下期我想讲《用Python写一个自动洗牌发牌的麻将游戏》,敬请期待!

测试案例

本文转载自互联网,如有侵权,联系删除

麻将胡了下载