hi, i'm writing a poker game project and encountered some problem while i try to sort the cards in hand.

so far, i have a deck of 52 cards, each of the player is assigned for 3 cards.
the questions, I don't know how to sort the cards in the players' hand.

for example, playerHand = [TC, 3S, 5S]
how do I sort the cards to [3S, 5S, TC]? (as T = 10, Ace = 14)

I know it's somehow like ranking the values and then sort them.
however, i have no idea where to start. :(

Something like this ?

cards=['3S', 'KD','5S', 'TC','2D','3D']
print sorted(cards,key=lambda x:values[x[0]])

This puts the cards ordered first by value, then suit by using normal function, not lambda:

cards=['3S', 'KD','5S', 'KC','TD','3D']

def sortkey(x):
  return values[value],suit

print sorted(cards,key = sortkey)

You can play around with this ...

# sort cards (2 letter names) by first and second character
# TC = Ten of Club   KD = King of Diamond   AH = Ace of Heart  etc.

import operator

cards = ['3S', 'KD','5S', 'TC','2D','3D']

# sort by first character in each card
print sorted(cards)
# sort by second character (index=1) in each card
print sorted(cards, key=operator.itemgetter(1))

""" result >>>
['2D', '3D', '3S', '5S', 'KD', 'TC']
['TC', 'KD', '2D', '3D', '3S', '5S']

Seems to me like this would be a great opportunity to apply and use object oriented programming.

A card is a type of object. What I would try is to make a card class with rank and suit attributes. Then I'd add comparison methods to compare card rank. (I'm assuming a lone card's suit is unimportant. However, in some games or rules suit does determine rank.) If my idea is correct any sort function should return the correct order. I think we could even add a method to return a nice string representation of the card.

Something like this.

#Python 3.1

class Card:

    suits = {'spades': '♠',
             'hearts': '♥',
             'diamonds': '♦',
             'clubs': '♣',}

    ranks = {1: 'A',
             10: 'T',
             11: 'J',
             12: 'Q',
             13: 'K',
             14: 'A',}

    for i in range(2, 10):
        ranks[i] = str(i)

    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit

    def __eq__(self, other):
        if self.rank == other.rank:
            return True
            return False

    def __ge__(self, other):
        if self.rank >= other.rank:
            return True
            return False

    def __gt__(self, other):
        if self.rank > other.rank:
            return True
            return False

    def __le__(self, other):
        if self.rank <= other.rank:
            return True
            return False

    def __lt__(self, other):
        if self.rank < other.rank:
            return True
            return False

    def __ne__(self, other):
        if self.rank != other.rank:
            return True
            return False

    def __str__(self):
        #Return a string representation of the card. Example: A♠
        return Card.ranks[self.rank] + Card.suits[self.suit]

    def __repr__(self):
        #Needed to make printing a list of cards look nice.
        #Would be better to create a hand object.
        return str(self)

if __name__ == '__main__':
    playerHand = [Card(10, 'clubs'), Card(3, 'spades'), Card(5, 'spades')]
    #Orders player's hand as you requested.
    #However, in most examples I've seen high rank is usually displayed first.
    #Sorting and then reversing the hand will order the cards high rank first.

simpler: (wrote this this morning but then the internet cut out.)

class Card(object):
    # You can remap these, but then you need to rewrite the __cmp__ function.
    # All the following arranges from small to big
    SUITMAPPER = ("Diamond", "Club", "Heart", "Space")
    VALUEMAPPER = ("2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack",
                   "Queen", "King", "Ace")
    def __init__(self, value, suit):
        # suit and value are both int. They correspondes to the index for the
        self.suit = suit
        self.value = value

    def __cmp__(self, other):
        # check for correct type
        # you can rewrite this function to sort for your own
        if not isinstance(other, Card): 
            raise TypeError("Cannot compare card with non card")
        suitcmp = cmp(self.suit, other.suit) # See python doc on cmp.
        if suitcmp != 0:
            return suitcmp
            return cmp(self.value, other.value)

    def __str__(self):
        txt = self.__class__.VALUEMAPPER[self.value]
        txt += " of "
        txt += self.__class__.SUITMAPPER[self.suit]
        return txt

if __name__ == "__main__":
    c_3S = Card(1, 3)
    c_5S = Card(3, 3)
    c_TC = Card(8, 1)
    playerHand = [c_TC, c_3S, c_5S]
    print "Unsorted: "
    for card in playerHand:
        print card
    playerHand.sort() # .sort() method uses the __cmp__ method
    print "Sorted from small to big: "
    for card in playerHand:
        print card


    print "Sorted from big to small: "
    for card in playerHand:
        print card

Ok, so this is another poster, we had one discussion just moment ago:

I did my version and experimented the probability of various high value hands.

Here is my previously unposted code. Lower hand printing commented out as they are so common. Full house is extremely rare however without exchange of cards.

import random
from itertools import islice

for i in range(2,11):
    valuecode[i] = str(i)
def dealer(deck):
    while deck:
        yield deck.pop()

def gethand(dealer):
    return sorted(islice(dealer,5))

def isflush(cards):
    return all(suit==firstsuit
               for value,suit in cards
               for _,firstsuit in (cards[0],)

def isstraight(cards):
    if all(a==b for a,b in zip(range(2,6)+[14],[x for x,_ in cards])):
##        print 'Small ace',cards #straight 1..5
        return True
        return all(nextvalue==thisvalue+1
               for (thisvalue,_),(nextvalue,_) in zip(cards[:-1],cards[1:]))

def cardcode(value,suit):
    return suitcode[suit]+valuecode[value]

def codedhand(cards):
    return ','.join(cardcode(*card) for card in cards)
if __name__== '__main__':
    wins = games = 0

    multiples={frozenset([1,3]):'Triple',frozenset([1,2]):'Two pairs', frozenset([1,4]):'Four same',
               frozenset([2,3]):'Full house'}
    while 'Royal' not in handstyle: # and wins < 1000:
        ## cards with ace as more high value 14
              for suit in ('heart','diamonds','spade','club')
              for value in range(13)]


        while len(deck)>=10 and 'Royal' not in handstyle:
            playerhand, dealerhand = gethand(getcards), gethand(getcards)

            for cards in (dealerhand,playerhand):
                if len(set(x for x,_ in cards))<4: ## 3 or 4 same, two pairs or full house
                    values=list(x for x,_ in cards)
                    for value in set(values):
##                    print multiples[frozenset(counts.values())]

                if isflush(cards) or isstraight(cards):
                    if isflush(cards) and isstraight(cards):
                        handstyle = 'Royal Flush' if cards[-1][0]==14 else 'Straight Flush'
                        print '***'+handstyle+'***'
                        handstyle = 'Straight ' if isstraight(cards) else 'Flush'
                    print handstyle,':',codedhand(cards)
    raw_input("\n\n%i wins in %i games" % (wins,games))

Cool, Buster. I might implement some of your ideas in my own class.

I wish the original poster would have told us which card game he is programming.

My best guess at the moment is seven card stud.

If we knew then we could get to work on making a good hand class.

I'm having trouble thinking of a way to rank a hand as a whole.


(I'm programming for the hold'em variant, btw.)

That's cool, Tony. I'll have to look over that thread some more.

thanks, everyone!

i saw someone has the similar question as mine.
that we need to convert the card values and suits into rank (integers), then sort the hand without using the build-in function.

I haven't learned about how to write class on my own, otherwise i believe it's a much more convenient way to program.

right now, i figured out how to convert the card values and suits into rank. I also know how to write a sorting function without using the build-in sort function.

the following is what I got:

def rankValues (hand):
    if card.value == "Two":
        return 0
    elif card.value == "Three":
        return 1
    elif card.value == "Four":
        return 2
    elif card.value == "Five":
        return 3
    elif card.value == "Six":
        return 4
    elif card.value == "Seven":
        return 5
    elif card.value == "Eight":
        return 6
    elif card.value == "Nine":
        return 7
    elif card.value == "Ten":
        return 8
    elif card.value == "Jake":
        return 9
    elif card.value == "Queen":
        return 10
    elif card.value == "King":
        return 11
    elif card.value == "Ace":
        return 12

def rankSuits(hand):
    if card.suit == "Spades":
        return 3
    elif card.suit == "Hearts":
        return 2
    elif card.suit == "Dimonds":
        return 1
        return 0

def sortHand (hand):
    for j in range(1,len(hand)):
        i = j
        while i > 1 and hand[i]<hand[i-1]:
            temp = hand[i]
            hand[i] = hand[i-1]
            hand[i-1] = temp
            i = i-1
    return hand

However, i'm having trouble with combining the three functions (rankValues(), rankSuits(),sortHand()) together so that I can sort cards in hand.

BTW, reply to lrh9, the poker game i'm writing is the basic 5 cards one.

thanks in advance

Have you first created the 5-card hand?

What do you ultimately want the hand sorted by? Rank, suit or poker hand?
ex. a 5 card hand that contains a pair sorted by rank could look like this:
2s, 3d, 6h, 6c, Ad
or sorted by what the poker hand is looks like:
6h, 6c, Ad, 3d, 2s - read from left to right, pair of sixes with ace, three,
two kicker