Contents of blackjack.py


toggle line numbers
  1: #! /usr/bin/python
  2: """
  3: BlackJack game with single or multiple decks containing playing
  4: cards with suits and ranks making it possible to try your hand at
  5: counting cards.
  6: 
  7: Copyright (c) 2007,2009, Roger Lew
  8: All rights reserved. Licensed under BSD.
  9: """
 10: from random import randint,shuffle
 11: import sys
 12: 
 13: def ifelse(condition, a, b):
 14:     """Excel-like if/else functionality for list generators"""
 15:     if condition : return a
 16:     else         : return b
 17:     
 18: class card:
 19:     """a playing card"""
 20:     def __init__(self,suit,rank,show=1):
 21:         self.suit,self.rank,self.show=suit,rank,show
 22:         if rank in ['J','Q','K'] : self.values=[10]
 23:         elif rank in ['A']       : self.values=[1,11]
 24:         else                     : self.values=[int(rank)]
 25: 
 26:     def __str__(self):
 27:         """returns string representation of card"""
 28:         if self.show : return '[%s%3s]'%(self.suit,self.rank)
 29:         else         : return '[    ]'
 30: 
 31:     def __add__(self,other):
 32:         """operator overloaded addition, returns a list of possible values"""
 33:         return_values=[]
 34:         # test type so the recursive sum function in the blackjack class works
 35:         if type(other)==list:
 36:             for sval in self.values:
 37:                 for oval in other:
 38:                     return_values.append(sval+oval)
 39:         else:
 40:             for sval in self.values:
 41:                 for oval in other.values:
 42:                     return_values.append(sval+oval)
 43:         return return_values
 44:         
 45: class deck:
 46:     """Single or multiple 52 card decks of playing cards"""
 47:     def __init__(self,num_of_decks):
 48:         self.cards=[]
 49:         self.discards=[]
 50:         self.num_of_decks=num_of_decks
 51:         
 52:         for i in range(num_of_decks):
 53:             for rank in ['2','3','4','5','6','7','8','9','10','J','Q','K','A']:
 54:                 for suit in ['S','H','D','C']:
 55:                     self.cards.append(card(suit,rank))
 56:         
 57:     def shuffle(self):
 58:         """Shuffles deck"""
 59:         for i in range(randint(1,100)): shuffle(self.cards)
 60: 
 61:     def draw(self,show=1):
 62:         """draws a single card"""
 63:         if len(self.cards)==0:
 64:             print 'Out of cards re-shuffling discards...'
 65:             self.cards,self.discards=self.discards,self.cards
 66:             self.shuffle()
 67:             
 68:         self.cards[-1].show=show
 69:         return self.cards.pop()
 70: 
 71:     def discard(self, x):
 72:         """returns a card to the discard pile"""
 73:         if type(x)==list : self.discards.extend(x)
 74:         else             : self.discards.append(x)
 75:         
 76:     def __str__(self):
 77:         """returns string representation of deck"""
 78:         return ''.join([card.__str__()+'\t' for card in self.cards])
 79: 
 80: class blackjack:
 81:     def __init__(self):
 82:         print "Let's play BlackJack!"
 83:         print "To quit enter 'Q' at Hit or Stand prompt.\n"
 84:         # Initialize deck
 85:         self.deck=deck(1)
 86:         self.deck.shuffle()
 87: 
 88:     def play(self):
 89:         # Deal cards
 90:         self.dealer=[self.deck.draw(),self.deck.draw(show=0)]
 91:         self.player=[self.deck.draw(),self.deck.draw()]
 92:         self.dealersums=self.sumcards(self.dealer)
 93:         self.playersums=self.sumcards(self.player)
 94:         self.winner=self.check4winner()
 95: 
 96:         # Hit or stand
 97:         choice='H'
 98:         while self.winner==0:
 99:             print self
100:             choice=raw_input('[H]it or [S]tand? ')
101:             if choice=='H' or choice=='h':
102:                 self.player.append(self.deck.draw())
103:                 self.playersums=self.sumcards(self.player)
104:                 self.winner=self.check4winner()
105: 
106:             elif choice=='S' or choice=='s':
107:                 # Dealer stands at 17
108:                 self.dealer[1].show=1
109:                 while self.winner==0 and min(self.dealersums) < 17:
110:                     print self
111:                     self.dealer.append(self.deck.draw())
112:                     self.dealersums=self.sumcards(self.dealer)
113:                     self.winner=self.check4winner()
114: 
115:                 # Determine winner if none declared
116:                 if self.winner==0:
117:                     dealerhisum=max([ifelse(x>21,0,x) for x in self.dealersums])
118:                     playerhisum=max([ifelse(x>21,0,x) for x in self.playersums])
119:                     if   playerhisum > dealerhisum : self.winner='Player Wins!'
120:                     elif playerhisum < dealerhisum : self.winner='Dealer Wins!'
121:                     else                           : self.winner='Tie'
122:                     
123:             elif choice=='Q' or choice=='q':
124:                 print 'Good bye'
125:                 sys.exit()
126:                 
127:         # Final feedback
128:         print self; print self.winner
129: 
130:         # Clean-up
131:         self.deck.discard(self.dealer); self.deck.discard(self.player)
132:         if 'Player' in self.winner : return 1 # wins count
133:         else                       : return 0
134: 
135:     def sumcards(self,cards):
136:         """recursive card sum function returns a list of possible values"""
137:         if  len(cards)==2: return cards[0]+cards[1]
138:         elif len(cards)>2: return cards[0]+self.sumcards(cards[1:])
139:     
140:     def check4winner(self):
141:         """returns winner if blackjack is hit or someone busts"""
142:         if 21 in self.dealersums : return 'Dealer Hit BlackJack!'
143:         if 21 in self.playersums : return 'Player Hit BlackJack!'
144:         if 0 not in [ifelse(x>21,1,0) for x in self.dealersums]: return 'Player Wins by Bust!'
145:         if 0 not in [ifelse(x>21,1,0) for x in self.playersums]: return 'Dealer Wins by Bust!'
146:         return 0 # indicates no winner
147:     
148:     def __str__(self):
149:         return 'Dealer: '+''.join([card.__str__()+'\t' for card in self.dealer])+\
150:              '\nPlayer: '+''.join([card.__str__()+'\t' for card in self.player])+'\n'
151: 
152: def main():
153:     BlackJack=blackjack()
154:     wins=counter=0
155:     while 1:
156:         wins+=BlackJack.play()
157:         counter+=1
158:         print 'Your %i of %i.\n'%(wins,counter)
159: 
160: if __name__ == "__main__":
161:     main()
162: 
163: 

rogerlew.geekgalaxy.com / software / PyBlackJack / blackjack.php