Pregunta

Tengo un algoritmo para calcular si la mano de un jugador mantiene una recta en Texas Hold'em. Funciona bien, pero me pregunto si hay una forma más simple de hacerlo que no implique conversiones de matriz/cadena, etc.

Aquí hay una versión simplificada de lo que tengo. Digamos que el jugador recibe una mano que es una matriz de valores de tarjetas de 52 elementos:

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

A 1 representa una tarjeta en ese ranura de valor. La mano anterior tiene un clubes de 2, sin diamantes, un corazón de 3 corazones, 4 corazones y 6 corazones, un espado de 5 y 10 pisos. Ahora lo miro para encontrar una recta.

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);

El truco aquí es o los diversos trajes, por lo que solo hay una representación de 2 a ACE. ¿Me equivoco al pensar que debe haber una forma más simple de hacer esto?

¿Fue útil?

Solución

Casi todo el trabajo que realiza su código es escribir la conversión. Si acaba de almacenar la mano en formato de bits para comenzar (necesidades> de 32 bits), podría hacer algo como:

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;

El equivalente usando un bucle de una línea sería:

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

Esto es mucho más corto y más fácil de entender.

La conversión hacia y desde una representación de bits requiere más código y tiempo de CPU de lo que guarda utilizando el operador o el operador.

Otros consejos

Bueno, una recta debe incluir un 5 o un 10, por lo que puede comenzar arrojando la mano si no tiene una u otra:

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
}

Puede usar un valor entero como un campo de bit para los valores de la tarjeta, ACE obtiene dos puntos de bajo y alto. Luego se compara con el final bit a bit con las diez rectas posibles.

O use un for -bucle y verifique por cinco números consecutivos, efectivamente es todo lo mismo.

Esta pregunta me interesó. Terminé yendo por la borda. Y escribió una página web para calcular cualquier mano. Probablemente no sea el más eficiente, pero funciona. Hice esto con Just JavaScript (sin jQuery). Aquí hay un manifestación http://jsbin.com/izuto4/2/

A continuación se muestra el código:

<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, eso es tan simple como se vuelve. Miré en la evaluación de la mano del póker hace un tiempo, y creo que la forma más rápida utiliza un enfoque como el suyo. Ver el primer resultado en este sitio. Utiliza operaciones bit a bit para calcular las manos.

EDITAR: Por primer resultado, me refiero a "PokerSource Poker-Eval Evaluator".

¿Por qué no ordenar las cartas por rango, y luego verificar que cada rango sea uno más que el anterior? "Rangos" es una matriz de longitud 5 con ACE = 1, 2 = 2, ... j = 11, q = 12, k = 13. Creo que esto es más simple que los otros métodos presentados aquí.

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]);
}

Puede usar los evaluadores de 7 cartas y 5 cartas de Specialk publicados aquí Y pídale que clasifique las manos. Si el rango que se devuelve es entre 5854 y 5863 (ambos inclusivos) o entre 7453 y 7462 (ambos inclusive), entonces su mano, ya sea de 5 o 7 cartas, respectivamente o contiene una recta.

Tenga en cuenta que el as de espadas se denota por 0, el as de corazones por 1, hasta los dos clubes que está representado por 51. El algoritmo "agregará" sus cartas y buscará el rango en una mesa pequeña, tomando 9 MB de RAM. También hará mucho más, pero oye ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top