Py学习  »  Python

使用python识别直线、齐平和其他类别(从扑克中)

Sachin Sharma • 4 年前 • 710 次点击  

我是Python的新手,从书本、论坛和开发人员那里学习。最近,我尝试在扑克程序中实现各种手排名类别。目标是计算概率,看看它是否符合理论扑克手概率?

Source: https://en.wikipedia.org/wiki/Poker_probability?oldformat=true

请在下面找到我迄今为止用来构建它的代码和逻辑。代码包含卡类和甲板类,它们一起实现使用的一组标准扑克牌,以及一个示例pytest测试函数test_xxx()。

到目前为止,我已经编写了hasonepair、hastwopairs、hasthreeofakind、hasfullhouse和hasfourofakind()函数,它工作得很好,但我正在努力实现直接、刷新和直接刷新。

有人能就如何处理直发、冲洗、皇家冲洗、直发病例提出建议或给出指导意见吗?此外,任何更新此代码的进一步建议都是很好的。


import random

SUITS = ["Clubs", "Diamonds", "Hearts", "Spades"]
RANKS = ["", "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"]

# here's two Python classes whose objects represent playing cards and decks thereof

class Card():
    """
    Represents a single playing card,
        whose rank internally is int _rank: 1..13 => "Ace".."King"
        and whose suit internally is int _suit 0..3 => "Clubs".."Spades"
    """

    def __init__(self, rank=1, suit=3): # this is the constructor!
        '''
        Initialize card with given int suit and int rank
        :param rank:
        :param suit:
        :return:
        '''
        self._rank = rank
        self._suit = suit

    def __str__(self): # this is the "stringifier"
        """
        Return the string name of this card:
        "Ace of Spades": translates int fields to strings
        :return:
        """

        # "Ace of Spades" is string for self._rank==1, self._suit==3

        toreturn = RANKS[self._rank] + " of " + SUITS[self._suit]

        return toreturn


class Deck():
    """
    Represents a deck of 52 standard playing cards,
        as a list of Card refs
    """

    def __init__(self): # constructor
        """
        Initialize deck: field _cards is list containing
            52 Card refs, initially
        :return: nothing
        """

        self._cards = []
        for rank in range(1, 14):
            for suit in range(4):
                c = Card(rank, suit) # create next Card with given value
                self._cards.append(c) # add it to this Deck

    def __str__(self):
        """
        "Stringified" deck: string of Card named,
        with \n for easier reading
        :return:
        """
        toreturn = ''

        # for index in range(len(self._cards)):
        #     self._cards[index]

        for c in self._cards:
            temp = str(c)  # temp is the stringified card
            toreturn = toreturn + temp + "\n"  # note \n at end

        return toreturn

    def shuffle(self):
        random.shuffle(self._cards)  # note random function to do this

    def dealCard(self):
        toreturn = self._cards.pop(0)  # get and remove top card from deck
        return toreturn

def buildDict(hand):
    dict = {}

    for card in hand:
        dict[card._rank] = dict.get(card._rank, 0) + 1


    return dict


def hasOnePair(dict):

    twocount = 0
    threecount = 0

    for v in dict.values():
        if v == 2:
            twocount += 1
        elif v == 3:
            threecount += 1

    if twocount==1 and threecount != 1:
        return True
    else:
        return False



def hasTwoPairs(dict):

    twocount1 = 0
    threecount1 = 0

    for v in dict.values():
        if v ==2:
            twocount1 += 1
        elif v == 3:
            threecount1 +=1

    if twocount1 == 2 and threecount1 != 1:
        return True
    else:
        return False



def hasThreeOfAKind(dict):


    twocount = 0
    threecount = 0

    for v in dict.values():
        if v == 2:
            twocount += 1
        elif v == 3:
            threecount += 1

    if twocount != 1 and threecount == 1:
        return True
    else:
        return False



def hasFullHouse(dict):

    twocount = 0
    threecount = 0

    for v in dict.values():
        if v == 2:
            twocount += 1
        elif v == 3:
            threecount += 1

    if twocount == 1 and threecount == 1:
        return True
    else:
        return False





def hasFourOfAKind(dict):

    fourcount = 0
    onecount = 0

    for v in dict.values():
        if v ==4:
            fourcount += 1
        elif v == 1:
            onecount +=1

    if fourcount == 1 and onecount == 1:
        return True
    else:
        return False


def hasStraight(hand):


    return False

def hasFlush(dict):


    return False

def hasStraightFlush(dict):

    return False

def hasRoyalFlush(dict):

    return False

def main():


    TRIALS = 1000  # int(input ("Input number of hands to test: "))

    hand = []  # list of Card in hand

    # accumulators for different counts

    onepairCount = 0
    twopairCount = 0
    threeCount = 0
    fourCount = 0
    fullHouseCount = 0
    StraightCount = 0



    for num in range(TRIALS):

        # create new Deck and shuffle
        d = Deck()
        d.shuffle()

        # initialize hand as empty list
        hand = []

        # deal top 5 cards of deck, adding to hand

        for count in range(5):
            hand.append(d.dealCard())


        # build the dictionary of card ranks in hand

        dict = buildDict(hand)



        # use dictionary to make hand checking easier

        if hasOnePair(dict):
            onepairCount += 1
        elif hasTwoPairs(dict):
            twopairCount += 1
        elif hasThreeOfAKind(dict):
            threeCount += 1
        elif hasFourOfAKind(dict):
            fourCount += 1
        elif hasFullHouse(dict):
            fullHouseCount += 1
        elif hasStraight(dict):
            StraightCount +=1

    # add more if needed...

    # print out results...

    print("Number of one pair hands is: ", onepairCount)
    print("% of hands: ", 100.0 * onepairCount / TRIALS)

    print("Number of two pair hands is: ", twopairCount)
    print("% of hands: ", 100.0 * twopairCount / TRIALS)


    print("Number of trips hand is: ", threeCount)
    print("% of hands: ", 100.0 * threeCount / TRIALS)

    print("Number of quads hand is: ", fourCount)
    print("% of hands: ", 100.0 * fourCount / TRIALS)

    print("Number of trips hand is: ", fullHouseCount)
    print("% of hands: ", 100.0 * fullHouseCount / TRIALS)

    print("Number of trips hand is: ", StraightCount)
    print("% of hands: ", 100.0 * StraightCount / TRIALS)



def card_example():

    card1 = Card()  # Card(1,3) => Ace of Clubs
    card2 = Card(12, 2) # Card (12,2) => Queen of Hearts

    card1._newfield = 47 # we can add new fields to any Python object!

    # three ways of printing a Card
    #

    print(card1.__str__())  # calling the methods against card
    print(str(card2)) # type-casting
    print(card2) # short-cut: passing obj ref to print does str() automagically

    print(card1._newfield) # see the new field value?

    print(card1._rank) # see the rank (1..13)
    print(card1._suit) # see the suit (0..3)

def deck_example():
    """
    Test Deck: create, print then shuffle, print again
    Then deal first two cards and print, along with bottom card
    """

    deck = Deck()
    print(str(deck)) # see entire deck before shuffling

    print("Now we shuffle:\n")

    deck.shuffle()
    print(str(deck)) # see entire deck after shuffling

    card1 = deck.dealCard()
    card2 = deck.dealCard()

    print("The first card dealt is", str(card1), "and the second is", str(card2))
    print("Bottom of deck is", deck._cards[-1])  # can't hide the implementation!

if __name__ == "__main__": # only run this if this .py is NOT imported
    # pass

    # card_example() # uncomment to test creating & calling Card methods

    # deck_example()  # uncomment to test Deck: create, print, shuffle, print

    main()  # uncomment to run general poker odds calculations

#
# -------------------------------------------------------------------------
#

#pytest follows...

def test_one_pair():
    testhand = [Card(2, 3), Card(1, 2),
                Card(3, 1), Card(13, 2),
                Card(2, 0)]

    dict = buildDict(testhand)

    assert hasOnePair(dict)  #hasTwoPairs

def test_two_pair():
    testhand = [Card(2, 3), Card(1, 2),
                Card(3, 1), Card(3, 2),
                Card(2, 0)]

    dict = buildDict(testhand)

    assert hasTwoPairs(dict)

def test_three_pair():
    testhand = [Card(1, 3), Card(1, 2),
                Card(1, 1), Card(13, 2),
                Card(2, 0)]

    dict = buildDict(testhand)

    assert hasThreeOfAKind(dict)

def has_Four_Of_A_Kind():
    testhand = [Card(1, 3), Card(1, 2),
                Card(1, 1), Card(1, 0),
                Card(2, 0)]

    dict = buildDict(testhand)

    assert hasFourOfAKind(dict)

def test_full_house():
    testhand = [Card(1, 3), Card(1, 2),
                Card(1, 1), Card(13, 2),
                Card(13, 2)]

    dict = buildDict(testhand)

    assert hasFullHouse(dict)

def test_Straight():
    testhand = [Card(11, 1), Card(10, 3),
                Card(9, 2), Card(8, 1),
                Card(7, 3)]

    dict = buildDict(testhand)

    assert hasStraight(dict)


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/36176
 
710 次点击  
文章 [ 1 ]  |  最新文章 4 年前
Green Cloak Guy
Reply   •   1 楼
Green Cloak Guy    4 年前

直牌的条件是你的五张牌有相邻的等级,这样没有两张牌有相同的等级。您可以使用两种不同的检查来确认这一点:

  1. 直牌中没有两张牌具有相同的等级(因此,根据鸽子洞原则,必须存在最小和最大之间的所有等级

def hasStraight(hand):
    # account for both low-ace and high-ace
    ranks_low = sorted([card._rank for card in hand])
    ranks_high = sorted([(14 if card._rank == 1 else card._rank) for card in hand])

    return (
        (
            ranks_low[-1] - (len(hand) - 1) == ranks_low[0]
            or ranks_high[-1] - (len(hand) - 1) == ranks_high[0]
        )                                                        # condition 1
        and len(set(hand)) == len(hand)                          # condition 2
    )


冲洗的条件是所有卡片都是同一套。这很容易验证,只需 set true

def hasFlush(hand):
    suits_set = set(*[card._suit for card in hand])
    return len(suits_set) == 1

def hasStraightFlush(hand):
    return hasStraight(hand) and hasFlush(hand)

def hasRoyalFlush(hand):
    ranks = sorted([14 if card._rank == 1 else card._rank for card in hand])
    return (
        hasStraightFlush(hand)
        and ranks[0] == 10 and ranks[-1] == 14
    ) # royal flush starts at 10, ends at high-ace