欧拉计划 54

本文介绍了一种算法,用于判断扑克游戏中两种牌型的大小。通过分析牌型(如一对、两对、三条等)和牌面值来确定胜者。算法还处理了特殊情况,如皇家同花顺和同花顺,并提供了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在扑克游戏中,一局牌由五张牌组成,组成的牌的大小由低向高如下:

High Card: 最高值的牌.
One Pair: 两张面值一样的牌.
Two Pairs: 两个值不同的One Pair.
Three of a Kind: 三张面值一样的牌.
Straight: 所有的牌面值为连续数值.
Flush: 所有的牌花色相同.
Full House: Three of a Kind 加一个One Pair.
Four of a Kind: 四张牌面值相同.
Straight Flush: 所有的牌花色相同并且为连续数值.
Royal Flush: 10,J,Q,K和A,并且为相同花色。
牌的面值大小排序如下:
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.

如果两个玩家的牌具有同样的排序(上面介绍的几种),那么他们牌的大小由手中最大的牌决定。
例如,一对8比一对5大(见下面例一);
但是如果两个玩家都用一对Q,那么他们手中最大的牌就用来比较大小(见下面例四);
如果他们最高面值的牌也相等,那么就用次高面值的牌比较,以此类推。

考虑下面的几个例子:

局 玩家 1 玩家 2 胜利者
1 5H 5C 6S 7S KD 一对5 2C 3S 8S 8D TD 一对8 玩家 2
2 5D 8C 9S JS AC 最大面值牌A 2C 5C 7D 8S QH 最大面值牌Q 玩家 1
3 2D 9C AS AH AC 三个A 3D 6D 7D TD QD 方片Flush 玩家 2
4 4D 6S 9H QH QC 一对Q最大牌9 3D 6D 7H QD QS 一对Q 最大牌7 玩家 1
5 2H 2D 4C 4D 4S 三个4的Full House 3C 3D 3S 9S 9D 三个3的Full House 玩家 1

文件 poker.txt 包含一千局随机牌。
每一行包含十张牌(用空格分隔);前五张是玩家1的牌,后五张是玩家2的牌。
所有的牌都是合理的(没有非法字符或者重复的牌)。每个玩家的牌没有顺序,并且每一局都有明确的输赢。

其中玩家1能赢多少局?

type_dict = {
    'High Card': 0,
    'One Pair': 1,
    'Two Pairs': 2,
    'Three of a Kind': 3,
    'Straight': 4,
    'Flush': 5,
    'Full House': 6,
    'Four of a Kind': 7,
    'Straight Flush': 8,
    'Royal Flush': 9,
}

value_dict = {
    'T': 10,
    'J': 11,
    'Q': 12,
    'K': 13,
    'A': 14
}
for i in range(2, 10):
    value_dict[str(i)] = i


def is_same_suit(player):
    """ is same suit """
    suit_list = [p[-1] for p in player]
    if len(set(suit_list)) == 1:
        return True
    else:
        return False


def to_values(player):
    """ str to values """
    values = [value_dict[p[0]] for p in player]
    values.sort(reverse=True)
    return values


def is_consecutive_values(values):
    """ is consecutive values """
    for i in range(len(values)-1):
        if values[i + 1] - values[i] != -1:
            return False
    return True


def get_values_count(values):
    """ values count """
    value_num_dict = dict()
    for v in values:
        value_num_dict[v] = value_num_dict.setdefault(v, 0) + 1
    return sorted(value_num_dict.items(), key=lambda d: d[1], reverse=True)


def poker_type(player):
    """ type, value """
    player_is_same_suit = is_same_suit(player)
    player_values = to_values(player)
    player_is_consecutive_values = is_consecutive_values(player_values)
    if player_is_same_suit:
        if player_is_consecutive_values:
            if player_values[0] == 14:
                return 'Royal Flush', player_values[0]
            else:
                return 'Straight Flush', player_values[0]
        else:
            return 'Flush', player_values
    if player_is_consecutive_values:
        return 'Straight', player_values[0]
    player_count = get_values_count(player_values)
    if player_count[0][1] == 4:
        return 'Four of a Kind', player_count[0][0]
    if player_count[0][1] == 3:
        if player_count[1][1] == 2:
            return 'Full House', player_count[0][0]
        else:
            return 'Three of a Kind', player_count[0][0]
    if player_count[0][1] == 2:
        if player_count[1][1] == 2:
            l = [player_count[0][0], player_count[1][0]]
            l.sort(reverse=True)
            l.append(player_count[2][0])
            return 'Two Pairs', l
        else:
            l = [player_count[i][0] for i in range(1, 4)]
            l.sort(reverse=True)
            l.insert(0, player_count[0][0])
            return 'One Pair', l
    return 'High Card', player_values


def main():
    """ main """
    n = 0
    file_object = open('p054_poker.txt')
    for line in file_object:
        l_ = line.split()
        player_1 = l_[:5]
        player_2 = l_[5:]
        player_1_type, player_1_values = poker_type(player_1)
        player_2_type, player_2_values = poker_type(player_2)
        if type_dict[player_1_type] > type_dict[player_2_type]:
            n += 1
        elif type_dict[player_1_type] == type_dict[player_2_type]:
            for v1, v2 in zip(player_1_values, player_2_values):
                if v1 > v2:
                    n += 1
                    break
                elif v1 < v2:
                    break
    file_object.close()
    return n


if __name__ == '__main__':
    print(main())

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值