这个问题已经在这里有了答案:




9年前关闭。






我想建立自己的扑克牌手评估器,但是在特定部分遇到麻烦。

如果两个玩家被发了两张牌,那么剩下的将有48张牌。然后,在德州扑克中,再分发5张可能的社区卡(称为“棋盘”)。我想列举/遍历所有48个选择的5种可能的棋盘组合,并计算玩家A获胜的时间,玩家B获胜的时间以及他们何时并列。

我不确定如何才能系统地遍历每5张卡组合。有人有什么想法吗?卡被表示为类Card的数组,但是如果这样做可以更快的话,我也可以将它们表示为位集。

我正在用Java执行此操作。

非常感谢

最佳答案

(免责声明:我写了一个非常快速的扑克手评估器)



您不希望每次在翻牌前两个玩家之间有对战时就评估C(48,5)(1 712 304)手:大多数程序只是在两个翻牌前所有可能的对决之间使用预先计算的查找表。

例如,假设您拥有“Ac Ad”和“7c 6c”,只需在包含以下内容的查找表中查找:1 333 573, 371 831, 6900(其中1333573是“Ac Ad”获胜的次数,371831是次数“7c 6c”获胜,并且平局数为6 900(它们的总和为1 712 304)。要获得一定的空间,您可以丢弃6 900,因为知道平局数应始终为C(48,5)-(胜1 +胜2)。

(有关此答案末尾的查找表的更多信息)

但是要回答你的问题:



如果您确实想循环遍历每种组合,则必须知道扑克手评估器通常是一种需要非常非常快的程序。这些程序通常每秒可以评估数亿只手(您正确阅读:数亿只手)。

当您需要如此高性能的“数字运算”时,您会忘记“设计模式”和“OO”。您想要的是原始速度。

例如,以下内容将通过最内层的循环C(48,5)次,并且速度非常快:

    for ( int i = 0; i < n; i++ ) {
        for ( int j = i + 1; j < n; j++ ) {
            for ( int k = j + 1; k < n; k++ ) {
                for (int l = k + 1; l < n; l++) {
                    for (int m = l + 1; m < n; m++) {
                        ...
                    }
                }
            }
        }
    }

对于两位翻牌前的玩家来说,这可能是一个非常糟糕的主意:使用查找表,您的速度将会大大提高。

但是对于三位翻牌前的玩家(使用翻牌前的 table 是不切实际的,对战太多),您可能想像这样用五个嵌套循环在C(46,5)手上进行循环(当然,您需要使用i,j,k,l,m从剩下的46张卡中正确提取5张卡)。然后,一旦获得了5张牌,就可以使用快速手牌评估器,从7张中获得最好的成绩(棋盘中的5张+每个玩家的2张)。

关于查找表:

大多数人使用大约169对169的对照表(“Ac Kd”,“As Kh”,“Ad Ks”等都变成“AK offsuit”,并且C(52,2)可能的起始手分为169型起始手)。 Wikipedia文章解释了如何获得169个非等效的起手牌:

http://en.wikipedia.org/wiki/Texas_hold_%27em_starting_hands

当您考虑一只手时,它们是不等价的,但是一旦您进行了第一手与第二手的比较,“169 vs 169”就是一个近似值(说得很好)。

当然,您可以得到更高的评价。只有C(52,2)(给出1326)真正不同的Hold'em起始手,这意味着在现代计算机上建立一个完美的查找表(一点也不近似)是非常实际的(C(1326,2)ain没有那么大),如果您真的需要完美的数字。如果可以近似计算,则使用169 vs 169表(它需要C(169,2)或14196个条目)。

10-02 02:46