【问题标题】:7 Card Poker Hand Evaluator7 张牌扑克手评估器
【发布时间】:2026-02-15 16:15:02
【问题描述】:

有人知道评估 7 张牌扑克手的快速算法吗?这比简单地强力检查一组 7 中的每 21 张 5 张牌组合更有效。

干杯,

皮特

【问题讨论】:

  • 好问题,但我认为你最好只检查 21 种组合,而不是试图找出一些疯狂的捷径。
  • @David 实际上,事实并非如此。人们在编写快速 7 卡评估器方面付出了很多努力。当您想要每秒做数百万手时,速度就变得很重要。
  • @David:有更好的方法更容易阅读并且不需要任何排序。它们的速度也快了几个数量级。一个例子是 - 嗯 - 在这里找到:code.google.com/p/specialkpokereval.
  • 作为练习,我用 Java 编写了自己的代码(为此我想重新发明*)。它已记录在案,并且正是您所描述的。您已经有了很多答案,但如果您使用 Java 编程,它可能与您更相关。回复此评论,我将创建一个链接它的新答案。如果它不是 Java,我想我对你来说不会比任何已经链接的更有趣。
  • 我写了一个 java 程序,可以在 5 秒内检查所有 1.33 亿张 7 张牌:codeproject.com/Articles/1068755/… 这是一个正在进行的项目,所以我希望它会更快。

标签: algorithm poker playing-cards


【解决方案1】:

我用 JavaScript 写了一个。核心评估方法仅使用位操作,因此非常快。考虑到这一点,查看 21 种组合仍然非常快。我们唯一需要更深入的时候是出现平局时。当这种情况发生时,我们需要研究更多细节,看看哪张 5 张牌实际上是最好的。这是我想出的解决方案:

hands=["4 of a Kind", "Straight Flush", "Straight", "Flush", "High Card",
       "1 Pair", "2 Pair", "Royal Flush", "3 of a Kind", "Full House" ];
var A=14, K=13, Q=12, J=11, _ = { "♠":1, "♣":2, "♥":4, "♦":8 };

//Calculates the Rank of a 5 card Poker hand using bit manipulations.
function rankPokerHand(cs,ss) {
  var v, i, o, s = 1<<cs[0]|1<<cs[1]|1<<cs[2]|1<<cs[3]|1<<cs[4];
  for (i=-1, v=o=0; i<5; i++, o=Math.pow(2,cs[i]*4)) {v += o*((v/o&15)+1);}
  v = v % 15 - ((s/(s&-s) == 31) || (s == 0x403c) ? 3 : 1);
  v -= (ss[0] == (ss[1]|ss[2]|ss[3]|ss[4])) * ((s == 0x7c00) ? -5 : 1);

  document.write("Hand: "+hands[v]+((s == 0x403c)?" (Ace low)":"")+"<br/>");
}

//Royal Flush   
rankPokerHand( [ 10, J, Q, K, A],  [ _["♠"], _["♠"], _["♠"], _["♠"], _["♠"] ] ); 

Explanation Here
Demo Here

【讨论】:

  • 为此付出了很多努力! +1 :)
  • 他是个女巫!很棒的文章。
  • 这段代码有一个错误 - 如果你有一张 A 的顺子作为低牌(例如 A♣ 2♦ 3♦ 4♠ 5♥ 6♦ K♥),那么它会错误地选择 降低直。在这个例子中,6♦ 高顺子应该是最好的。这是因为它给了 Ace 额外的权重,但在这种情况下这样做是错误的,因为它不是高顺子而是低顺子。见imgur.com/a/e9wGR
【解决方案2】:

这个网站列出了一堆Poker Hand Evaluator libraries,并提供了关于它们的一些细节。其中大部分是针对 5 张牌的,但至少有一张是针对 7 张牌的,称为The Snezee7 Evaluator。此外,该网站还对用于快速分析扑克手牌的不同技术和算法进行了很好的概述。

我在几个不同的poker projects 中使用了 Pokersource Evaluator 的 Keith Rule C# 端口,并认为它是一个出色的库。您可以使用许多巧妙的技巧来制作真正快速的手动评估器,但编写代码需要大量工作,我强烈建议您使用现有的库。

【讨论】:

  • 请注意,Snezee7 需要 266 MB 的查找表。
  • 确实如此......但这就是您获得快速手动评估器的方式(大量预计算)。二加二评估器使用类似的方法来评估 7 张牌,使用 123 MB 查找表。对于 5 张牌,查找表要小得多。
  • 无耻的插件 - 虽然没有上面的一些插件那么快,但我有一个在不使用任何桌子的情况下每秒完成约 7000 万手的游戏:github.com/ashelly/ACE_eval
  • @polarysekt 遗憾的是,Coding the Wheel 网站已经关闭了几个月。不确定它是否会回来,但现在您可以使用 web.archive.org/web/20140625212722/http://codingthewheel.com/… 在 WayBack Machine 中找到两个链接的详细信息
  • 另一个插件:lcrocker.github.io/onejoker/cardlib 具有多种语言的绑定。它的 5-card evaluator 比以往任何一款都快,它的 7-card evaluator 可以媲美最好的,并且只需要 1Mb 的表。
【解决方案3】:

很高兴您问到 :) 是的,这是一个全新的解决方案,可能只是门票:

代码:http://code.google.com/p/specialkpokereval/
博客:http://specialk-coding.blogspot.com/2010/04/texas-holdem-7-card-evaluator_23.html

此评估器的商业级演变可通过 iTunes Store 用于 iPhone/iPod Touch。它被称为“Poker Ace”。

在 James Devlin 的博客“Coding The Wheel”上可以找到各种解决方案的精彩总结并附有链接。

一位尚未讨论的评估员是Klaatu's

祝你好运!

【讨论】:

  • 我已将您的评估员添加到我的roundup。如有任何反馈,我将不胜感激。
  • @AShelly 您的 ACE 评估员非常棒。多年来我一直梦想着将它移植到 GPU 上……但遗憾的是我不再玩扑克了!
【解决方案4】:

我开发了一种算法来评估 7 张牌手牌,而无需迭代所有 21 种组合。

基本上,它将 7 张牌分为两类:同花和非同花。如果是同花顺,则很容易在 8192 个条目的表中查找该值。如果不是flush,它将使用动态编程技术运行一个哈希函数,然后在49205个条目的哈希表中查找值。

如果您有兴趣,请查看我在 github 上的工作。

https://github.com/HenryRLee/PokerHandEvaluator

【讨论】:

  • 如果你在检查刷新之后而不是在 if(suit-suit_hash]) 之前计算五进制,那么你的评估器可以大大提高性能,因为 len 总是 13 并且 k 总是 7 扁平化循环可以节省另一个平均 15%
  • @SiddharthChabra 好主意。感谢您的提示。如果您愿意,欢迎您提交拉取请求。
【解决方案5】:

我认为你应该做 21 种组合并使用某种 7462 表。 第一:任何7张牌有21种不同的5张牌组合 第 2 名:每一个可能的最终扑克牌 (2.598.960) 代表 7462 种不同类型的牌中的一种 所以,这很容易。

您只需查看每 21 种卡片组合,并查看每一种组合的 7462 排名表。 http://www.sendspace.com/file/pet0dd

然后,对于我制作的这张 7462 表,对于每 7 张卡片,您将获得 21 个不同的排名。 21个组合中排名最高的就是你想知道的那个。

了解表格:在每一行中,您都有 5 张牌(Z 表示同花,Y 表示非同花),并且您有它的排名。那只是你需要的。我给你表格和一个示例算法。这不是真正的代码。它是视觉基本格式,我现在就写了。可能不起作用,但你应该明白。代码是这样的:

'############### 1st: Define your hand, for example "2c2d2h2s3c3h3s" #############################################################################################

Dim mycard As New ArrayList

mycard(1).Add("2c")
mycard(2).Add("2d")
mycard(3).Add("2h")
mycard(4).Add("2s")
mycard(5).Add("3c")
mycard(6).Add("3h")
mycard(7).Add("3s")
mycard.Sort() '################# you need to sort in alphabeticall order to match it later with 7462 table #############################################



' ################## 2nd: Let´s transform it to every kind of 5 cards combinations (21). It will also preserve the alphabeticall order ##################################

Dim myHand5 As String = ""
Dim suited as String = ""
Dim ranking as Integer = 0
Dim myranking as Integer = 7462
Dim mystring as String = ""

For cicle1 = 0 to 2
     For cicle2 = cicle1 + 1 to 3
          For cicle3 = cicle3 + 1 to 4
               For cicle4 = cicle3 + 1 to 5
                    For cicle5 = cicle4 + 1 to 6
                         myhand5 = left(mycard(cicle1),1) & left(mycard(cicle2),1) & left(mycard(cicle3),1) & left(mycard(cicle4),1)  & left(mycard(cicle5),1)
                         suited = left(mycard(cicle1),2) & left(mycard(cicle2),2) & left(mycard(cicle3),2) & left(mycard(cicle4),2)  & left(mycard(cicle5),2)
                         if suited = "ccccc" or suited = "ddddd" or suited = "hhhhh" or suited = "sssss" then myhand5 = myhand5 & "Z" Else myhand5 = myhand5 & "Y"  
                          ranking = 0                              
                          FileOpen (1, "7462.txt", Input)
                          Do
                               ranking = ranking + 1
                               Input(1, mystring)
                               Input(1, ranking)
                               If mystring = myhand5 Then 
                                    If ranking < myranking then myrankin = ranking
                               End If
                          Loop Until EOF(1)
                          FileClose(1)
                    Next cicle5
               Next cicle4
          Next cicle3
     Next cicle2
Next cicle1

最终排名是 myranking 变量。你应该在不到一秒钟的时间内就知道你的手。并且也很好与其他手比较,因为你有排名值而不是它的名字。如果你想用扑克算法做点什么,这就是你应该开始的地方。有了排名值,一切都变得简单快捷。

注意:我不是程序员。我是一个想成为的人。我了解一些视觉基本功能。我希望我知道如何制作真正的程序。如果算法有效,请发表评论。如果您希望它非常非常快,我不知道该怎么做。我希望我有一个超快速的算法,可以让我(实时)检查我在比赛的每个阶段与任何对手的赔率。我尝试了很多算法来实时计算我在翻牌圈的赔率,但我能做到的最快是 30 秒。现在,我可以在 3 秒内计算出我在翻牌圈的赔率,但我使用的是一个 150 GB 的数据库,其中很多东西都是预先计算好的。如果您想实时了解您的赔率,您应该预先计算很多事情。我就是这样做的。

【讨论】:

    【解决方案6】:

    我在 C here 中为扑克评估员创建了一个测试平台。在我测试的评估器中,poker-eval 库是赢家。 Steve Brecher's Holdem Showdown 也非常快,内存需求也明显减少。我自己的ACE_Eval 拥有它自己的。

    我欢迎帮助添加其他评估者,以及来自其他机器的测试结果的贡献。

    【讨论】:

    • 我仔细查看了 Steve Brecher 的评估器,但我很难从他的 0x0V0RRRRR 评估结果中提取卡片值。您能否在基准测试的 BHS 部分添加更详细的解码器?
    • 我会尽量做到这一点,但与此同时:最多有 5 个“R”半字节,其中0..C 代表“2”..“Ace”。它们代表构成手牌等级的牌的价值。尾随 0s 被忽略。您需要查看排名以确定要提取多少值。因此,对于带有 7 个底牌的 4 个 A,您将拥有 C5000。对于超过 3s 的满屋 K,您将获得 B1000。两对,8s 和 4s 和一个 Q 踢球者是62A00。等等。高牌手将使用所有 5 个半字节。 ACE_Eval.h 使用类似的表示。请参阅ACE_decode() 了解获得获胜卡片的一种方法。
    【解决方案7】:

    当然,如果你想做得很快。我之前放的算法太慢了。

    table7462 应该在数组中,而不是在文件中。

    然后,您应该预先计算每张不同的 7 张牌并将其存储到数据库中。有 133.784.560 种不同的 7 牌组合。

    您应该使用这种格式(按字母顺序):

    “2c2d2h2s3c3d3h”并对其进行排名

    存储每 133.784.560 个不同的组合。你做 52C7 cicles,对其进行排序并将其存储在数据库中。 也许几天后你就准备好了。 准备好后,您不再需要 21 种组合,只需按字母顺序排列并在数据库中搜索即可。

    如果您这样做,您会发现您可以在需要时实时计算与对手的赔率。

    相信我。我不是程序员,我可以做到。我在 3 秒内就知道我在翻牌圈的赔率。

    【讨论】:

      【解决方案8】:

      我开发了一个模拟器德州扑克,在此​​开发过程中,我发现翻牌圈有 7462 种独特组合(52 - 5/5 张牌)。反过来,这个数字下降到 6075 (5/6),在河牌圈下降到 4824 (5/7)。这是因为 1 或 2 张牌与扑克手的分类无关。一个例子是: 76543QK = 7654332 顺子(3比7)

      我的模拟器名为 Easy Poker,可在我的网站 http://crvltda.webs.com 上找到

      参考。 Pokersoftware.com/forum

      【讨论】:

        【解决方案9】:

        我可以推荐https://github.com/chenosaurus/poker-evaluator/

        它是用 JavaScript 编写的,使用 128 MB HandRanks.dat 文件。

        代码只有几行,很容易移植到任何其他语言。

        【讨论】: