алгоритм — PHP Получение всех уникальных результатов игры за покер

В настоящее время я пытаюсь создать покерный алгоритм, который определяет вероятность выигрыша руки. Он должен быть очень быстрым, потому что каждый раз придется проходить через сотни тысяч разных рук.

То, что я изо всех сил пытаюсь сделать, — это иметь возможность собрать все уникальные руки, которые могли бы появиться на доске. Доска содержит 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 рук. Это очень медленно для моего алгоритма.

Мне просто интересно, есть ли у кого-то лучшая идея перебрать возможные доски.

Сохранение значений платы в массиве и последующее тестирование, чтобы увидеть, находится ли значение карты в списке, все еще очень медленное. Есть ли способ зацикливания только через уникальные комбинации досок?

1

Решение

То, что вы делаете, в принципе нормально, но вместо итерации от 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());
2

Другие решения

создать массив со всеми картами, из которых можно вытащить карты

создать пустой массив для уже использованных карт

при получении карты из массива со всеми картами добавьте ее во второй массив и удалите ее из массива кулаков (не задано), чтобы вы не могли выбрать ее снова …

$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

Таким образом, $ selected_card имеет только неиспользованные карты в любое время, а $ known_cards имеет все уже взятые карты.

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);
0
По вопросам рекламы [email protected]