This is a sightly revised version of Michael Dawson's blackjack.py from chapter 9 of Michael Dawson, "Python: Programming for the Absolute Beginner," Third Edition, Course Technology PTR, 2010, Cengage Learning, Boston, ISBN 978-1-4354-5500-9, to avoid problems when run under Python 2.
1 # Blackjack 2 # From 1 to 7 players compete against a dealer 3 4 import cards, games2 5 6 class BJ_Card(cards.Card): 7 """ A Blackjack Card. """ 8 ACE_VALUE = 1 9 10 @property 11 def value(self): 12 if self.is_face_up: 13 v = BJ_Card.RANKS.index(self.rank) + 1 14 if v > 10: 15 v = 10 16 else: 17 v = None 18 return v 19 20 class BJ_Deck(cards.Deck): 21 """ A Blackjack Deck. """ 22 def populate(self): 23 for suit in BJ_Card.SUITS: 24 for rank in BJ_Card.RANKS: 25 self.cards.append(BJ_Card(rank, suit)) 26 27 28 class BJ_Hand(cards.Hand): 29 """ A Blackjack Hand. """ 30 def __init__(self, name): 31 super(BJ_Hand, self).__init__() 32 self.name = name 33 34 def __str__(self): 35 rep = self.name + ":\t" + super(BJ_Hand, self).__str__() 36 if self.total: 37 rep += "(" + str(self.total) + ")" 38 return rep 39 40 @property 41 def total(self): 42 # if a card in the hand has value of None, then total is None 43 for card in self.cards: 44 if not card.value: 45 return None 46 47 # add up card values, treat each Ace as 1 48 t = 0 49 for card in self.cards: 50 t += card.value 51 52 # determine if hand contains an Ace 53 contains_ace = False 54 for card in self.cards: 55 if card.value == BJ_Card.ACE_VALUE: 56 contains_ace = True 57 58 # if hand contains Ace and total is low enough, treat Ace as 11 59 if contains_ace and t <= 11: 60 # add only 10 since we've already added 1 for the Ace 61 t += 10 62 63 return t 64 65 def is_busted(self): 66 return self.total > 21 67 68 69 class BJ_Player(BJ_Hand): 70 """ A Blackjack Player. """ 71 def is_hitting(self): 72 response = games2.ask_yes_no("\n" + self.name + ", do you want a hit? (Y/N): ") 73 return response == "y" 74 75 def bust(self): 76 print(self.name, "busts.") 77 self.lose() 78 79 def lose(self): 80 print(self.name, "loses.") 81 82 def win(self): 83 print(self.name, "wins.") 84 85 def push(self): 86 print(self.name, "pushes.") 87 88 89 class BJ_Dealer(BJ_Hand): 90 """ A Blackjack Dealer. """ 91 def is_hitting(self): 92 return self.total < 17 93 94 def bust(self): 95 print(self.name, "busts.") 96 97 def flip_first_card(self): 98 first_card = self.cards[0] 99 first_card.flip() 100 101 102 class BJ_Game(object): 103 """ A Blackjack Game. """ 104 def __init__(self, names): 105 self.players = [] 106 for name in names: 107 player = BJ_Player(name) 108 self.players.append(player) 109 110 self.dealer = BJ_Dealer("Dealer") 111 112 self.deck = BJ_Deck() 113 self.deck.populate() 114 self.deck.shuffle() 115 116 @property 117 def still_playing(self): 118 sp = [] 119 for player in self.players: 120 if not player.is_busted(): 121 sp.append(player) 122 return sp 123 124 def __additional_cards(self, player): 125 while not player.is_busted() and player.is_hitting(): 126 self.deck.deal([player]) 127 print(player) 128 if player.is_busted(): 129 player.bust() 130 131 def play(self): 132 # deal initial 2 cards to everyone 133 self.deck.deal(self.players + [self.dealer], per_hand = 2) 134 self.dealer.flip_first_card() # hide dealer's first card 135 for player in self.players: 136 print(player) 137 print(self.dealer) 138 139 # deal additional cards to players 140 for player in self.players: 141 self.__additional_cards(player) 142 143 self.dealer.flip_first_card() # reveal dealer's first 144 145 if not self.still_playing: 146 # since all players have busted, just show the dealer's hand 147 print(self.dealer) 148 else: 149 # deal additional cards to dealer 150 print(self.dealer) 151 self.__additional_cards(self.dealer) 152 153 if self.dealer.is_busted(): 154 # everyone still playing wins 155 for player in self.still_playing: 156 player.win() 157 else: 158 # compare each player still playing to dealer 159 for player in self.still_playing: 160 if player.total > self.dealer.total: 161 player.win() 162 elif player.total < self.dealer.total: 163 player.lose() 164 else: 165 player.push() 166 167 # remove everyone's cards 168 for player in self.players: 169 player.clear() 170 self.dealer.clear() 171 172 173 def main(): 174 print("\t\tWelcome to Blackjack!\n") 175 176 names = [] 177 number = games2.ask_number("How many players? (1 - 7): ", low = 1, high = 8) 178 for i in range(number): 179 name = raw_input("Enter player name: ") 180 names.append(name) 181 print() 182 183 game = BJ_Game(names) 184 185 again = None 186 while again != "n": 187 game.play() 188 again = games2.ask_yes_no("\nDo you want to play again?: ") 189 190 191 main() 192 raw_input("\n\nPress the enter key to exit.") 193 194 195 196