Python实现德州扑克牌型比较与排序算法详解

沈亦白
沈亦白
发布时间:2026-10-10| 2人浏览过
原创

本文详细解析使用Python实现德州扑克牌型比较与排序的算法。通过定义牌面等级、花色判断及牌型识别函数,利用元组排序特性实现多条件比较。重点处理了同花顺、四条、葫芦等复杂牌型,并解决了A作为最小值(A-2-3-4-5)的边界情况,最终实现高效、准确的牌局评估。

核心逻辑与数据结构设计

在德州扑克中,比较手牌大小的核心在于将复杂的牌面抽象为可比较的数值序列。程序首先需要解析输入的5张牌,提取其点数(ranks)和花色(suits)。为了便于后续比较,我们将点数映射为数字:'2'到'9'对应2到9,'T'、'J'、'Q'、'K'、'A'分别对应10、11、12、13、14。

比较两个手牌时,遵循“等级优先,点数次之”的原则。首先判断牌型等级(如同花顺、四条等),等级高的手牌直接获胜;若等级相同,则依次比较构成该牌型的关键牌点数,直至分出胜负。

关键函数实现

1. 牌面解析与排序

首先定义 card_ranks 函数,将手牌字符串转换为数字列表,并按降序排列。这为后续比较提供了统一的数据格式。

def card_ranks(hand):
    ranks = ['--23456789TJQKA'.index(r) for r, s in hand]
    ranks.sort(reverse=True)
    return ranks

2. 基础牌型判断

我们需要判断手牌是否满足“顺子”(Straight)和“同花”(Flush)的条件:

  • 顺子判断:点数最大值与最小值之差为4,且去重后长度为5。注意这里暂未处理A作为最小值(A-2-3-4-5)的特殊情况,该情况将在后文单独处理。
  • 同花判断:提取所有牌的花色,若去重后集合长度为1,则为同花。
def straight(ranks):
    return (max(ranks) - min(ranks)) == 4 and len(set(ranks)) == 5

def flush(hand):
    suit = [s for r, s in hand]
    return len(set(suit)) == 1

3. 牌型识别函数 kind(n)

为了识别四条、三条、对子等牌型,定义 kind(n, ranks) 函数。该函数遍历排序后的点数列表,返回出现次数恰好为 n 的点数。若不存在或存在多个,则返回 None。

def kind(n, ranks):
    for s in ranks:
        if ranks.count(s) == n:
            return s
    return None

4. 处理两个对子(Two Pair)

当手牌包含两个对子时,需要返回较大的对子和较小的对子。利用 kind(2) 获取第一个对子,再将点数列表反转后再次调用 kind(2) 获取第二个对子。若两次结果不同,说明有两个对子;若相同,则说明只有一个对子或没有。

def two_pair(ranks):
    pair = kind(2, ranks)
    lowpair = kind(2, list(reversed(ranks)))
    if pair != lowpair:
        return (pair, lowpair)
    else:
        return None

综合牌型评估 (hand_rank)

根据德州扑克的规则,牌型等级从高到低依次为:同花顺、四条、葫芦、同花、顺子、三条、两对、对子、高牌。我们定义 hand_rank 函数,返回一个元组,元组的第一个元素为等级,后续元素为用于比较的点数。

def hand_rank(hand):
    ranks = card_ranks(hand)
    if straight(ranks) and flush(hand):
        return (8, max(ranks))
    elif kind(4, ranks):
        return (7, kind(4, ranks), kind(1, ranks))
    elif kind(3, ranks) and kind(2, ranks):
        return (6, kind(3, ranks), kind(2, ranks))
    elif flush(hand):
        return (5, ranks)
    elif straight(ranks):
        return (4, max(ranks))
    elif kind(3, ranks):
        return (3, kind(3, ranks), ranks)
    elif two_pair(ranks):
        return (2, two_pair(ranks), ranks)
    elif kind(2, ranks):
        return (1, kind(2, ranks), ranks)
    else:
        return (0, ranks)

特殊边界情况处理:A-2-3-4-5 顺子

在标准顺子判断中,A通常被视为最大点数(14)。然而,A-2-3-4-5 也是一种合法的顺子,此时A应被视为最小点数(1)。在 card_ranks 函数中,若检测到点数为 [14, 5, 4, 3, 2],则将其转换为 [5, 4, 3, 2, 1] 以正确参与比较。

def card_ranks(hand):
    ranks = ['--23456789TJQKA'.index(r) for r, s in hand]
    ranks.sort(reverse=True)
    return [5, 4, 3, 2, 1] if (ranks == [14, 5, 4, 3, 2]) else ranks

完整牌局处理与洗牌发牌

最后,实现 poker 函数,接收多手牌列表,返回所有最大手牌的集合。利用 allmax 辅助函数,通过 hand_rank 作为比较键,找出所有等级最高的手牌。同时,提供 deal 函数进行洗牌和发牌,模拟真实游戏流程。

def poker(hands):
    return allmax(hands, key=hand_rank)

def allmax(iterable, key=None):
    result, maxval = [], None
    key = key or (lambda x: x)
    for x in iterable:
        xval = key(x)
        if not result or xval > maxval:
            result, maxval = [x], xval
        elif xval == maxval:
            result.append(x)
    return result

import random
def deal(numhands, n=5, deck=[r+s for r in '23456789TJKQA' for s in 'SHDC']):
    random.shuffle(deck)
    return [deck[n*i:n*(i + 1)] for i in range(numhands)]

通过上述步骤,我们实现了一个完整且高效的德州扑克牌型比较系统。该程序不仅处理了常规牌型,还妥善处理了边界情况,确保了比较的准确性和鲁棒性。

以上就是Python实现德州扑克牌型比较与排序算法的详细内容,更多关于Python算法实现、德州扑克编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。