[python]判断麻将和牌算法

代码

import re

def check_win(cards):
    complete = []
    cards = sorted(cards)
    for i in set(cards):
        original_cards = cards.copy()
        if cards.count(i) >= 2:
            cards.remove(i)
            cards.remove(i)
            complete.append((i, i))
            for j in range(int(len(cards)/3)):
                if cards.count(cards[0]) >= 3:
                    complete.append((cards[0], cards[0], cards[0]))
                    cards = cards[3:]
                elif cards[0] in cards and cards[0]+1 in cards and cards[0]+2 in cards:
                    complete.append((cards[0], cards[0]+1, cards[0]+2))
                    cards.remove(cards[0]+2)
                    cards.remove(cards[0]+1)
                    cards.remove(cards[0])
        if len(complete) == 5:
            return complete
        else:
            cards = original_cards
            complete = []

def data_transf(cards):
    m = list(map(int, ''.join(re.findall(r'\d+(?=m)', cards))))
    p = list(map(str, ''.join(re.findall(r'\d+(?=p)', cards))))
    for i in range(len(p)):
        p[i] = int('2' + p[i])
    s = list(map(str, ''.join(re.findall(r'\d+(?=s)', cards))))
    for i in range(len(s)):
        s[i] = int('4' + s[i])
    z = list(map(str, ''.join(re.findall(r'\d+(?=z)', cards))))
    for i in range(len(z)):
        z[i] = int('2' + z[i]) * 3
    return m + p + s + z

cards = '1336p243m2p4578p77z'       #1-9:m 21-29:p 41-49:s 63 66 69 72 75 78 81:z
print(check_win(data_transf(cards)))

算法思路

输入格式为了顺应人的习惯,使用正则表达式进行了处理。将数据转换为不同的数字,每个花色之间空出了足够的距离来防止判断顺子干扰(以及未来可能的牌理(向听,进张数)判断)。

转换数据后,将所有数字代码相加组成列表cards,目标是将列表中零散的数字组成一个个元组(即麻将的将、刻字、顺子)的列表complete返回。通过set去重,遍历每一种列表的数字代码,若大于等于2个就认为对子提取成功,开始分析剩下的3n张牌怎样组成面子。

就像判断清一色的听牌一样,从边上抽取面子是最好的选择,这里也是如此。通过思考可以发现,例如333456这样的牌,如果先抽顺子就会留下336这样的无解形状,而先提取刻子就不会发生这样的情况。按照刻子->顺子的顺序循环n次,即可处理完手牌。

不能忘记的是,因为使用remove方法,需要将原始数据备份original_cards,以便下次循环使用。

还有一些后续需要改进的地方,之后再写。

结果展示

乱序的普通手牌
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
九莲也可以
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值