Problem Statement

Modified Blackjack

  1. The game consists of a single player playing against the dealer, played by our program in this example.
  2. Each player is initially dealt two cards from a standard 52 card deck. Each card's value is its face value, with face cards having a value of 10, and aces are valued 11.
  3. The object of the game is to get a higher total value than the other player, without going over 21.
  4. The game consists of several steps:
    1. Both the player and the dealer review the two cards they are dealt. Both the player and the dealer can see the opponent's hand as well.
    2. The player is given the option to draw additional cards. The player may continue to draw cards until she or he chooses to stop, or their total value is greater than 21.
    3. If the player stops before going over 21, the dealer must draw cards to try and beat the player. The dealer stops drawing cards either when their total beats the player, or the dealer's total is greater than 21.
    4. At the end, the participant with the greatest card value that is less than or equal to 21 wins the game. If it is a tie, the dealer wins.

*~*sigh*~*

Image Credit: Giphy

Let's break it down into smaller parts

Use Classes!

Image Credit: Giphy

Let's break it down into classes

class Card:
  
class Card:

Properties

@property def suit(self): return self.__suit

@property def name(self): return self.__name

@property def value(self): return self.__value

class Card:

# Properties …

class Card:

def init(self, a_suit, a_number):

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit this.__name = str(a_number) this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit this.__name = str(a_number) this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit if:

else:
  <mark>this.__name = str(a_number)
  this.__value = a_number</mark>

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit if a_number == 1:

else:
  this.__name = str(a_number)
  this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit if a_number == 1: this.__name = “Ace” this.__value = 11 else: this.__name = str(a_number) this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit if a_number == 1: this.__name = “Ace” this.__value = 11 elif a_number == 11: this.__name = “Jack” this.__value = 10 elif a_number == 12: this.__name = “Queen” this.__value = 10 elif a_number == 13: this.__name = “King” this.__value = 10 else: this.__name = str(a_number) this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number): this.__suit = a_suit if a_number == 1: this.__name = “Ace” this.__value = 11 elif a_number == 11: this.__name = “Jack” this.__value = 10 elif a_number == 12: this.__name = “Queen” this.__value = 10 elif a_number == 13: this.__name = “King” this.__value = 10 else: this.__name = str(a_number) this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number): if not (a_suit == “Spades” or a_suit == “Hearts” or a_suit == “Clubs” or a_suit == “Diamonds”): raise ValueError(“The suit must …") if a_number < 1 or a_number > 13: raise ValueError(“The card number …") this.__suit = a_suit if a_number == 1: this.__name = “Ace” this.__value = 11 elif a_number == 11: this.__name = “Jack” this.__value = 10 elif a_number == 12: this.__name = “Queen” this.__value = 10 elif a_number == 13: this.__name = “King” this.__value = 10 else: this.__name = str(a_number) this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number): if not (a_suit == “Spades” or a_suit == “Hearts” or a_suit == “Clubs” or a_suit == “Diamonds”): raise ValueError(“The suit must …") if a_number < 1 or a_number > 13: raise ValueError(“The card number …") this.__suit = a_suit if a_number == 1: this.__name = “Ace” this.__value = 11 elif a_number == 11: this.__name = “Jack” this.__value = 10 elif a_number == 12: this.__name = “Queen” this.__value = 10 elif a_number == 13: this.__name = “King” this.__value = 10 else: this.__name = str(a_number) this.__value = a_number

Properties …

class Card:

def init(self, a_suit, a_number):

Properties …

class Card:

def init(self, a_suit, a_number): …

Properties …

def str(self): return “{} of {}".format(this.__name, this.__suit)

class Deck:

from Card import *

class Deck:

from Card import *

class Deck:

def init(self):

from Card import *

class Deck:

def init(self): self.__card_deck = []

from Card import *

class Deck:

def init(self): self.__card_deck = [] suits = [“Spades”, “Hearts”, “Diamonds”, “Clubs”] for suit in suits:

from Card import *

class Deck:

def init(self): self.__card_deck = [] suits = [“Spades”, “Hearts”, “Diamonds”, “Clubs”] for suit in suits: for i in range(1, 14): self.__card_deck.append(Card(suit, i))

from Card import *

class Deck:

def init(self): self.__card_deck = [] suits = [“Spades”, “Hearts”, “Diamonds”, “Clubs”] for suit in suits: for i in range(1, 14): self.__card_deck.append(Card(suit, i))

from Card import *

class Deck:

def init(self): self.__card_deck = [] suits = [“Spades”, “Hearts”, “Diamonds”, “Clubs”] for suit in suits: for i in range(1, 14): self.__card_deck.append(Card(suit, i))

def str(self): output = "” for a_card in self.__card_deck: output += str(a_card) + “\n” return output

Let's Test It!

from Deck import *

class Main:

@staticmethod def main(): a_deck = Deck() print(a_deck)

if name == “main": Main.main()

from Deck import *

class Main:

@staticmethod def main(): a_deck = Deck() print(a_deck)

if name == “main": Main.main()

from Card import *

class Deck:

def init(self): … def str(self): …

from Card import *

class Deck:

def init(self): … def str(self): …

def shuffle(self, times):

from Card import *

class Deck:

def init(self): … def str(self): …

def shuffle(self, times): for i in range(0, times):

import random
from Card import *

class Deck:

def init(self): … def str(self): …

def shuffle(self, times): for i in range(0, times): first = random.randint(0, 52) second = random.randint(0, 52)

import random
from Card import *

class Deck:

def init(self): … def str(self): …

def shuffle(self, times): for i in range(0, times): first = random.randint(0, 52) second = random.randint(0, 52) if first != second: temp = self.__card_deck[first] self.__card_deck[first] = self.__card_deck[second] self.__card_deck[second] = temp

import random
from Card import *

class Deck:

def init(self): … def str(self): …

def shuffle(self, times): if times <= 0: raise ValueError(“The deck must …") for i in range(0, times): first = random.randint(0, 52) second = random.randint(0, 52) if first != second: temp = self.__card_deck[first] self.__card_deck[first] = self.__card_deck[second] self.__card_deck[second] = temp

import random
from Card import *

class Deck:

def init(self): … def str(self): …

def shuffle(self, times): if times <= 0: raise ValueError(“The deck must …") for i in range(0, times): first = random.randint(0, 52) second = random.randint(0, 52) if first != second: temp = self.__card_deck[first] self.__card_deck[first] = self.__card_deck[second] self.__card_deck[second] = temp

Let's Test It!

from Deck import *

class Main:

@staticmethod def main(): a_deck = Deck() a_deck.shuffle(1000) print(a_deck)

if name == “main": Main.main()

from Deck import *

class Main:

@staticmethod def main(): a_deck = Deck() a_deck.shuffle(1000) print(a_deck)

if name == “main": Main.main()

import random
from Card import *

class Deck:

def init(self): … def str(self): … def shuffle(self, times): …

import random
from Card import *

class Deck:

def init(self): … def str(self): … def shuffle(self, times): …

def draw(self):

import random
from Card import *

class Deck:

def init(self): … def str(self): … def shuffle(self, times): …

def draw(self): output = self.__card_deck[self.__card_position] self.__card_position += 1 return output

import random
from Card import *

class Deck:

def init(self): self.__card_position = 0

def str(self): … def shuffle(self, times): …

def draw(self): output = self.__card_deck[self.__card_position] self.__card_position += 1 return output

import random
from Card import *

class Deck:

def init(self): self.__card_position = 0 …

def str(self): … def shuffle(self, times): …

def draw(self): output = self.__card_deck[self.__card_position] self.__card_position += 1 return output

class Hand:

from Card import *

class Hand:

from Card import *

class Hand:

def init(self): self.__card_hand = []

from Card import *

class Hand:

def init(self): self.__card_hand = []

@property def value(self): value = 0 for card in self.__card_hand: value += card.value return value

def str(self): output = "” for card in self.__card_hand: output += str(card) + “\n” return output

from Card import *

class Hand:

def init(self): self.__card_hand = []

@property def value(self): value = 0 for card in self.__card_hand: value += card.value return value

def str(self): output = "” for card in self.__card_hand: output += str(card) + “\n” return output

def add_card(self, input): if not isinstance(input, Card): raise ValueError(“Input must be a Card object”) self.__card_hand.append(input)

class Dealer:

from Hand import *

class Dealer:

def init(self, a_hand): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) self.__my_hand = a_hand

from Hand import *

class Dealer:

def init(self, a_hand): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) self.__my_hand = a_hand

def str(self): output = “The dealer currently holds: \n” output += str(self.__my_hand) output += “for a total of {}".format(self.__my_hand.value) return output

from Hand import *

class Dealer:

def init(self, a_hand): … def str(self): …

from Hand import *

class Dealer:

def init(self, a_hand): … def str(self): …

def make_moves(self, player_value):

from Hand import *

class Dealer:

def init(self, a_hand): … def str(self): …

def make_moves(self, player_value): while self.__my_hand.value < player_value and self.__my_hand.value <= 21: # we need to draw a card here!

from Hand import *

class Dealer:

def init(self, a_hand): … def str(self): …

def make_moves(self, player_value): while self.__my_hand.value < player_value and self.__my_hand.value <= 21: # we need to draw a card here!

Option 1: Make Deck Static

Pros:

  • Requires few code changes
  • Can use deck from anywhere

Cons:

  • Can only have one deck
  • Not standard

Option 2: Pass Deck to Dealer

Pros:

  • No modification to deck
  • More object-oriented

Cons:

  • Have to manage deck instance
  • Easy to lose objects in code
from Hand import *

class Dealer:

def init(self, a_hand): … def str(self): …

def make_moves(self, player_value): while self.__my_hand.value < player_value and self.__my_hand.value <= 21: # we need to draw a card here!

from Hand import *

class Dealer:

def init(self, a_hand, a_deck): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) if not isinstance(a_deck, Deck): raise ValueError(“A_deck must be a Hand object”) self.__my_hand = a_hand self.__the_deck = a_deck

def str(self): …

def make_moves(self, player_value): while self.__my_hand.value < player_value and self.__my_hand.value <= 21: # we need to draw a card here!

from Hand import *

class Dealer:

def init(self, a_hand, a_deck): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) if not isinstance(a_deck, Deck): raise ValueError(“A_deck must be a Hand object”) self.__my_hand = a_hand self.__the_deck = a_deck

def str(self): …

def make_moves(self, player_value): while self.__my_hand.value < player_value and self.__my_hand.value <= 21: new_card = self.__the_deck.draw() print(“The dealer draws a {}".format(str(new_card))) self.__my_hand.add_card(new_card)

from Hand import *

class Dealer:

def init(self, a_hand, a_deck): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) if not isinstance(a_deck, Deck): raise ValueError(“A_deck must be a Hand object”) self.__my_hand = a_hand self.__the_deck = a_deck

def str(self): …

def make_moves(self, player_value): while self.__my_hand.value < player_value and self.__my_hand.value <= 21: new_card = self.__the_deck.draw() print(“The dealer draws a {}".format(str(new_card))) self.__my_hand.add_card(new_card)

from Hand import *
from Deck import *

class Dealer:

def init(self, a_hand, a_deck): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) if not isinstance(a_deck, Deck): raise ValueError(“A_deck must be a Hand object”) self.__my_hand = a_hand self.__the_deck = a_deck

def str(self): output = “The dealer currently holds: \n” output += str(self.__my_hand) output += “for a total of {}".format(self.__my_hand.value) return output

from Hand import *
from Deck import *

class Dealer:

def init(self, a_hand, a_deck): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) if not isinstance(a_deck, Deck): raise ValueError(“A_deck must be a Hand object”) self.__my_hand = a_hand self.__the_deck = a_deck

def str(self): output = “The dealer currently holds: \n” output += str(self.__my_hand) output += “for a total of {}".format(self.__my_hand.value) return output

from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) if not isinstance(a_deck, Deck): raise ValueError(“A_deck must be a Hand object”) self.__my_hand = a_hand self.__the_deck = a_deck

def str(self): output = “The player currently holds: \n” output += str(self.__my_hand) output += “for a total of {}".format(self.__my_hand.value) return output

from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): if not isinstance(a_hand, Hand): raise ValueError(“A_hand must be a Hand object”) if not isinstance(a_deck, Deck): raise ValueError(“A_deck must be a Hand object”) self.__my_hand = a_hand self.__the_deck = a_deck

def str(self): output = “The player currently holds: \n” output += str(self.__my_hand) output += “for a total of {}".format(self.__my_hand.value) return output

from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

def make_moves(self):

import sys
from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

def make_moves(self): with sys.stdin as reader:

import sys
from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

def make_moves(self): with sys.stdin as reader: while self.__my_hand.value <= 21:

import sys
from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

def make_moves(self): with sys.stdin as reader: while self.__my_hand.value <= 21: print(“You currently have a value of {}".format( self.__my_hand.value)) print(“Would you like to draw another card (y/n)?: “) input = reader.readline().strip()

import sys
from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

def make_moves(self): with sys.stdin as reader: while self.__my_hand.value <= 21: print(“You currently have a value of {}".format( self.__my_hand.value)) print(“Would you like to draw another card (y/n)?: “) input = reader.readline().strip() if input == “y” or input == “Y”: new_card = self.__the_deck.draw() print(“The dealer draws a {}".format(str(new_card))) self.__my_hand.add_card(new_card) elif input == “n” or input == “N”: break; else: print(“Invalid input!")

import sys
from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

def make_moves(self): with sys.stdin as reader: while self.__my_hand.value <= 21: print(“You currently have a value of {}".format( self.__my_hand.value)) print(“Would you like to draw another card (y/n)?: “) input = reader.readline().strip() if input == “y” or input == “Y”: new_card = self.__the_deck.draw() print(“The dealer draws a {}".format(str(new_card))) self.__my_hand.add_card(new_card) elif input == “n” or input == “N”: break; else: print(“Invalid input!") print(“You end your turn with a value of {}".format( self.__my_hand.value))

import sys
from Hand import *
from Deck import *

class Player:

def init(self, a_hand, a_deck): … def str(self): …

def make_moves(self): with sys.stdin as reader: while self.__my_hand.value <= 21: print(“You currently have a value of {}".format( self.__my_hand.value)) print(“Would you like to draw another card (y/n)?: “) input = reader.readline().strip() if input == “y” or input == “Y”: new_card = self.__the_deck.draw() print(“The dealer draws a {}".format(str(new_card))) self.__my_hand.add_card(new_card) elif input == “n” or input == “N”: break; else: print(“Invalid input!") print(“You end your turn with a value of {}".format( self.__my_hand.value))

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main():

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck()

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck() the_deck.shuffle(1000)

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck() the_deck.shuffle(1000) player_hand = Hand() player_hand.add_card(the_deck.draw()) player_hand.add_card(the_deck.draw()) a_player = Player(player_hand, the_deck)

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck() the_deck.shuffle(1000) player_hand = Hand() player_hand.add_card(the_deck.draw()) player_hand.add_card(the_deck.draw()) a_player = Player(player_hand, the_deck) dealer_hand = Hand() dealer_hand.add_card(the_deck.draw()) dealer_hand.add_card(the_deck.draw()) a_dealer = Dealer(dealer_hand, the_deck)

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck() the_deck.shuffle(1000) player_hand = Hand() player_hand.add_card(the_deck.draw()) player_hand.add_card(the_deck.draw()) a_player = Player(player_hand, the_deck) dealer_hand = Hand() dealer_hand.add_card(the_deck.draw()) dealer_hand.add_card(the_deck.draw()) a_dealer = Dealer(dealer_hand, the_deck) a_player.make_moves()

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck() the_deck.shuffle(1000) player_hand = Hand() player_hand.add_card(the_deck.draw()) player_hand.add_card(the_deck.draw()) a_player = Player(player_hand, the_deck) dealer_hand = Hand() dealer_hand.add_card(the_deck.draw()) dealer_hand.add_card(the_deck.draw()) a_dealer = Dealer(dealer_hand, the_deck) a_player.make_moves() a_dealer.make_moves(player_hand.value)

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck() the_deck.shuffle(1000) player_hand = Hand() player_hand.add_card(the_deck.draw()) player_hand.add_card(the_deck.draw()) a_player = Player(player_hand, the_deck) dealer_hand = Hand() dealer_hand.add_card(the_deck.draw()) dealer_hand.add_card(the_deck.draw()) a_dealer = Dealer(dealer_hand, the_deck) a_player.make_moves() a_dealer.make_moves(player_hand.value)

<mark>if player_hand.value <= 21 and dealer_hand.value > 21:
  print("The player wins!")
elif player_hand.value <= 21 and player_hand.value > dealer_hand.value:
  print("The player wins!")
elif dealer_hand.value <= 21:
  print("The dealer wins!")
else:
  print("There is no winner")</mark>

if name == “main": Main.main()

from Deck import *
from Hand import *
from Dealer import *
from Player import *

class Main:

@staticmethod def main(): the_deck = Deck() the_deck.shuffle(1000) player_hand = Hand() player_hand.add_card(the_deck.draw()) player_hand.add_card(the_deck.draw()) a_player = Player(player_hand, the_deck) dealer_hand = Hand() dealer_hand.add_card(the_deck.draw()) dealer_hand.add_card(the_deck.draw()) a_dealer = Dealer(dealer_hand, the_deck) a_player.make_moves() a_dealer.make_moves(player_hand.value)

if player_hand.value <= 21 and dealer_hand.value > 21:
  print("The player wins!")
elif player_hand.value <= 21 and player_hand.value > dealer_hand.value:
  print("The player wins!")
elif dealer_hand.value <= 21:
  print("The dealer wins!")
else:
  print("There is no winner")

if name == “main": Main.main()

"/js/highlight.pack.js"