Poker calcular cartas validas?

Iniciado por @XSStringManolo, 12 Julio 2019, 19:14 PM

0 Miembros y 1 Visitante están viendo este tema.

@XSStringManolo

La única forma que se me ocurre es haciendo arrays con las posibles convibaciones, pero sería una locura hacer un array para cada convinación posible. Tiene quer haber alguna forma de saber que cartas me sirven.

Mi idea es pedir al usuario sus cartas y las cartas en la mesa, y que me de todas las combinaciones posibles relevantes y su porcentaje de obtener cada convinación.
No se me ocurre como hacerlo sin tirarme semanas escribiendo combinaciones a mano xD

El programa debería ser en plan:
Dime las cartas de tu mano:
Trebol1, Picas1

Tienes pareja de ases.
Introduce apuesta en la mesa.
La apuesta son 20$ recomendado ver 10 a 1.

PrimeraCartaDestapada = Corazones5;

CartasRestantesEnElMazo = 40;

Manos posibles:
Escalera Real: 0'00%
...
...
Poker: 0'008%
Corazones1 0'02%
Rombos1 0'02%

Trio: 0'04%
Corazones1 0'02%
Rombos1 0'02%


Posibilidad media de ganar: 73%
Odds de bote: 27%
Recomendado:
Subir 24€


Como podría obtener automáticamente las cartas que me sirven?
Por ejemplo si tengo Picas1, Trebol1 y en la mesa hay Corazones1, PicasRey. Como calculo las cartas validas tipo:
Cartas que sirven:
Poker: Rombos1
FullHouse: CorazonesRey, RombosRey, TrebolRey.
Escalera: ...
Dobles Parejas: ...
Parejas: ...
Cartas Inútiles...

CartasMazo = 40
CartasValidasEnMazo = 22
CartasInvalidasEnMazo = 18

Probabilidades de poker: 0'008%
Probabilidades de ganar con poker: 97'63%

Probabilidades de FullHouse 0'1%
Probabilidades de ganar con FullHouse: 94'78%

.......

Probabilidades de sacar una mano con más 90%winrate = 0'12%

Probabilidad final de victoria = 73%
...

Markski

Hace aprox. un año o año y medio tuve un problema similar (pero no tan ambicioso como el tuyo), y encontré el siguiente articulo muy útil (lamentablemente está en inglés): http://www.pokerology.com/lessons/math-and-probability/

@XSStringManolo

Ando mirando juegos de poker de codigo abierto y tratare de desarrollarlo con algoritmos matemáticos, si no, me va a ser imposible. Hay cerca de 2 millones o billones de combinaciones posibles. He estado mirando varias páginas como la que me linkeas junto con la wikipedia de probabilidades de poker, poker, etc.

La otra opción sería hacer una IA que aprenda jugando, pero sin tener un mínimo de algoritmos para comprobar los resultados poco puedo hacer. Tengo que meditar bastante sobre como hacer los algoritmos hasta que se me ilumine la bombilla.

fzp

#3
CitarLa única forma que se me ocurre es haciendo arrays con las posibles convibaciones, pero sería una locura hacer un array para cada convinación posible. Tiene quer haber alguna forma de saber que cartas me sirven.

Se me ocurre una idea, pero muy general y sin detallar. Habría que verla despacio y pensando bien. Sería lo siguiente. Si una carta la representas con dos caracteres, por ejemplo el primero el palo, del 0 al 3, o 'T,D,C,P', y la carta con otro carácter por ejemplo, 1,2,3,4,5,6,7,8,9,0,J,Q,K, con 1 = As y 0 = 10. Con esa convención una mano de cinco cartas podría representarse con un arreglo de 10 caracteres, por ejemplo:
{D,4,D,J,T,A,P,6,C,2} sería una mano de:
- el 4 de diamantes: D4
- la J de diamantes: DJ
- el As de tréboles: TA
- el 6 de picas: P6
- el 2 de corazones: D2

Ahora se podría construir un algoritmo que leyese los caracteres del arreglo, los pares, 0,2,4,6,8 serían el palo, y los impares 1,3,5,7,9 serían la carta. Y leyendo las repeticiones de cartas se obtendrían las parejas, trios,...; o las sucesiones válidas, 2,3,4,5,6, etc,  las escaleras. Igual con los palos, si hay cinco repeticiones de C sería como minimo un 'color' de corazones, ya viendo su hay una sucesión válida de cartas podría ser una escalera de color.

El algoritmo tendría su trabajillo pero desde luego nada que ver con escribir todas las combinaciones posibles, cosa que, me temo sería imposible.

También te dejo este enlace por si te puede ser útil. Yo me he bajado el texto, pero ún no lo he leído; pero tiene buena pinta.
https://openlibra.com/es/book/desarrollando-con-java-8-poker

EDITO:
Es mala idea usar para las cartas esos caracteres. Mejor usar enteros. Eso sí, como se son enteros pequeños se pueden usar char, pero no por su valor de signo ('1'...'J'...'K') sino por su valor numérico. Mejor usar los valores enteros 1,2,.., 10, 11, 12, 13. Con independencia de que al representar en pantalla el 12 sea la "Q", el 13 el"K", el 1 el"A". Pero internamente usar sus valores numéricos.

Así el algoritmo para detectar escaleras sería mucho más fácil. Sólo habría que comprobar que a partir de la tercera carta, la carta fuese el entero anterior + 1. Por ejemplo que fuesen 4-5-6-7. Y después comprobar dos condiciones alternativa (OR):  que el valor de la segunda carta fuese también = al valor de la primera +1 (en este caso 3) o que la primera carta fuese el entero 1; ya que en póker el As abre cualquier escalera. Así se detectarían las dos posibles escaleras:
3-4-5-6-7
A-4-5-6-7

Y luego para determinar cual escalera gana a otras habría que codificar varias cosas:
- que entre dos escaleras primero gana la que mayor nº último tenga
- que entre dos escaleras que terminan en el mismo nº gana aquella que NO empiece por 1 (la 6-7-8-9-10 gana a la A-7-8-9-10)
- que la escalera 1-10-11-12-13 (A-10-J-Q-K) gana a cualquier otra, ya que en realidad es la
(10-J-Q-K-A)

También para los palos quizá fuera mejor usar enteros 0-3 o 1-4 mejor que los caracteres T,D,C,P ya que -quizá- pudiera construirse algún algoritmo basado en un for  mejor que comparar con las letras correspondientes. A lo mejor también puede construirse un switch-case, con lo que daría igual usar las letras. Como digo esto son comentarios generales. Una vez puesto a la faena ya se  verá qué puede ser más conveniente o eficiente. Es sólo por sugerir una vía sin precisar demasiado.

Serapis

#4
No estoy seguro de haberte entendido del todo...

No solo no es mala idea obtener por combinatoria todas las manos, si no que es mucho más eficaz ya que reduce sensiblemente el análisis de cada mano, las funciones de verificación se resumen en 3 o 4 muy simples.
De hecho es lo que yo haría, pero con dos indicaciones que fijan y minimizan el problema:
* Solo para las manos que retienen un valor. De este modo cada mano se asocia a un hash, el resto solo manteienen el valor (negativo) de la carta más alta, HASH = 0)
* El cálculo del hash se divide en dos pasos (cuando se encuentra una posible mano). En el paso 1, se simplifica el cálculo al no considerar palos-color. Si se localiza es una mano (se considera potencialmente de momento), la segunda fase determina si cumple los requisitos de color siendo que esa figura lo exija, si no lo cumple se descarta (por ejemplo con un valor negativo (menos 13)).
Esto simplifica enormemente el análisis a base de una preparación inicial (y única) y la división en dos partes permite que el número de combinaciones resultantes sea totalmente asequibles.

El hash podría calcularse como la multiplicación de valores de cada carta. Dado que el 1, no altera una multiplicación para el caso de calcular el hash, cada carta debería sumar 1 a su valor natural, o bien intermente asignar siempre 1 valor más a cada carta (lo que resulte más transparente y menos costoso, creo que sería lo primero).
Sabiendo el número máximo de cartas que recibe un jugador (pongamos 5) y que el valor más alto es el rey (13+1) pero que solo hay 4 reyes, entonces el hash mas alto sería: 14*14*14*14*13 = 499.408 que es un valor manejable, y por tanto no habría problema en mantener un array (en la banca) de hasta 500.000 donde se guarda que figuras ofrece cada mano. Dicho array por tanto mantiene un valor numérico, conforme asignado conforme a la siguiente enumeración (es un ejemplo, se puede modificar al gusto)

enumeracion figuras
   CARTA_ALTA= 0 // en realidad valor de la carta más alta con signo negativo, pero este es el valor que se guarda en el array
   PAREJA = 2
   TRIO  = 4
   DOBLE_PAREJA = 8 + 2    // tienes doblepareja pero también una sola pareja,
   FULL  = 16 + 8 + 4 + 2               //full, pero también, hay doble pareja, pareja, y trio
   POKER = 32 + 8 + 2    // doblepareja del mismo valor (4 naipes del mismo valor).
   
   COLOR = 64           // 5 cartas del mismo color
   ESCALERA = 128    // 5 cartas consecutivas
   ESCALERA_COLOR = 256 + 128 + 64 // Cinco cartas consecutivas del mismo palo
   ESCALERA_REAL = 512 + 256 + 128 + 64 // escalera de color del 10 al as.
fin enumeracion


Así tu función de hash, podría ser algo como:

entero = Hash(carta1, carta2, carta3, carta4, carta5) // o bien pasar el array de cartas del jugador, con el número de cartas que contiene (habrá juegos con diferente numero de cartas, aunque convencionalmente suelen ser 5).
 entero temp = (carta1 + 1) * (carta2 +1) * (carta3 +1) * (carta4 +1) * (carta5 +1)
 entero resultado = ArrayValor(temp)  // el array precalculado al inicio (una sola vez).
 
   si (resultado = 0)
       Si BuscarColor(carta1, carta2, carta3, carta4, carta5) = false
           devolver (-1 * BuscarValorCartaMasAlta(carta1, carta2, carta3, carta4, carta5)
       sino
           devolver = COLOR  // valor 64, esto puede interesar para decidir el descarte para intentar buscar escalera de color.
       fin si
   Sino
     // en el array cada 'mano cuyo Valor es Dependiente De Color', se el suma 1, así estos son impares...(mayor que 2).
      si ((resultado and 1) = 1)  // )  
           resultado = RevisarSiManoCumpleRequisitosdeColor(resultado, carta1, carta2, carta3, carta4, carta5)
           // si mano cumple resultado podría aumentar el valor, por ejemeplo ante una posible escalera (128), pasa a ser de color (suma 256) y si además es de color investigar si es real (si suma 512).
      fin si
   fin si

   devolver resultado
fin funcion



Jugando con 52 cartas y tomando solo 5 de ellas cada vez, el número de combinaciones posibles es: 52*51*50*49*48 = 311.875.200. Este es el número máximo de combinaciones distintas de manos que existen. Si bien, dado que hay más jugadores y la banca... durante el desarrollo del juego el número de combinaciones posibles se reduce enormemente (dado también las cartas salidas y las que se tienen actualmente).
Por otro lado, como estamos hablando de no considerar en el primer paso, diferencias entre palos. Las combinaciones como hemos dicho anteriormente no alcanzan las 500.000, desde 2*2*2*2*3 = 48 hasta 14*14*14*14*13 = 499.408  (desde poker de ases hasta poker de reyes)
El valor 2*2*2*2*? = POKER (de ases, recuerda que sumamos 1 al valor de cada carta, para que no existan multiplicaciones *1)
Podemos reducir las combinaciones si decidimos no aumentar ese 1 al valor de cada carta a condición de que cuando aparezca un as, se haga más código para identificar parejas, trios y póker, ya que en ese caso las combinaciones quedarían como: 13*13*13*13*12 = 342.732
Ahora bien, 350.000 frente a 500.000 a cambio de simplificar el código, es preferible el array de 500.000.

Así a bote pronto, no he verificado si diferentes productos (a la hora de calcular el hash) de la mano actual de un jugador pueda dar el valor equivalente al de una mano de valor. Que seguramente sea posible, en ese caso habría que minimizar tal posibilidad asignando valores númeriscos distintos a ciertos naipes...

Un forma rápida de verificarlo es calcular las combinaciones, desde 2*2*2*2*3, 2*2*2*2*4...2*2*2*2*14 hasta 14*14*14*14*2, 14*14*14*14*3...14*14*14*14*13, OJO: No se precisan calcular los 311millones, si se pasan siempre las cartas ordenadas de menor a mayor, se eliminan todas las repeticiones (2*2*2*2*3 = 2*2*2*3*2 = 2*2*3*2*2 = 2*3*2*2*2 = 3*2*2*2*2, esta tiene 5 repeticiones, pero si son todos valores distintos, hay hasta 120 repeticiones (1*2*3*4*5)...
...entonces vas desde la combinación 2*2*2*2*3 hasta 13*14*14*14*14,
LUEGO EL TOTAL de combinaciones (a considerar como no repetidas a bulto) SON: (52*51*50*49*48) / (1*2*3*4*5) = 2.598.960
Puesto que hablamos de 350.000 indices sobre un array de 500.000 y hay unas 2'6millones de firmas únicas de manos, es claro que hay valores repetidos con la forma de calcular el hash. Hay que tomar decisiones a la hora de decidir como evitar o diferenciar esas colisiones...

p.d.: Se ha cambiado el signo '+' por el signo '*', donde ponía: (52+51+50+49+48) / (1*2*3*4*5) = 2.598.960, es: (52*51*50*49*48) / (1*2*3*4*5) = 2.598.960, como el propio resultado resume.

Serapis

#5
Acabo de percatarme, que el hilo tiene 2 años, solo que como es del día 25 de julio y estamos a 28 de julio, pareciera que data de hace solo 3 días... en fin.



Dado que el hilo se ha desbloqueado, dejo aquí el fichero que creé para el caso:

Cita de: Serapis en 29 Julio 2021, 00:38 AM
Después de crear todas las combinaciones posibles de manos del poker para barajas de 52 cartas repartiendo 5 cartas, cuando voy a subir el fichero y compartirlo en un hilo, el hilo está cerrado así que lo dejo aquí para cualquier interesado...

Las 52 cartas están representadas por 52 letras (A-Z, a-z), así cada palo está representado por 13 letras.

Descargar desde aquí:
https://www.mediafire.com/file/athvonhxotk6ugu/Todas_las_manos_del_p%25C3%25B3ker_-_2.598.960.zip/file  5'93Mb. comprimido, 17'3Mb. descomprimido.
(como es una página de descarga sin registro caducará con el tiempo, conservaré el fichero en el pc (no sé cuanto tiempo), pero si no es así no cuesta rehacerlo, si no está disponible simplemente avisad...).