Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

PYTHON CODE:: Chapter 9 Assignment (25 pts.): Blackjack Simulation Previously in

ID: 3849944 • Letter: P

Question

PYTHON CODE::

Chapter 9 Assignment (25 pts.):

Blackjack Simulation

Previously in this chapter you saw the card_dealer.py program that simulates cards being dealt from a deck. Enhance the program so it simulates a simplified version of the game of

Blackjack between two virtual players. The cards have the following values:

Numeric cards are assigned the value they have printed on them. For example, the value of the 2 of spades is 2, and the value of the 5 of diamonds is 5.

Jacks, queens, and kings are valued at 10.

Aces are valued at 1 or 11, depending on the player’s choice.

The program should deal cards to each player until one player’s hand is worth more than

21 points. When that happens, the other player is the winner. (It is possible that both players’ hands will simultaneously exceed 21 points, in which case neither player wins.) The program should repeat until all the cards have been dealt from the deck.

If a player is dealt an ace, the program should decide the value of the card according to the following rule: The ace will be worth 11 points, unless that makes the player’s hand exceed

21 points. In that case, the ace will be worth 1 point.

Sample Output:

>>>

Player 1 was dealt 8 of Hearts

Player 2 was dealt 4 of Hearts

Player 1 was dealt 5 of Diamonds

Player 2 was dealt 7 of Diamonds

Player 1 was dealt 10 of Clubs

Player 2 was dealt 9 of Clubs

Player 2 wins.

>>>

# This program uses a dictionary as a deck of cards.

def main():
# Create a deck of cards.
deck = create_deck()

# Get the number of cards to deal.
num_cards = int(input('How many cards should I deal? '))

# Deal the cards.
deal_cards(deck, num_cards)

# The create_deck function returns a dictionary
# representing a deck of cards.
def create_deck():
# Create a dictionary with each card and its value
# stored as key-value pairs.
deck = {'Ace of Spades':1, '2 of Spades':2, '3 of Spades':3,
'4 of Spades':4, '5 of Spades':5, '6 of Spades':6,
'7 of Spades':7, '8 of Spades':8, '9 of Spades':9,
'10 of Spades':10, 'Jack of Spades':10,
'Queen of Spades':10, 'King of Spades': 10,
  
'Ace of Hearts':1, '2 of Hearts':2, '3 of Hearts':3,
'4 of Hearts':4, '5 of Hearts':5, '6 of Hearts':6,
'7 of Hearts':7, '8 of Hearts':8, '9 of Hearts':9,
'10 of Hearts':10, 'Jack of Hearts':10,
'Queen of Hearts':10, 'King of Hearts': 10,
  
'Ace of Clubs':1, '2 of Clubs':2, '3 of Clubs':3,
'4 of Clubs':4, '5 of Clubs':5, '6 of Clubs':6,
'7 of Clubs':7, '8 of Clubs':8, '9 of Clubs':9,
'10 of Clubs':10, 'Jack of Clubs':10,
'Queen of Clubs':10, 'King of Clubs': 10,
  
'Ace of Diamonds':1, '2 of Diamonds':2, '3 of Diamonds':3,
'4 of Diamonds':4, '5 of Diamonds':5, '6 of Diamonds':6,
'7 of Diamonds':7, '8 of Diamonds':8, '9 of Diamonds':9,
'10 of Diamonds':10, 'Jack of Diamonds':10,
'Queen of Diamonds':10, 'King of Diamonds': 10}

# Return the deck.
return deck

# The deal_cards function deals a specified number of cards
# from the deck.

def deal_cards(deck, number):
# Initialize an accumulator for the hand value.
hand_value = 0

# Make sure the number of cards to deal is not
# greater than the number of cards in the deck.
if number > len(deck):
number = len(deck)

# Deal the cards and accumulate their values.
for count in range(number):
card, value = deck.popitem()
print(card)
hand_value += value

# Display the value of the hand.
print('Value of this hand:', hand_value)

# Call the main function.
main()

Explanation / Answer

import sys
import os
import random

deck = None
stats = {'player':{'win':0,'lose':0,'tie':0,'blackjack':0},'dealer'{'win':0,'lose':0,'tie':0,'blackjack':0}}
history = {'bets':[]} #use later to log playing history

def NewBlackjackGame():
player = Player("Player 1")
dealer = Player("Dealer")
game = Game(player, dealer,[])
round_number = 1
while player.credits > 1:
print('### Round ' + str(round_number) + ' ###')
game.play_round()
round_number = round_number + 1
if player.credits < 1:
print('You are out of credits. Game over.')

class Hand():
def __init__(self, owner):
self.owner = owner
self.cards =[]
self.values=[]
self.total = self.get_total()

def show_hand(self,dealer_turn):
if self.owner == "Player 1":
print(self.owner + ' current hand: ' + str(self.cards) + ' for a total of: ' + str(self.get_total()))
if self.owner == "Dealer" and dealer_turn==0:
print('Dealer shows: ' + self.cards[0] + ' and <card face down>') #don't show the card in the hole
if self.owner == "Dealer" and dealer_turn==1:
print(self.owner + ' current hand: ' + str(self.cards) + ' for a total of: ' + str(self.get_total()))

def draw_card(self):
global deck
new_card = deck.draw()
self.cards.append(new_card)
self.values.append(deck.values_lookup[new_card])
if "A" in self.cards:
self.adjust_ace_value()
self.total = self.get_total()

def adjust_ace_value(self):
global deck
total_of_non_ace_cards = sum(deck.values_lookup[i] for i in self.cards if i != 'A')
if total_of_non_ace_cards <= 10:
self.values[self.cards.index('A')]=11
else:
self.values[self.cards.index('A')]=1

def clear_hand(self):
del self.cards[:]
del self.values[:]

def get_total(self):
return sum(c for c in self.values)

class Game():
def __init__(self, player, dealer, stats):
self.player = player
self.dealer = dealer
self.stats = stats

def hit_or_stand(self):
#choice = raw_input('Continue or stop? You have a ' + str(self.get_bust_probability(self.player.hand,self.dealer.hand)) + ' percent probability of busting') #use this later when I help the player if they need help
choice = raw_input('Press any key to Hit, or "s" to [s]tand > ')
if choice == "s":
return 0
else:
return 1

def increment_stats(self,player,cat):
global stats
if player == 'player' and cat == 'win':
stats['player']['win'] = stats['player']['win'] +1
stats['dealer']['lose'] = stats['dealer']['lose'] +1
if player == 'player' and cat == 'lose':
stats['player']['lose'] = stats['player']['lose'] +1
stats['dealer']['win'] = stats['dealer']['win'] +1
if player == 'player' and cat == 'blackjack':
stats['player']['blackjack'] = stats['player']['blackjack'] +1
stats['dealer']['lose'] = stats['dealer']['lose'] +1
if player=='dealer' and cat == 'blackjack':
stats['player']['lose'] = stats['player']['lose'] +1
stats['dealer']['blackjack'] = stats['dealer']['blackjack'] +1
if player == 'player' and cat == 'tie':
stats['player']['tie'] = stats['player']['tie'] +1
stats['dealer']['tie'] = stats['dealer']['tie'] +1
def play_round(self):
global deck
global history
deck = Deck()
deck.shuffle()
self.player.hand.clear_hand()
self.dealer.hand.clear_hand()
initial_bet = 0
dealer_turn =0 #is it the dealer's turn?
hit = None # 1 is player and 0 is dealer
winner = None# -1 for dealer, 1 for player, 0 for tie
while initial_bet < 1 or initial_bet > self.player.credits:
try:
initial_bet = int(raw_input('How much would you like to bet? You have ' + str(self.player.credits) + ' credits. '))
if initial_bet < 1:
print('Please bet at least 1 credit')
if initial_bet > self.player.credits:
print('You do not have sufficient credits to make this wager. You have ' + str(self.player.credits) + ' credits left.')
except ValueError:
print('That was an invalid number. Please enter a value >= 1')
print('You bet ' + str(initial_bet))
self.player.change_credits(-initial_bet)
history['bets'].append(initial_bet)

for i in range(2):
self.player.hand.draw_card()
self.dealer.hand.draw_card()
self.player.hand.show_hand(dealer_turn)
self.dealer.hand.show_hand(dealer_turn)
if self.player.hand.total < 21:
hit = self.hit_or_stand()
if self.player.hand.total == 21:
print('Player Blackjack!')
self.increment_stats('player', 'blackjack')
self.player.change_credits(initial_bet*2.5) #3:2 returns for blackjack
winner = 1

while self.player.hand.total < 21 and hit and winner == None:
self.player.hand.draw_card()
self.player.hand.show_hand(dealer_turn)
if self.player.hand.total > 21:
print('Player bust!')
self.increment_stats('player', 'lose')
winner = -1
break
hit = self.hit_or_stand()
if hit == 0 and winner == None:
print('Player stands. Dealer turn')
dealer_turn = 1
self.dealer.hand.show_hand(dealer_turn)
if self.dealer.hand.total == 21 and self.player.hand.total < 21:
print('Dealer Blackjack!')
self.increment_stats('dealer', 'blackjack')
winner = -1
if self.dealer.hand.total == 21 and self.player.hand.total == 21 and len(self.player.hand.card) ==2:
print('Push! You have tied. You will get back your initial wager.')
self.player.change_credits(int(initial_bet))
self.increment_stats('player', 'tie')   
winner = 0
if self.dealer.hand.total > 17 and self.dealer.hand.total > self.player.hand.total:
print('Dealer wins!')
self.increment_stats('player', 'lose')
winner = -1
while self.dealer.hand.total < 17 and winner == None:
print('Dealer draws card...')
self.dealer.hand.draw_card()
self.dealer.hand.show_hand(dealer_turn)
if self.dealer.hand.total < 21 and winner == None:
if self.dealer.hand.total > self.player.hand.total:
print('Dealer wins!')
self.increment_stats('player', 'lose')
winner = -1
if self.dealer.hand.total == self.player.hand.total:
print('Push! You have tied. You will get back your initial wager.')
self.player.change_credits(int(initial_bet))
self.increment_stats('player', 'tie')
winner = 0
if self.dealer.hand.total < self.player.hand.total:
print('Player 1 wins!')
self.player.change_credits(2*int(initial_bet))
self.increment_stats('player', 'win')
winner = 1
if self.dealer.hand.total>21 and winner == None:
print('Dealer bust. Player wins!')
self.player.change_credits(2*int(initial_bet))
self.increment_stats('player', 'win')
winner = 1
print('Your current credit is: ' + str(self.player.credits))

def get_bust_probability(self,player_hand,dealer_hand):
global deck
margin = 21 - player_hand.total
deck.card_values.append(deck.values_lookup[dealer_hand.cards[1]])
over_margin = len([c for c in deck.card_values if c > margin])
deck.card_values.remove(deck.values_lookup[dealer_hand.cards[1]])
return round((over_margin/len(Deck().cards))*100.0)

class Deck():
def __init__(self):
self.values_lookup = {'A':1,'2':2,'3':3,'4':4, '5':5,'6':6,'7':7,'8':8,'9':9,'10':10,'J':10,'K':10,'Q':10}
self.cards = list(self.values_lookup.keys())*4
self.card_values = list(self.values_lookup.values())*4

def shuffle(self):
random.shuffle(self.cards)

def draw(self):
self.card_values.remove(self.values_lookup[self.cards[0]]) #update the values list
return self.cards.pop(0)

def cards_left(self):
return len(self.cards)

class Player():
def __init__(self, name):
self.credits = 100
self.hand = Hand(name)

def get_credits(self):
return self.credits

def change_credits(self,value):
self.credits = self.credits + value

def main():
NewBlackjackGame()

if __name__ == '__main__':
main()