class Blackjack(): def __init__(self): # Set up the player's wallet. self.wallet = Wallet() # Reset the game. self.reset_game() def reset_game(self): """ Reset all game variables for a new round. """ # Set the current cards to an empty array. self.hands = {'dealer': Hand(), 'player': Hand()} # Create a new new deck of cards. self.deck = Deck(shuffle_deck=True) def ask_bet(self): """ Ask a player for the current round's bet. """ balance = self.wallet.get_balance() message = '\nYou have {balance} remaining. Enter your bet: '.format( balance=balance) while True: try: self.bet = int(input(message)) except: print('Please enter a number. Try again.') continue else: if self.bet > balance: print( 'You cannot bet more than you have. Please enter a smaller number.' ) continue else: print('You bet {} for this round.'.format(self.bet)) break def draw_initial_cards(self): """ Draw initial cards for player and dealer. """ # Draw cards for player and dealer. for current in ('dealer', 'player'): for i in range(0, 2): card = self.deck.draw_card() self.hands[current].add(card) @staticmethod def format_card(card): """ Displays a single card tuple """ card_value = str(card[1]).capitalize() card_suit = card[0].capitalize() return "{} of {}".format(card_value, card_suit) def display_cards(self, show_all=False): """ Display all cards for the player and dealer. """ message = "{}'s cards: {}" for player in ['dealer', 'player']: # Format the cards correctly. cards = [ self.format_card(card) for card in self.hands[player].cards ] # If it's the player's turn, do not display the second card of the dealer. if not show_all and player in 'dealer': cards[1] = '--hidden--' # Print the message. print(message.format(player.capitalize(), ' | '.join(cards))) # Empty line. print() def player_input(self): """ Ask player for input. """ while True: action = input( "Do you want to Hit or Stay? Enter 'h' for hit, and 's' for stay: " ) if action not in ['h', 's']: print( "You can only enter 'h' for hit, and 's' for stay. Please try again.\n" ) else: break return action def display_totals(self): """ Display the totals for this round. """ print() print("---- Results for this round ----") self.display_cards(show_all=True) print("Dealer total is: {}".format(self.hands['dealer'].total)) print("Player total is: {}".format(self.hands['player'].total)) def player_result(self, outcome): """ Player has either won or lost this round. """ self.display_totals() if outcome == 'win': self.wallet.add_money(self.bet * 2) message = 'You won this round and doubled your bet of {}.' elif outcome == 'lose': self.wallet.subtract_amount(self.bet) message = 'You lost this round and your bet of {}.' print(message.format(self.bet)) print('Coins in your wallet are now: {}'.format( self.wallet.get_balance())) def check_blackjack(self, person): """ Check if a person has blackjack. """ if self.hands[person].total == 21: # If the player has more 21, he instantly won. print("{} has BLACKJACK!!!!".format(person.capitalize())) def play_game(self): # Play until game is not continued. continue_game = True while continue_game: # Play another round. self.play_round() # Once complete, ask if the player wants to play again. while True: # If user is out of money, he cannot play again. if self.wallet.balance == 0: print('You are broke and cannot play any more.') continue_game = False break # If user has money left, ask if he wants to play play_again = input('Do you want to play anther round (y/n): ') if play_again.lower() not in ['y', 'n']: print('Invalid choice. Please enter y or n only.') elif play_again == 'y': print('Alright. Let\'s play again.') break else: print('Thank you for playing.') if self.wallet.balance > self.wallet.initial_balance: print('You made some coins. Congrats.') else: print( 'You lost money, but at least you are not broke.') continue_game = False break def play_round(self): """ Play another round. """ # Reset everything. self.reset_game() # Ask player for their bet. self.ask_bet() # Draw initial set of cards. self.draw_initial_cards() # Print out first cards that were dealt. self.display_cards() # Indicate if round is complete. round_complete = False # Indicate if player already won this turn. player_won = False # Edge case: Player starts with a blackjack. if self.check_blackjack('player'): player_won = True self.player_result('win') return True # Ask player for actions. while True: player_action = self.player_input() if player_action == 'h': # Draw a new card. card = self.deck.draw_card() self.hands['player'].add(card) self.display_cards() if self.check_blackjack('player'): player_won = True self.player_result('win') break elif self.hands['player'].total > 21: # If the player has more than 21, he instantly lost. self.player_result('lose') round_complete = True break else: print('You finished your turn. Now let the dealer play.') break # Dealer gets to play if player did not win already. if not player_won and not round_complete: self.display_cards(show_all=True) while True: # If the dealer has more than the player and less than 21, dealer wins. if self.hands['dealer'].total < 21 and self.hands[ 'dealer'].total > self.hands['player'].total: self.player_result('lose') break elif self.check_blackjack('dealer'): self.player_result('lose') break elif self.hands['dealer'].total > 21: self.player_result('win') break else: print('Dealer will hit again') # Wait for effect. sleep(3) # Let the dealer pick a card. card = self.deck.draw_card() self.hands['dealer'].add(card) self.display_cards(show_all=True)
class Blackjack(): def __init__(self): # Set up the player's wallet. self.wallet = Wallet() # Create a way to generate new cards. self.deck_generator = DeckGenerator() # Reset the game. self.reset_game() def reset_game(self): """ Reset all game variables for a new round. """ # The player always goes first. self.current_turn = 'player' # Set the current cards to an empty array. self.cards = {'dealer': [], 'player': []} # Set the totals for each player. self.totals = {'dealer': 0, 'player': 0} # Create a new new deck of cards. self.deck = self.deck_generator.get_new_deck() def ask_bet(self): """ Ask a player for the current round's bet. """ balance = self.wallet.get_balance() message = '\nYou have {balance} remaining. Enter your bet: '.format( balance=balance) while True: try: self.bet = int(input(message)) except: print('Please enter a number. Try again.') continue else: if self.bet > balance: print( 'You cannot bet more than you have. Please enter a smaller number.' ) continue else: print('You bet {} for this round.'.format(self.bet)) break def draw_card(self): """ Draw a single card and return it. """ index_options = len(self.deck) - 1 random_index = randint(0, index_options) return self.deck.pop(random_index) def draw_initial_cards(self): """ Draw initial cards for player and dealer. """ # Draw cards for player and dealer. for current in ('dealer', 'player'): for i in range(0, 2): card = self.draw_card() self.cards[current].append(card) @staticmethod def format_card(card): """ Displays a single card tuple """ card_value = str(card[1]).capitalize() card_suit = card[0].capitalize() return "{} of {}".format(card_value, card_suit) def display_cards(self): """ Display all cards for the player and dealer. """ message = "{}'s cards: {}" for player in ['dealer', 'player']: # Format the cards correctly. cards = [self.format_card(card) for card in self.cards[player]] # If it's the player's turn, do not display the second card of the dealer. if self.current_turn == 'player' and player == 'dealer': cards[1] = '--hidden--' # Print the message. print(message.format(player.capitalize(), ' | '.join(cards))) # Empty line. print() def player_input(self): """ Ask player for input. """ while True: action = input( "Do you want to Hit or Stay? Enter 'h' for hit, and 's' for stay: " ) if action not in ['h', 's']: print( "You can only enter 'h' for hit, and 's' for stay. Please try again.\n" ) else: break return action def tally_up_cards(self): """ Tally up all the cards for each player. """ for player in ['dealer', 'player']: self.totals[player] = self.check_cards(player) def check_cards(self, player): """ Check the cards for the specified player. """ total = 0 for card in self.cards[player]: # Number cards can simply be added. if isinstance(card[1], int): total = total + card[1] # People cards have a value of 10. if card[1] in ['jack', 'queen', 'king']: total = total + 10 # Handle aces separately. # Find the best combination for aces. # 1 ace: 1 or 11 # 2 aces: 1,1, or 11,1 (all other combos go over) # 3 aces: 1,1,1 or 11,1,1 (all other combos go over) # 4 aces: 1,1,1,1 or 11,1,1,1 (all other combos go over) aces = list(filter(lambda card: card[1] == 'ace', self.cards['player'])) if len(aces) == 1: if (total + 11) > 21: total = total + 1 else: total = total + 11 elif len(aces) == 2: if (total + 12) > 21: total = total + 2 else: total = total + 12 elif len(aces) == 3: if (total + 13) > 21: total = total + 3 else: total = total + 13 elif len(aces) == 4: if (total + 14) > 21: total = total + 4 else: total = total + 14 return total def display_totals(self): """ Display the totals for this round. """ print() print("---- Results for this round ----") self.display_cards() print("Dealer total is: {}".format(self.totals['dealer'])) print("Player total is: {}".format(self.totals['player'])) def player_result(self, outcome): """ Player has either won or lost this round. """ self.display_totals() if outcome == 'win': self.wallet.add_money(self.bet * 2) message = 'You won this round and doubled your bet of {}.' elif outcome == 'lose': self.wallet.subtract_amount(self.bet) message = 'You lost this round your bet of {}.' print(message.format(self.bet)) print('Coins in your wallet are now: {}'.format( self.wallet.get_balance())) def play_game(self): # Play until game is not continued. continue_game = True while continue_game: # Play another round. self.play_round() # Once complete, ask if the player wants to play again. while True: # If user is out of money, he cannot play again. if self.wallet.balance == 0: print('You are broke and cannot play any more.') continue_game = False break # If user has money left, ask if he wants to play play_again = input('Do you want to play anther round (y/n): ') if play_again.lower() not in ['y', 'n']: print('Invalid choice. Please enter y or n only.') elif play_again == 'y': print('Alright. Let\'s play again.') break else: print('Thank you for playing.') if self.wallet.balance > self.wallet.initial_balance: print('You made some money. Congrats') else: print( 'You lost money, but at least you are not broke.') continue_game = False break def play_round(self): """ Play another round. """ # Reset everything. self.reset_game() # Ask player for their bet. self.ask_bet() # Draw initial set of cards. self.draw_initial_cards() # Print out first cards that were dealt. self.display_cards() # Tall up initial cards. self.tally_up_cards() # Indicate if round is complete. round_complete = False # Indicate if player already won this turn. player_won = False # Edge case: Player starts with a blackjack. if self.totals['player'] == 21: # If the player has more 21, he instantly won. print("BLACKJACK!!!!") player_won = True self.player_result('win') return True # Ask player for actions. while True: player_action = self.player_input() if player_action == 'h': # Draw a new card. card = self.draw_card() self.cards[self.current_turn].append(card) self.display_cards() self.tally_up_cards() if self.totals['player'] == 21: # If the player has more 21, he instantly won. print("BLACKJACK!!!!") player_won = True self.player_result('win') break elif self.totals['player'] > 21: # If the player has more than 21, he instantly lost. self.player_result('lose') round_complete = True break else: print('You finished your turn. Now let the dealer play.') break # Dealer gets to play if player did not win already. if not player_won and not round_complete: self.current_turn = 'dealer' self.display_cards() while True: # If the dealer has more than the player and less than 21, dealer wins. if self.totals['dealer'] < 21 and self.totals[ 'dealer'] > self.totals['player']: self.player_result('lose') break elif self.totals['dealer'] == 21: print('Dealer has Blackjack') self.player_result('lose') break elif self.totals['dealer'] > 21: self.player_result('win') break else: print('Dealer will hit again') # Wait for effect. sleep(3) # Let the dealer pick a card. card = self.draw_card() self.cards[self.current_turn].append(card) self.display_cards() self.tally_up_cards()