Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joel Thompson's Black Jack part 1 #5

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# Blackjack

* [Part 1](README_1.md)
* [Part 2](README_2.md)
The game layout uses 5 classes: Card, Deck, Player, Hand, and Game State
The Game State class will collect the deck(s) of cards and deal them as well
as implement the turn flow of the game and win/loss conditions. This is subject
to change as I code it out, possibly breaking up Game State into a couple more
classes for Shoe, Deal, Bet.
* [Part 2](README_2.md)
The layout now uses 6 classes and an interface (play_blackjack.py).
The game_state file sets up a new shoe and hands as well as the deal method.
The interface contains functions for intro display, hand display, the dealer's
logic, player's moves, and the evaluation and results for a round.
Empty file added __init__.py
Empty file.
33 changes: 33 additions & 0 deletions card.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
suits = ['♡', '♢', '♧', '♤']
ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']


class Card:
"""Playing card.

Responsibilities:

*Card has a rank, suit and value derived from the rank.
*Two cards with same rank and suit should be equal to eachother

Collaborators:

*Collected in a Deck
*Collected in a Hand for the players and a Hand for the dealer.
"""
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
if self.rank.isdigit():
self.value = int(self.rank)
elif self.rank is 'A':
self.value = 1
else:
self.value = 10

def __eq__(self, other):
"""Test equality for 2 cards."""
return self.suit == other.suit and self.rank == other.rank

def __str__(self):
return'{}{}'.format(self.rank, self.suit)
30 changes: 30 additions & 0 deletions deck.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import random
from card import Card, ranks, suits


class Deck:
"""A shuffled deck of playing cards.

Responsibilities:
*Constructs a shuffled deck containing 1 of each card.
*Allows cards to be drawn
*Should be able to report it's current size
collaborators:
+Collects 1 of each card from the Card class.
"""
def __init__(self):
self.cards = []
for rank in ranks:
for suit in suits:
card = Card(rank, suit)
self.cards.append(card)
random.shuffle(self.cards)

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

def __str__(self):
return " ".join([card.__str__() for card in self.cards])

def __eq__(self, other):
return self.__cards__ == other.__cards__
39 changes: 39 additions & 0 deletions game_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import random
from hand import Hand
from shoe import Shoe


class Game():
"""Contains the initial state of a game, as well as methods for actions and
results within the game.

Responsiblities:
*Initiates new hands for the player and dealer
*Contains the hit method for drawing cards into those hands

Collaborators:
+Collects hands from Hand
+Collects the Shoe
"""
def __init__(self):
self.player_hand = Hand()
self.dealer_hand = Hand()
self.shoe = Shoe()

def __str__(self):
return ' '.join([cards.__str__() for cards in self.player.hand])

def deal(self):
"""Method for the initial card dealing to the player and dealer."""
for _ in range(2):
self.player_hand.cards.append(self.shoe.draw())
for _ in range(2):
self.dealer_hand.cards.append(self.shoe.draw())

def hit(self):
"""Allows the player draw another card (hit)."""
self.player_hand.cards.append(self.shoe.draw())

def dealer_hit(self):
"""Allows the dealer draw another card (hit)."""
self.dealer_hand.cards.append(self.shoe.draw())
32 changes: 32 additions & 0 deletions hand.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from card import Card, ranks, suits


class Hand:
"""Contains the value for a given hand and the Ace exception rule.

*Determines the value of a given hand from the rank of each card
*Implements the ace swap if a card is an ace and the hand value < 12.

Collaborators:
+Collects Cards.
"""

def __init__(self):
self.cards = []
self.value = 0

def __str__(self):
return ' '.join([str(card) for card in self.cards])

def get_value(self):
"""Determines the value of the current hand."""
self.value = 0
for card in self.cards:
self.value += card.value
for card in self.cards:
if card.rank == 'A' and self.value < 12:
self.value += 10
if len(self.cards) == 2 and self.value == 21:
return 'BLACKJACK'
else:
return self.value
160 changes: 160 additions & 0 deletions play_blackjack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
from card import Card, ranks, suits
from deck import Deck
from player import Player
from hand import Hand
from game_state import Game
import sys


def intro():
print("="*80)
print('\n____ __ __ __ __'
'\n/ __ )/ /___ ______/ /__ / /___ ______/ /__'
'\n/ __ / / __ `/ ___/ //_/ __ / / __ `/ ___/ //_/'
'\n/ /_/ / / /_/ / /__/ ,< / /_/ / /_/ / /__/ ,<'
'\n/_____/_/\__,_/\___/_/|_| \____/\__,_/\___/_/|_|'
)
print("\n\n")
print("="*80)


def get_shoe_size():
"""Allows the player to choose 1 or 6 decks for the shoe."""
while True:
try:
shoe_size = int(input("\nPlay with 1 or 6 decks in the shoe?\n>:"))
if shoe_size == 1 or shoe_size == 6:
break
else:
print("\nLooking for a 1 or a 6...try again.")
continue
except ValueError:
print("\nLooking for a 1 or a 6...try again.")
continue
return shoe_size


def display():
"""Prints out the current hands as well as the player's bet/bank."""
print('*' * 80)
print('Dealer Hand:{} and Hole:??'.format([str(card)
for card
in game.dealer_hand.cards[1:]]))
print('*' * 80)
print('Your Hand:{}'.format([str(card)
for card
in game.player_hand.cards]))
print("Bank: {}, Bet: {}".format(player.bank, 10))
print('*' * 80)


def player_move():
move = input("(H)it or (S)tand? \n>:").lower()
if move == 'h':
game.hit()
return
elif move == 's':
return 'STAND'
else:
print("I'm sorry what was that?")
return player_move()


def dealer_move():
"""Contains the dealers simple logic."""
dealer_value = game.dealer_hand.get_value()
if len(game.dealer_hand.cards) == 2 and dealer_value == 17:
print("\nDealer hits...")
game.dealer_hit()
return 'HIT'
elif game.dealer_hand.value < 17:
print("\nDealer hits...")
game.dealer_hit()
return 'HIT'
else:
return 'STAND'


def game_flow():
"""Contains the turn scheme of the game. Including hand evaluations."""
print("\nSetting up a new game...")
game.deal()
print("\nDealing the cards...")
print("\n\nLet's begin!!!")
while True:
display()
pmove = player_move()
dmove = dealer_move()
player_value = game.player_hand.get_value()
if player_value > 21:
return
elif pmove == 'STAND' and dmove == 'STAND':
return


def results():
"""Prints the final hand values and determines the winner of the game."""
player_value = game.player_hand.get_value()
dealer_value = game.dealer_hand.get_value()
print("Your hand: {}, Value: {}".format([str(card)
for card
in game.player_hand.cards],
player_value))
print("Dealer's hand: {}, Value: {}".format([str(card)
for card
in game.dealer_hand.cards],
dealer_value))
if player_value == 'BLACKJACK' and dealer_value != 'BLACKJACK':
print("\nWhoa you got BLACKJACK!!")
player.win_blackjack(bet)
return
elif player_value > 21:
print("Oh no! You BUSTED!!")
return 'BUST'
elif player_value == 21 and dealer_value == 'BLACKJACK':
print("\nOh no! the house got BLACKJACK!!")
return
elif dealer_value > 21:
print("\nThe house busts! You win!")
player.win_no_blackjack(bet)
return
elif player_value > dealer_value:
print("\nYou beat the house!!")
player.win_no_blackjack(bet)
return
elif player_value < dealer_value:
print("\nOh no! The house wins!")
return
elif player_value == dealer_value:
print("\nAhh it's a push...")
player.push(bet)
else:
return


def get_bet():
"""Allows the player to choose their bet."""
while True:
try:
bet = int(input("\nHow much will you bet on this hand?\n>:"))
break
except ValueError:
print("\nThat was not a valid bet. Try again...")
return bet


if __name__ == "__main__":
intro()
player = Player()
shoe_size = get_shoe_size()
while player.bank > 0:
game = Game()
game.shoe.set(shoe_size)
print("\nYou have ${}".format(player.bank))
bet = get_bet()
player.bet(bet)
print("\nTaking your bet...")
game_flow()
results()
print("\n\nGet outta here!! You're broke!!")
sys.exit()
36 changes: 36 additions & 0 deletions player.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from hand import Hand


class Player:
"""Contains the Players bank.

responsibilties:
*Contains the method for decrementing the player's bet.
*Contains the methods for incrementing the players bank based
on the win/push condition (blackjack or not).

collaborators:
*Collected in the game state
"""

def __init__(self):
self.bank = 100

def __str__(self):
self.hand = ' '.join([cards.__str__() for cards in self.hand])

def bet(self, bet):
"""Decrements the bet from the player's bank."""
self.bank -= bet

def win_no_blackjack(self, bet):
"""Increments non-blackjack winnings to the player's bank."""
self.bank += bet * 2

def win_blackjack(self, bet):
"""Increments blackjack winnings to the player's bank."""
self.bank += bet * 2.5

def push(self, bet):
"""Return's the player's bet when the result is a push."""
self.bank += bet
29 changes: 29 additions & 0 deletions shoe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from deck import Deck


class Shoe():
"""Gathers the deck(s) into a shoe.

*Contains the draw() method to draw from a concatenated list of decks.

Collaborators:
+Collects decks into a shoe.
"""

def __init__(self):
self.total = Deck().cards
self.drawn_cards = []

def __str__(self):
return " ".join([cards.__str__() for cards in self.total])

def set(self, n):
"""Method to determine the number of decks (n) in the shoe."""
self.total *= n
return self.total

def draw(self):
"""Take a new card from the shoe and return it."""
new_card = self.total.pop()
self.drawn_cards.append(new_card)
return new_card
Empty file added tests/__init__.py
Empty file.
Loading