6
votes

Algorithme pour déterminer le gagnant d'une main Texas Hold'em

OK, alors je fais un Texas Hold'em Ai pour mon projet principal. J'ai créé l'interface graphique et les procédures de paris / de négociation, mais j'ai atteint la partie où j'ai besoin de déterminer qui a gagné la main et je ne connais pas le meilleur moyen d'aborder cela. J'utilise Python Btw. ATM J'ai 2 listes, une pour les 7 cartes de joueur, une pour les 7 cartes d'ordinateur. Actuellement, toutes les cartes sont stockées comme une structure dans la liste comme {'numéro': xx, 'costume': x}, où le nombre est de 2-14, costume est de 1 à 4. La façon dont j'allais aborder cela, est une fonction pour chaque type de main, en commençant par le plus haut. Par exemple. Self.Checkroyal (Plingercards) et passez manuellement dans la liste et évaluez si un rinçon royal a été atteint. Il doit y avoir un meilleur moyen de faire cela.


3 commentaires

Alors, quelle est votre question?


@Culcajun: Cela pourrait être de l'aide - code.google.com/p/specialkpokereval.


Bibliothèque facile à Python qui gère également des cartes, un pont, etc.: https://github.com/worldveil/Deuces .


5 Réponses :


6
votes

http://www.codingthewheel.com/archives/poker-hand- Evaluateur-Roundup

meilleur algorithme que vous obtiendrez est de 7 looks dans la table de recherche de taille 100 Mo (si je me souviens bien)


5 commentaires

Parlez-vous des deux plus deux méthodes de génération d'une table avec 32 millions d'entrées et de suivre un chemin basé sur votre main? Si oui, comment puis-je adapter cela à Python car il utilise des pointeurs pour les fonctions?


@LCAJUN: le Pokersource.sourceforge.net répertorié dans le lien ci-dessus contient des fixations Python.


Moins exigeant et au moins de bons évaluateurs sont fournis ici: code.google.com/p/specialkpokereval. Également décrit ci-dessous.


Vraiment bel article! Outre les idées précieuses, c'est une lecture très amusante aussi!


Ici semble rester de l'histoire. web.archive .org / web / 20131109140408 / http: // ...



0
votes

Monte Carlo ? C'est la première suggestion que je vois ici . C'est un autre projet principal. Simple et lent, mais sinon, vous regardez probablement des combinatoires compliquées que je ne prétends pas à en savoir beaucoup.


3 commentaires

Le papier que vous référez est d'essayer de résoudre un problème beaucoup plus intéressant. Le questionneur veut juste un algorithme de déterminer le gagnant d'une main donnée (par exemple, rinçage bat un droit).


Monte Carlo est habitué à trouver l'équité approximative d'une main contre d'autres, en simulant des millions de jeux de poker. Il utilise l'algorithme qui veut :)


Ah oui. Corrigez-vous! J'ai clairement lu la question trop rapidement et j'ai répondu à la question qui s'est présentée dans ma tête, pas ce qui a été posé ...



3
votes

La méthode utilisée dans la poste de Ralu est de loin la meilleure alternative que j'ai vue. J'ai utilisé cette méthode dans mon propre projet et c'est très rapide.

falaises:

Faites du prétraitement, pour générer une table contenant une valeur pour chaque main de poker distinct. Assurez-vous que la table est triée par la force de la main.

Chaque valeur de carte a une valeur prime correspondante. La table est indexée par la multiplication de chaque valeur de carte dans la main. Donc, pour trouver la valeur de la main AAAAAK, vous calculez la multiplication principale et utilisez-la comme index pour la table: xxx

(désolé pour la syntaxe Java).

De cette façon, AAAAAK est la même main que Kaaaa, et vous n'avez pas besoin d'une table de 5 dim.

Notez que vous devez passer à travers toutes les combinaisons de la meilleure main de 5 cartes, avec le 7 cartes que vous pouvez choisir, pour trouver la valeur la plus importante, qui est la valeur réelle de la main.

Vous utilisez une table différente pour les flushes.

La table devient assez costaud, Comme il y a beaucoup de cellules gaspillées par cette mise en œuvre. Pour contrer cela, vous pouvez créer une carte lors du prétraitement, qui mappe les grandes valeurs primordiales aux valeurs entière et l'utilisent à la place de la source.


2 commentaires

Moins exigeant et au moins de bons évaluateurs sont fournis ici: code.google.com/p/Specialkpokereval. Également décrit dans ma réponse sur cette page. Profitez!


Semble intéressant. Merci d'avoir partagé!



1
votes

Un exemple d'un évaluateur de Texas Hold'em TeXas Hold'em 7 et 5 est prêt à être trouvé ici et expliqué davantage ici . Cela pourrait vous aider avec la performance. Tous les commentaires bienvenus à l'adresse e-mail qui y sont trouvés.


0 commentaires

4
votes
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 commentaires

Semble très bon et clair. Mais quels sont les exemples pour les arguments de la main1 et de la main2? Comment les cartes devraient-elles être envoyées aux fonctions pour être comparées?