""" hand.py A class representing a hand of cards, particularly a black jack hand. Jim M | Nov 2008 | GPL """ from card import Card from doctest import testmod class Hand: """A hand of cards, with methods for blackjack. >>> h = Hand() >>> h.addCard(Card(1, 's')) >>> h.addCard(Card(11, 'd')) >>> h.count() 2 >>> h.blackJackValue() 21 >>> h.isBlackJack() True >>> h.addCard(Card(1, 'c')) >>> h.blackJackValue() 12 >>> h.isBust() False >>> h.count(1) # how many aces? 2 >>> str(h) '3 cards: ace of spades, jack of diamonds, ace of clubs' """ def __init__(self, n=0): """A hand of n random cards. (If n isn't given or is 0, the hand is initially empty and may be filled with addCard().) >>> Hand(3).count() 3 """ self.cards = [] for i in range(n): self.cards.append(Card()) def count(self, rank=None): """Return number of cards of given rank in the hand, or the total number of cards if rank isn't specified. >>> threeCards = Hand(5) >>> threeCards.count() 5 """ if not rank: return len(self.cards) else: howMany = 0 for card in self.cards: if rank == card.getRank(): howMany += 1 return howMany def addCard(self, card=None): """Add a card to the hand. If the card isn't specified, add a random card. >>> hand = Hand(3) >>> hand.addCard() >>> hand.count() 4 """ if not card: card = Card() self.cards.append(card) def blackJackValue(self): """Return the hand's black jack value. (An ace that would put the sum over 21 counts as 1 rather than 11.) >>> hand = Hand() >>> hand.addCard(Card(1, 's')) # add ace of spades >>> hand.addCard(Card(7, 'c')) # add ten of clubs >>> hand.blackJackValue() 18 >>> hand.addCard(Card(13, 'c')) # add king of clubs >>> hand.blackJackValue() 18 >>> hand.addCard(Card(1, 'd')) # add ace of diamonds >>> hand.blackJackValue() 19 """ value = 0 for card in self.cards: value += card.blackJackValue() nAces = self.count(1) while nAces > 0 and value > 21: value -= 10 nAces -= 1 return value def getCard(self, n=None): """Return the n'th card from the hand, 1 <= n <= self.count(). If n isn't given, return the last card.""" if n and n >= 1 and n <= self.count(): return self.cards[n-1] else: return self.cards[-1] def isBust(self): """Return True if the hand's blackjack value is over 21.""" return self.blackJackValue() > 21 def isBlackJack(self): """Return True if the hand has two cards that total 21.""" return self.count()==2 and self.blackJackValue()==21 def printHand(self, indent=0): """Print the hand, one card per line, with specified indentation.""" for card in self.cards: print " "*indent + str(card) def sort(self): """Arrange the cards in increasing order by suit, ace high.""" self.cards.sort() def __str__(self): if len(self.cards)==0: return "no cards" elif len(self.cards)==1: return "1 card: " + str(self.cards[0]) else: names = [] for card in self.cards: names.append(str(card)) return ("%i cards: " % self.count()) + ', '.join(names) if __name__=="__main__": testmod()