2010-10-23 7 views
5

Tengo un algoritmo para calcular si la mano de un jugador tiene una escalera en Texas Hold'em. Funciona bien, pero me pregunto si hay una manera más simple de hacerlo que no involucre matrices/cadenas de conversión, etc.¿Hay una manera más simple que esto de calcular una escalera en el póker?

Aquí hay una versión simplificada de lo que tengo. Digamos que el jugador recibe una mano que es una matriz de 52-elemento de valores de las cartas:

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 la que la ranura de valor. La mano de arriba tiene 2 palos, sin diamantes, 3 corazones, 4 corazones y 6 corazones, 5 palas y 10 palas. Ahora lo miro para encontrar una escalera.

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 para los diversos trajes por lo que solo hay una representación de 2 a As. ¿Me equivoco al pensar que debe haber una forma más simple de hacer esto?

+2

Parece bastante simple para mí, ¿cuánto más simple crees que podría ser? Con el fin de detectar la rueda, simplemente insertaría una copia del último elemento de cada conjunto de trajes en la parte delantera de la matriz antes de juntarlos. Luego puede buscar el resultado de la cadena para '11111'. –

+0

podría ser más rápido con el uso de un revés while/for loop 'for (var i = 3; i -;) {...}' – vol7ron

+0

@Larry Lustig: Es la línea de análisis que yo pensaba que podría ser más simple. Ya sabes, como en "tal vez si fuera mejor en esto, no tendría que convertir a una matriz => cadena => int y luego volver a una cadena" ... – Robusto

Respuesta

2

Casi todo el trabajo que hace su código es conversión de tipos. Si acaba almacenada la mano en formato de bits, para empezar (necesita> 32 Tipo de bits), se 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 utilizando 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 bit a bit toma más código y tiempo de CPU de lo que ahorra al usar el operador O bit a bit.

+0

Gracias, esto tiene sentido. – Robusto

2

Bueno, una escalera debe incluir un 5 o un 10, por lo que puede empezar por tirar la mano si no tiene uno u otro:

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 
} 
1

No, eso es casi tan simple como consigue. Analicé la evaluación de mano de póquer hace un tiempo, y creo que la forma más rápida utiliza un enfoque como el tuyo. Vea el primer resultado en this site. Utiliza operaciones a nivel de bit para calcular las manos.

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

+0

más rápido! = Más simple – vol7ron

+0

Cierto, pero es eso método no simple? No puedo pensar en nada más simple. Por cierto, este método es casi exactamente el mismo al que hace referencia Elko en su respuesta. –

2

Puede usar un valor entero como un campo de bits para los valores de la tarjeta, ace obtiene dos puntos bajo y alto. Luego se compara con bitwise end contra las diez posibles rectas.

O utilice un bucle for y compruebe cinco números consecutivos: de hecho, es lo mismo.

2

Esta pregunta me ha interesado. 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 solo con JavaScript (sin jQuery). Aquí es un demohttp://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> 
0

Por qué no ordenar las cartas por rango, y luego verifique que cada rango es 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]); 
} 
0

Puede utilizar 7-cartas y 5 cartas de evaluadores SpecialK publicado here y pedirle que para clasificar las manos. Si el rango que se devuelve está entre 5854 y 5863 (ambos inclusive) o entre 7453 y 7462 (ambos inclusive), entonces su mano, ya sea de 5 o 7 cartas, respectivamente es o contiene una escalera.

Tenga en cuenta que el As de Picas se denota por 0, el As de Corazones por 1, hasta el Dos de Tréboles que está representado por 51. El algoritmo "agregará" sus cartas y buscará el rango en un pequeño tabla, ocupando 9MB de RAM. También hará mucho más, pero bueno ...

Cuestiones relacionadas