我目前正在尝试制作一种能够赢得胜利的扑克算法。它需要非常快,因为它每次都必须遍历成千上万的不同手。
我努力做的就是能够获得可能出现在董事会中的所有独特之手。一块板包含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 :(得分:2)
你正在做的事情基本上没问题,但是每次只能从第一张牌和第三张牌后面的牌中挑选第二张牌,而不是每次从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种组合。你可以进一步修剪这些组合,因为对于某些人而言,这套服装并不重要,但这可能会非常复杂。
起初我误解了你的问题,并在下面给出了答案,但这并没有完全解决你的具体问题。我还没有删除它,因为它已经有了一个upvote,所以有人显然觉得它很有用。
使用所有卡片创建一个数组。创建一个剩余卡片数量的变量: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());
&#13;
答案 1 :(得分:0)
创建一个包含所有卡牌的阵列,以便从
中拔出牌为已使用的卡片创建一个空数组
当从阵列中获取所有卡片的卡片时将其添加到第二个阵列并将其从第一个阵列中移除(未设置),这样您就不能再次选择它了...
$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也可以使用所有卡片。
答案 2 :(得分:0)
如果您只想要已知集合中的所有唯一组合,则可以实现以下算法:
$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);