Domanda

Ho un algoritmo per calcolare se la mano di un giocatore tiene una dritta in Texas Hold'em. Funziona bene, ma mi chiedo se esiste un modo più semplice per farlo che non coinvolga conversioni di array/stringa, ecc.

Ecco una versione semplificata di ciò che ho. Supponiamo che il giocatore venga distribuito una mano che è una serie di valori delle carte a 52 elementi:

var rawHand = [1,0,0,0,0,0,0,0,0,0,0,0,0, //clubs
               0,0,0,0,0,0,0,0,0,0,0,0,0, //diamonds
               0,1,1,0,1,0,0,0,0,0,0,0,0, //hearts
               0,0,0,1,0,0,0,0,1,0,0,0,0];//spades

Un 1 rappresenta una scheda in quella slot di valore. La mano sopra ha 2-club, senza diamanti, a 3 heart, a 4 u metri e 6 ore, un 5-pades e un 10-pades. Ora lo guardo per trovare un dritto.

var suits = []; //array to hold representations of each suit

for (var i=0; i<4; i++) {
    var index = i*13;
    // commenting this line as I removed the rest of its use to simplifyy example
    //var hasAce = (rawHand[i+13]);

    //get a "suited" slice of the rawHand, convert it to a string representation
    //of a binary number, then parse the result as an integer and assign it to
    //an element of the "suits" array
    suits[i] = parseInt(rawHand.slice(index,index+13).join(""),2);
}

// OR the suits    
var result = suits[0] | suits[1] | suits[2] | suits[3];

// Store the result in a string for later iteration to determine
// whether straight exists and return the top value of that straight
// if it exists; we will need to determine if there is an ace in the hand
// for purposes of reporting a "low ace" straight (i.e., a "wheel"),
// but that is left out in this example
var resultString = result.toString(2);

//Show the result for the purposes of this example
alert("Result: " + resultString);

Il trucco qui è o i vari semi, quindi c'è solo una rappresentazione da 2-a-ACE. Ho torto nel pensare che ci deve essere un modo più semplice per farlo?

È stato utile?

Soluzione

Quasi tutto il lavoro svolto dal codice è la conversione del tipo. Se hai appena memorizzato la mano in formato bitu

var mask = 2^13 - 1; // this will zero out all but the low 13 bits
var suits = (rawHand | rawHand>>13 | rawHand>>26 | rawHand>>39) & mask;

L'equivalente usando un ciclo di una linea sarebbe:

var suits = [];
for(var i=0; i < 13; i++) {
   suits[i] = rawHand[i] || rawHand[i+13] || rawHand[i+26] || rawHand[i+39];
}

Questo è molto più breve e più facile da capire.

La conversione da e verso una rappresentazione di un po 'richiede più codice e tempo della CPU rispetto a quello che si risparmia utilizzando il bit o l'operatore.

Altri suggerimenti

Bene, un dritto deve includere un 5 o un 10, quindi puoi iniziare gettando la mano se non ne ha una o l'altra:

if (rawHand[3] || rawHand[16] || rawHand[29] || rawHand[42] ||
    rawHand[8] || rawHand[21] || rawHand[34] || rawHand[47]) {
  // do some more checks
} else {
  // not a straight
}

È possibile utilizzare un valore intero come bitfield per i valori della carta, Ace ottiene due punti bassi e alti. Quindi si confronta con Bitwise End con i dieci possibili rettilinei.

Oppure usa un ad anello e controlla cinque numeri consecutivi - in effetti è lo stesso.

Questa domanda mi ha interessato. Ho finito per andare in mare. E ha scritto una pagina web per calcolare qualsiasi mano. Probabilmente non è il più efficiente ma funziona. L'ho fatto con Just JavaScript (senza jQuery). Ecco un Demo http://jsbin.com/izuto4/2/

Di seguito è riportato il codice:

<html>
<head>
<script>
   // var myrawHand = [1,0,0,0,0,0,0,0,0,0,0,0,0, //clubs
   // 0,0,0,0,0,0,0,0,0,0,0,0,0, //diamonds
   // 0,1,1,0,1,0,0,0,0,0,0,0,0, //hearts
   // 0,0,0,1,0,0,0,0,0,0,0,0,0];//spades

    function getCardsInHand(rawHand) {
        var cardsInHand = new Array();
        var counter = 0;
        for (var i = 0; i < rawHand.length; i ++) {
            if (rawHand[i]) {
                cardsInHand[counter] = i;
                counter ++;
            }
        }
        return cardsInHand;
    }

    function cardsfiltered(rawHand) {
        var cards = getCardsInHand(rawHand)

        var cardsfiltered = new Array();
        for (var j = 0; j < cards.length; j ++){
            cardsfiltered[j] = cards[j] - (parseInt(cards[j] / 13) * 13);
        }
        cardsfiltered.sort();
        return {cards : cards, cardsfiltered : cardsfiltered};
    }

    function whatIsMyHand(rawHand) {
        var cardObject = cardsfiltered(rawHand);
        if (((cardObject.cards[0] == 0 && cardObject.cards[1] == 9)
                || (cardObject.cards[0] == 13 && cardObject.cards[1] == 22)
                || (cardObject.cards[0] == 26 && cardObject.cards[1] == 35)
                || (cardObject.cards[0] == 39 && cardObject.cards[1] == 48))
                && cardObject.cards[4] == cardObject.cards[3] + 1 &&
                cardObject.cards[3] == cardObject.cards[2] + 1 &&
                cardObject.cards[2] == cardObject.cards[1] + 1) {
            return "Royal Flush";
        }
        else if (cardObject.cards[4] == cardObject.cards[3] + 1 &&
                cardObject.cards[3] == cardObject.cards[2] + 1 &&
                cardObject.cards[2] == cardObject.cards[1] + 1 &&
                cardObject.cards[1] == cardObject.cards[0] + 1) {
            return "Straight Flush";
        }
        else if ((cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2]
                && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3])
                && (cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1]
                || cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) {
            return "Four of a Kind";
        }
        else if ((cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1]
                && cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2]
                && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])
                || (cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1]
                && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3]
                && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) {
            return "Full House";
        }
        else if (parseInt(cardObject.cards[0] / 13) == parseInt(cardObject.cards[1] / 13)
                && parseInt(cardObject.cards[0] / 13) == parseInt(cardObject.cards[2] / 13)
                && parseInt(cardObject.cards[0] / 13) == parseInt(cardObject.cards[3] / 13)
                && parseInt(cardObject.cards[0] / 13) == parseInt(cardObject.cards[4] / 13)) {
            return "Flush";
        }
        else if ((cardObject.cardsfiltered[4] == cardObject.cardsfiltered[3] + 1
                && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[2] + 1
                && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[1] + 1
                && cardObject.cardsfiltered[1] == cardObject.cardsfiltered[0] + 1)
                || (cardObject.cardsfiltered[0] == 0
                && cardObject.cardsfiltered[1] == 10
                && cardObject.cardsfiltered[2] == 11
                && cardObject.cardsfiltered[3] == 12
                && cardObject.cardsfiltered[4] == 9)) {
            return "Straight";
        }
        else if ((cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1]
                && cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2])
                || (cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2]
                && cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3])
                || (cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3]
                && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) {
            return "Three of a Kind";
        }
        else if ((cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1]
                && (cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3]
                || cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4]))
                || (cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2]
                && cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4])) {
            return "Two Pair"
        }
        else if (cardObject.cardsfiltered[0] == cardObject.cardsfiltered[1]
                || cardObject.cardsfiltered[1] == cardObject.cardsfiltered[2]
                || cardObject.cardsfiltered[2] == cardObject.cardsfiltered[3]
                || cardObject.cardsfiltered[3] == cardObject.cardsfiltered[4]) {
            return "Pair";
        }
        else {
            return "High Card";
        }
    }
    var CardCheckCount = 0;
    function MaxCardCheck(element) {
        if (element.checked) {
            if (CardCheckCount < 5) {
                CardCheckCount++;
                return true;
            }
        }
        else {
            CardCheckCount--;
            return true;
        }
        element.checked = !element.checked;
        alert("You can only pick 5 cards.");
        return false;
    }

    function calculateHand() {
        var checkboxes = document.getElementsByTagName("input");
        var myrawHand = new Array();
        for (var i = 0, element; element = checkboxes[i]; i++) {
          myrawHand[parseInt(element.name)] = element.checked ? element.value : 0;
        }
        alert(whatIsMyHand(myrawHand));
    }
</script>
</head>
<body>
<table>
    <thead>
        <tr>
            <td>&nbsp;A</td>
            <td>&nbsp;2</td>
            <td>&nbsp;3</td>
            <td>&nbsp;4</td>
            <td>&nbsp;5</td>
            <td>&nbsp;6</td>
            <td>&nbsp;7</td>
            <td>&nbsp;8</td>
            <td>&nbsp;9</td>
            <td>10</td>
            <td>&nbsp;J</td>
            <td>&nbsp;Q</td>
            <td>&nbsp;K</td>
            <td>&nbsp;</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><input name="0" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="1" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="2" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="3" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="4" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="5" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="6" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="7" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="8" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="9" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="10" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="11" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="12" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td>Clubs</td>
        </tr>
        <tr>
            <td><input name="13" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="14" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="15" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="16" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="17" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="18" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="19" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="20" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="21" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="22" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="23" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="24" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="25" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td>Diamonds</td>
        </tr>
        <tr>
            <td><input name="26" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="27" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="28" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="29" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="30" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="31" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="32" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="33" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="34" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="35" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="36" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="37" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="38" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td>Hearts</td>
        </tr>
        <tr>
            <td><input name="39" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="40" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="41" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="42" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="43" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="44" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="45" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="46" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="47" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="48" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="49" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="50" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td><input name="51" type="checkbox" value="1" onclick="MaxCardCheck(this);"/></td>
            <td>Spades</td>
        </tr>
    </tbody>
</table>
<button onclick="calculateHand()">Calculate Hand</button>
</body>
</html>

No, è così semplice come si ottiene. Ho esaminato la valutazione delle mani del poker qualche tempo fa e penso che il modo più veloce usi un approccio come il tuo. Vedere il primo risultato in questo sito. Utilizza operazioni bitwise per calcolare le mani.

EDIT: per primo risultato, intendo "valutatore di poker poker-poker-evali".

Perché non ordinare le carte per rango, e quindi controllare che ogni grado sia uno più del precedente. I "ranghi" sono un array di lunghezza 5 con ace = 1, 2 = 2, ... j = 11, q = 12, k = 13. Penso che questo sia più semplice degli altri metodi presentati qui.

function isStraight( ranks) {
  ranks.sort();
  return (ranks[0] + 1 == ranks[1] || (ranks[0] == 1 && ranks[4] == 13)) &&
         (ranks[1] + 1 == ranks[2]) &&
         (ranks[2] + 1 == ranks[3]) &&
         (ranks[3] + 1 == ranks[4]);
}

È possibile utilizzare i valutatori a 7 carte e 5 carte di Specialk pubblicati pubblicati qui E chiedi di classificare le mani. Se il rango che viene restituito è compreso tra 5854 e 5863 (sia inclusivi) o tra 7453 e 7462 (entrambi inclusi), quindi la tua mano, che si tratti di 5 o 7 carte, rispettivamente è o contiene una dritta.

Nota che l'asso di picche è indicato da 0, l'asso dei cuori di 1, attraverso i due club che è rappresentato da 51. L'algoritmo "aggiungerà" le tue carte e cercherà il grado in un piccolo tavolo, occupando 9 MB di RAM. Farà anche molto di più, ma hey ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top