Python实现德州扑克牌型比较与排序算法详解
本文详细解析使用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 ranks2. 基础牌型判断
我们需要判断手牌是否满足“顺子”(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)) == 13. 牌型识别函数 kind(n)
为了识别四条、三条、对子等牌型,定义 kind(n, ranks) 函数。该函数遍历排序后的点数列表,返回出现次数恰好为 n 的点数。若不存在或存在多个,则返回 None。
def kind(n, ranks):
for s in ranks:
if ranks.count(s) == n:
return s
return None4. 处理两个对子(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算法实现、德州扑克编程的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









