Ok, así que estoy haciendo una IA de Texas Hold'em para mi proyecto sénior. He creado los procedimientos de gui y betting/dealing, pero he llegado a la parte donde necesito determinar quién ganó la mano, y no sé cuál es la mejor manera de abordar esto. Estoy usando python por cierto. ATM tengo 2 listas, una para las 7 tarjetas de jugador, una para las 7 tarjetas de computadora. Actualmente todas las cartas se almacenan como una estructura en la lista como {'Number': XX, 'Suit': x}, donde el número es 2-14, el palo es 1-4. La forma en que iba a abordar esto, es hacer una función para cada tipo de mano, empezando por la más alta. P.ej. self.CheckRoyal (playerCards), y repasa manualmente la lista y evalúa si se logró una escalera real. Tiene que haber una forma numérica mejor para hacer esto.Algoritmo para determinar el ganador de una mano de Texas Hold'em
Respuesta
http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup
mejor algoritmo que se obtiene es 7 se ve en la tabla de consulta de tamaño de 100 MB (si no recuerdo mal)
¿Estás hablando del método dos más dos de generar una tabla con 32 millones de entradas y siguiendo un camino basado en tu mano? Si es así, ¿cómo lo adaptaría a Python ya que usa punteros para las funciones? – ULcajun
@ULcajun: el http://pokersource.sourceforge.net/ enumerado en el enlace de arriba tiene enlaces de python. –
Se proporcionan evaluadores menos exigentes y al menos buenos aquí: http://code.google.com/p/specialkpokereval/. También se describe a continuación. – SK9
Monte Carlo? Esa es la primera sugerencia que veo here. Es otro proyecto sénior. Simple y lento, pero de lo contrario probablemente estés viendo una combinatoria complicada de la que no voy a fingir que sé mucho.
El documento al que hace referencia está tratando de resolver un problema mucho más interesante. El interlocutor solo quiere un algoritmo para determinar quién es el ganador de una mano determinada (por ejemplo, flush beats a straight). – dfan
Monte Carlo se usa para encontrar la equidad aproximada de una mano contra otras, simulando millones de juegos de póker. Utiliza el algoritmo que OP quiere :) –
Ah, sí. ¡Correcto eres! He leído con claridad la cuestión demasiado rápidamente y respondió a la pregunta que apareció en mi cabeza, no lo que se pidió ... – Ricky
El método utilizado en la publicación de ralu es de lejos la mejor alternativa que he visto. Usé este método en mi propio proyecto, y es muy rápido.
acantilados:
hacer algo de procesamiento previo, para generar una tabla, que contiene un valor para cada distinta a mano de póquer. Asegúrate de que la mesa esté ordenada a mano.
Cada valor de la tarjeta tiene su correspondiente valor principal. La tabla está indexada por la multiplicación de cada valor de la carta en la mano. Así que para encontrar el valor de la AAAAK lado, se calcula la multiplicación de primera y utilizar esto como índice para la tabla:
int prime = getPrime(hand); // Calculates A.getPrime()...*K.getPrime();
int value = table[prime];
(Lo siento por la sintaxis de Java).
De esta manera, AAAAK es la misma mano que KAAAA, y no necesita una mesa de 5 dim.
Tenga en cuenta que tiene que pasar por todas las combinaciones de la mejor mano de 5 cartas, con las 7 cartas que puede elegir, para encontrar el valor más grande, que es el valor real de la mano.
Utiliza una tabla diferente para las descargas.
La tabla se vuelve bastante carnosa, ya que hay muchas celdas desperdiciadas por esta implementación. Para contrarrestar esto, puede crear un mapa durante el preprocesamiento, que mapea los valores primos grandes a valores enteros, y usar esto como fuente en su lugar.
menos exigente y se proporcionan al menos buenos evaluadores aquí: code.google.com/p/specialkpokereval. También se describe en mi respuesta en esta página. ¡Disfrutar! – SK9
Parece interesante. ¡Gracias por compartir! –
import itertools
from collections import Counter
# gets the most common element from a list
def Most_Common(lst):
data = Counter(lst)
return data.most_common(1)[0]
# gets card value from a hand. converts A to 14, is_seq function will convert the 14 to a 1 when necessary to evaluate A 2 3 4 5 straights
def convert_tonums(h, nums = {'T':10, 'J':11, 'Q':12, 'K':13, "A": 14}):
for x in xrange(len(h)):
if (h[x][0]) in nums.keys():
h[x] = str(nums[h[x][0]]) + h[x][1]
return h
# is royal flush
# if a hand is a straight and a flush and the lowest value is a 10 then it is a royal flush
def is_royal(h):
nh = convert_tonums(h)
if is_seq(h):
if is_flush(h):
nn = [int(x[:-1]) for x in nh]
if min(nn) == 10:
return True
else:
return False
# converts hand to number valeus and then evaluates if they are sequential AKA a straight
def is_seq(h):
ace = False
r = h[:]
h = [x[:-1] for x in convert_tonums(h)]
h = [int(x) for x in h]
h = list(sorted(h))
ref = True
for x in xrange(0,len(h)-1):
if not h[x]+1 == h[x+1]:
ref = False
break
if ref:
return True, r
aces = [i for i in h if str(i) == "14"]
if len(aces) == 1:
for x in xrange(len(h)):
if str(h[x]) == "14":
h[x] = 1
h = list(sorted(h))
for x in xrange(0,len(h)-1):
if not h[x]+1 == h[x+1]:
return False
return True, r
# call set() on the suite values of the hand and if it is 1 then they are all the same suit
def is_flush(h):
suits = [x[-1] for x in h]
if len(set(suits)) == 1:
return True, h
else:
return False
# if the most common element occurs 4 times then it is a four of a kind
def is_fourofakind(h):
h = [a[:-1] for a in h]
i = Most_Common(h)
if i[1] == 4:
return True, i[0]
else:
return False
# if the most common element occurs 3 times then it is a three of a kind
def is_threeofakind(h):
h = [a[:-1] for a in h]
i = Most_Common(h)
if i[1] == 3:
return True, i[0]
else:
return False
# if the first 2 most common elements have counts of 3 and 2, then it is a full house
def is_fullhouse(h):
h = [a[:-1] for a in h]
data = Counter(h)
a, b = data.most_common(1)[0], data.most_common(2)[-1]
if str(a[1]) == '3' and str(b[1]) == '2':
return True, (a, b)
return False
# if the first 2 most common elements have counts of 2 and 2 then it is a two pair
def is_twopair(h):
h = [a[:-1] for a in h]
data = Counter(h)
a, b = data.most_common(1)[0], data.most_common(2)[-1]
if str(a[1]) == '2' and str(b[1]) == '2':
return True, (a[0], b[0])
return False
#if the first most common element is 2 then it is a pair
# DISCLAIMER: this will return true if the hand is a two pair, but this should not be a conflict because is_twopair is always evaluated and returned first
def is_pair(h):
h = [a[:-1] for a in h]
data = Counter(h)
a = data.most_common(1)[0]
if str(a[1]) == '2':
return True, (a[0])
else:
return False
#get the high card
def get_high(h):
return list(sorted([int(x[:-1]) for x in convert_tonums(h)], reverse =True))[0]
# FOR HIGH CARD or ties, this function compares two hands by ordering the hands from highest to lowest and comparing each card and returning when one is higher then the other
def compare(xs, ys):
xs, ys = list(sorted(xs, reverse =True)), list(sorted(ys, reverse = True))
for i, c in enumerate(xs):
if ys[i] > c:
return 'RIGHT'
elif ys[i] < c:
return 'LEFT'
return "TIE"
# categorized a hand based on previous functions
def evaluate_hand(h):
if is_royal(h):
return "ROYAL FLUSH", h, 10
elif is_seq(h) and is_flush(h) :
return "STRAIGHT FLUSH", h, 9
elif is_fourofakind(h):
_, fourofakind = is_fourofakind(h)
return "FOUR OF A KIND", fourofakind, 8
elif is_fullhouse(h):
return "FULL HOUSE", h, 7
elif is_flush(h):
_, flush = is_flush(h)
return "FLUSH", h, 6
elif is_seq(h):
_, seq = is_seq(h)
return "STRAIGHT", h, 5
elif is_threeofakind(h):
_, threeofakind = is_threeofakind(h)
return "THREE OF A KIND", threeofakind, 4
elif is_twopair(h):
_, two_pair = is_twopair(h)
return "TWO PAIR", two_pair, 3
elif is_pair(h):
_, pair = is_pair(h)
return "PAIR", pair, 2
else:
return "HIGH CARD", h, 1
#this monster function evaluates two hands and also deals with ties and edge cases
# this probably should be broken up into separate functions but aint no body got time for that
def compare_hands(h1,h2):
one, two = evaluate_hand(h1), evaluate_hand(h2)
if one[0] == two[0]:
if one[0] =="STRAIGHT FLUSH":
sett1, sett2 = convert_tonums(h1), convert_tonums(h2)
sett1, sett2 = [int(x[:-1]) for x in sett1], [int(x[:-1]) for x in sett2]
com = compare(sett1, sett2)
if com == "TIE":
return "none", one[1], two[1]
elif com == "RIGHT":
return "right", two[0], two[1]
else:
return "left", one[0], one[1]
elif one[0] == "TWO PAIR":
leftover1, leftover2 = is_twopair(h1), is_twopair(h2)
twm1, twm2 = max([int(x) for x in list(leftover1[1])]), max([int(x) for x in list(leftover2[1])])
if twm1 > twm2:
return "left", one[0], one[1]
elif twm1 < twm2:
return "right", two[0], two[1]
if compare(list(leftover1[1]), list(leftover2[1])) == "TIE":
l1 = [x[:-1] for x in h1 if x[:-1] not in leftover1[1]]
l2 = [x[:-1] for x in h2 if x[:-1] not in leftover2[1]]
if int(l1[0]) == int(l2[0]):
return "none", one[1], two[1]
elif int(l1[0]) > int(l2[0]):
return "left", one[0], one[1]
else:
return "right", two[0], two[1]
elif compare(list(leftover1[1]), list(leftover2[1])) == "RIGHT":
return "right", two[0], two[1]
elif compare(list(leftover1[1]), list(leftover2[1])) == "LEFT":
return "left", one[0], one[1]
elif one[0] == "PAIR":
sh1, sh2 = int(is_pair(h1)[1]), int(is_pair(h2)[1])
if sh1 == sh2:
c1 = [int(x[:-1]) for x in convert_tonums(h1) if not int(sh1) == int(x[:-1])]
c2 = [int(x[:-1]) for x in convert_tonums(h2) if not int(sh1) == int(x[:-1])]
if compare(c1, c2) == "TIE":
return "none", one[1], two[1]
elif compare(c1, c2) == "RIGHT":
return "right", two[0], two[1]
else:
return "left", one[0], one[1]
elif h1 > h2:
return "right", two[0], two[1]
else:
return "left", one[0], one[1]
elif one[0] == 'FULL HOUSE':
fh1, fh2 = int(is_fullhouse(h1)[1][0][0]), int(is_fullhouse(h2)[1][0][0])
if fh1 > fh2:
return "left", one[0], one[1]
else:
return "right", two[0], two[1]
elif one[0] == "HIGH CARD":
sett1, sett2 = convert_tonums(h1), convert_tonums(h2)
sett1, sett2 = [int(x[:-1]) for x in sett1], [int(x[:-1]) for x in sett2]
com = compare(sett1, sett2)
if com == "TIE":
return "none", one[1], two[1]
elif com == "RIGHT":
return "right", two[0], two[1]
else:
return "left", one[0], one[1]
elif len(one[1]) < 5:
if max(one[1]) == max(two[1]):
return "none", one[1], two[1]
elif max(one[1]) > max(two[1]):
return "left", one[0], one[1]
else:
return "right", two[0], two[1]
else:
n_one, n_two = convert_tonums(one[1]), convert_tonums(two[1])
n_one, n_two = [int(x[:-1]) for x in n_one], [int(x[:-1]) for x in n_two]
if max(n_one) == max(n_two):
return "none", one[1], two[1]
elif max(n_one) > max(n_two):
return "left", one[0], one[1]
else:
return "right", two[0], two[1]
elif one[2] > two[2]:
return "left", one[0], one[1]
else:
return "right", two[0], two[1]
'''
a = ['QD', 'KD', '9D', 'JD', 'TD']
b = ['JS', '8S', 'KS', 'AS', 'QS']
print compare_hands(a,b)
'''
- 1. Algoritmo de programación: encontrar al ganador de una competencia
- 2. Algoritmo para reconocimiento de escritura a mano
- 3. Algoritmo para determinar el tipo de cambio
- 4. ¿Cuál es el mejor algoritmo de derivación "llave en mano"?
- 5. Algoritmo para determinar posibles grupos de elementos
- 6. Algoritmo para encontrar calles y el mismo tipo en una mano
- 7. Algoritmo para determinar la diversión máxima
- 8. Algoritmo para determinar los divisores adecuados
- 9. ¿El mejor algoritmo para determinar el máximo y mínimo en una matriz de números?
- 10. Algoritmo para determinar el mejor equipo y formación?
- 11. Capturar nueva línea desde una entrada de texto texas
- 12. algoritmo para determinar la identidad de un archivo (Optimización)
- 13. Algoritmo para determinar el rectángulo delimitador mínimo para la recopilación de coordenadas de latitud/longitud
- 14. Detecta el juego ganador en cero y cruces
- 15. ¿Hay un algoritmo para determinar cuánta luz del día hay?
- 16. ¿Hay un algoritmo para determinar las regiones de color contiguas en una cuadrícula?
- 17. Algoritmo para determinar el monto de pago en efectivo "habitual" por un precio dado
- 18. Determinar las combinaciones de hacer cambios para una cantidad dada
- 19. Algoritmo de votación: cómo calcular el rango?
- 20. ¿Cuál es el algoritmo para determinar el tamaño del grupo de trabajo óptimo y el número de grupo de trabajo
- 21. Flex: ¿Cómo establecer el cursor de mano?
- 22. Algoritmos para probar una mano de póquer para un sorteo directo (4 a una escalera)?
- 23. ¿El método para calcular el cambio de producto cruzado para las coordenadas de la mano izquierda?
- 24. Algoritmo para ordenar una lista de objetos
- 25. Algoritmo para clasificar una lista de productos?
- 26. ¿Qué es un buen algoritmo para determinar si una entrada es un cuadrado perfecto?
- 27. algoritmo óptimo para calcular el resultado de una fracción continua
- 28. Algoritmo para asientos de grupos de personas?
- 29. Preguntas para determinar el conocimiento de Maven
- 30. Carpetas desechables para dispositivos de mano de alta resolución
¿Cuál es su pregunta? – Gabe
@UCLcajun: Esto podría ser de alguna ayuda, http://code.google.com/p/specialkpokereval/. – SK9
Biblioteca fácil en python que también reparte tarjetas, mazos, etc.: [https://github.com/worldveil/deuces](https://github.com/worldveil/deuces). – lollercoaster