PHP获取扑克的所有唯一板结果


PHP Getting all unique board results for poker

我目前正在尝试制作一个扑克算法来确定赢得一手牌的机会。它需要非常快,因为它每次都要遍历成千上万个不同的指针。

我正在努力做的是能够得到所有可能出现在棋盘上的独特手牌。棋盘上有5张牌。

每当一张牌出现在棋盘上,那张牌不能再出现。

所以我一直在做什么来获得所有可能的棋盘组合是循环通过所有可能的结果使用for循环。

在这个例子中,我将只获得前3张牌。

代码是这样的:

// $card_set_count is the amount of cards left in the deck after taking away the
// user's hand cards.
for($i=0;$i<$card_set_count;$i++) {
    // First known card
    $known_card1 = $card_set[$i];
    for($j=0;$j<$card_set_count;$j++) {
        // Second known card
        $known_card2 = $card_set[$j];
        // Skip the card if we already have it out
        if($known_card1 == $known_card2) continue;
        for($k=0;$k<$card_set_count;$k++) {
            // Third Known Card
            $known_card3 = $card_set[$k];
            // Skip card if the card is already out
            if($known_card3 == $known_card2 || $known_card1 == $known_card3) continue
            // Create board
            $board = array();
            $board[] = $known_card1;
            $board[] = $known_card2;
            $board[] = $known_card3;
        }
    }
}

这确实得到了我所有可能的棋盘组合。唯一的问题是它也让我重复的值,例如板:

Ad 6d 4c

相同

4c Ad 6d

我可以在我的棋盘列表上运行array_unique(),但是这里的问题是我的forloop必须循环91020手。这对我的算法来说太慢了。

我只是想知道是否有人有更好的想法通过可能的板循环。

将板值存储在数组中,然后测试以查看卡值是否在列表中仍然非常缓慢。是否存在一种只通过独特的棋盘组合进行循环的方法?

你所做的基本上是可以的,但不是每次从0迭代到$card_set_count,第二张牌应该只从第一张牌之后的牌中取出,第三张牌应该只从第二张牌之后的牌中取出,像这样:

for($i=0;$i<$card_set_count - 2;$i++) {
    for($j=$i + 1;$j<$card_set_count - 1;$j++) {
        for($k=$j + 1;$k<$card_set_count;$k++) {
            $board = array();
            $board[] = $card_set[$i];
            $board[] = $card_set[$j];
            $board[] = $card_set[$k];
            // evaluate hand ...
        }
    }
}

在包中剩下50张牌,那就有19600种组合。你可以进一步修剪这些组合,因为对于某些手牌,花色并不重要,但这可能会变得非常复杂。


一开始我误解了你的问题,给出了下面的答案,这并不能完全解决你的具体问题。我没有删除它,因为它已经得到了一个赞,所以显然有人觉得它很有用。

创建一个包含所有卡片的数组。创建一个变量,其中包含剩余的卡的数量:cardsLeft = 52。然后,当需要取牌时,从第1张卡到第52张卡中随机选择,将选中的卡牌与第52张卡互换,设cardsLeft为51。下一张牌,从1号牌到51号牌中选择,与51号牌交换,将cardsLeft设置为50,以此类推…
当你需要用新牌组开始新游戏时,只需将cardsLeft重置为52。不需要重新初始化或打乱数组。

我已经好几年没用过php了,但这里有一个Javascript的例子;这是不言而喻的。运行代码片段为三个玩家绘制扑克手牌(请参阅控制台中的输出)。

function Deck() {
    this.cards = [];
    this.left = 52;
    for (var suit = 0; suit < 4; suit++) {
        for (var number = 0; number < 13; number++) {
            this.cards.push("23456789TJQKA".charAt(number) + "cdhs".charAt(suit));
        }
    }
}
Deck.prototype.draw = function() {
    if (this.left == 0) this.shuffle();
    var pick = Math.floor(Math.random() * this.left);
    var swap = this.cards[pick];
    this.cards[pick] = this.cards[--this.left];
    this.cards[this.left] = swap;
    return swap;
}
Deck.prototype.shuffle = function() {
    this.left = 52;
}
var d = new Deck();
document.write("player 1: " + d.draw() + "," + d.draw() + "<BR>");
document.write("player 2: " + d.draw() + "," + d.draw() + "<BR>");
document.write("player 3: " + d.draw() + "," + d.draw() + "<BR>");
document.write("flop: " + d.draw() + "," + d.draw()+ "," + d.draw() + "<BR>");
document.write("turn: " + d.draw() + "<BR>");
document.write("river: " + d.draw());

创建一个包含所有卡片的数组

为已使用的卡创建一个空数组

当从数组中获得一张卡片时,将其添加到第二个数组中,并将其从第一个数组中移除(未设置),以便您不能再次选择它…

$chosen_card = array_rand($card_set);      // just choosing a card randomly to simulate whatever way you currently pick one 
$known_cards[] = $card_set[$chosen_card];  // copy the card to the know_cards array
unset($card_set[$chosen_card]);            // remove cards from unused cards

这样,$chosen_card在任何时候都只有未使用的卡片,而$known_cards则都有已经使用的卡片。

如果您只想要已知集合中的所有唯一组合,您可以实现以下算法:

$card_set = [1,2,3,4,5];
$k = 3;
$n = count($card_set);
$combs = [];
$stack = [[[],0,0]];
while (!empty($stack)){
  $params = array_pop($stack);
  $current_hand = $params[0];
  $i = $params[1];
  $len = $params[2];
  if ($len == $k){
    array_push($combs,$current_hand);
  } else {
    if ($i < $n - 1){
      array_push($stack,[$current_hand,$i + 1,$len]);
    }
    if ($i < $n){
      array_push($current_hand,$card_set[$i]);
      array_push($stack,[$current_hand,$i + 1,$len + 1]);
    }
  }
}
print_r($combs);