Skip to content

Instantly share code, notes, and snippets.

@calebreister
Last active August 29, 2015 13:57
Show Gist options
  • Save calebreister/9621947 to your computer and use it in GitHub Desktop.
Save calebreister/9621947 to your computer and use it in GitHub Desktop.
This is a console implementation of the game 21 (Blackjack). I did it in C++ for CS161, but now I have redone it in Python and made it more "Pythonic".
'''
Game logic for 21 aka Blackjack
'''
import util
class WinReason:
PLAYER_BUST, DEALER_BUST, PLAYER_21, DEALER_21 = range(4)
# Much of Python is convention, the developer saw no need
# for extra features such as const declarations
DECK_SIZE = 52
PLAYER_SIZE = 10
DEALER_SIZE = 10
'''
FUNCTION: cardValue
DESCRIPTION: Returns the input card's value (in the context of 21)
- Ace turns into 11 (and 1 if time)
- Face cards are 10
- All other cards are their rank
PARAMETERS:
card (I) - the card to get the point value of
RETURN VALUES: the point value of the card
'''
def cardValue(card):
val = card % 100
if val == 13 or val == 12 or val == 11:
return 10
elif card % 100 == 1:
return 11
else:
return card % 100
'''
FUNCTION: drawCard
DESCRIPTION: returns the top card off the deck
The top card is the first card in the given array
that has a value greater than 0. After pulling the value,
replace it with a 0.
PARAMETERS:
deck (I/O) - the array from which to pull the card,
output because the value pulled is also replaced with a 0
size (I) - the size of the deck
RETURN VALUES:
if deck is empty return 0
'''
def drawCard(deck):
for i in range(len(deck)):
if deck[i] == 0:
#dynamically remove deck item
deck.remove(deck[i])
top = deck[0]
deck.remove(deck[0])
return top
'''
FUNCTION: handSum
DESCRIPTION: computes and returns the sum of the given hand
PARAMETERS:
hand (I) - the hand to sum
RETURN VALUES: the sum of the hand
'''
def handSum(hand):
cardSum = 0
for i in range(len(hand)):
cardSum += cardValue(hand[i])
return cardSum
'''
FUNCTION: CountCards
DESCRIPTION: count the number of items without a value of 0 in an array
PARAMETERS:
-I deck[]: the array to count
-I size: the size of the array
RETURN VALUES: the number of nonzero items in the array
'''
def countCards(deck):
count = 0
for i in range(len(deck)):
if deck[i] != 0:
count += 1
return count
'''
FUNCTION: AskPlayer
DESCRIPTION: prompts the user with a yes or no question
PARAMETERS:
-I question: the yes-no question to ask
RETURN VALUES:
true if user input is 'y'
false otherwise
'''
def askPlayer(question):
print("\n[Y/N]", question, end=' ')
ans = input()
if ans == 'y' or input == 'Y':
return True
else: return False
'''
FUNCTION: PlayHand
DESCRIPTION: the game logic implementation of 21
PARAMETERS:
-I/O deck[]: the deck to use and manipulate
RETURN VALUES: enumerated
- PLAYER_BUST: if player gets total over 21
- PLAYER_21: condition shown at end
- DEALER_BUST: if dealer gets total over 21
- DEALER_21: condition shown at endy
'''
def playHand(deck):
player = [0, 0]
dealer = [0, 0]
for i in range(2):
#In Python, it appears that everything is dynamic
player.append(drawCard(deck))
dealer.append(drawCard(deck))
print(player)
print(dealer)
util.handPrint(dealer, "Dealer's Hand:", False, True)
util.handPrint(player, "Your Hand:")
while handSum(player) <= 21:
if askPlayer("Do you want another card?"):
player.append(drawCard(deck))
util.handPrint(player, "", False)
#Dealer won
if handSum(player) > 21:
return WinReason.PLAYER_BUST
util.handPrint(dealer, "Dealer's Hand:")
while handSum(dealer) < 17:
dealer.append(drawCard(deck))
util.handPrint(dealer, "Dealer's hand:")
#player wins
if handSum(dealer) > 21:
return WinReason.DEALER_BUST
if handSum(dealer) >= handSum(player):
return WinReason.DEALER_21#dealer wins
else: return WinReason.PLAYER_21#player wins
#!/usr/bin/env python3.3
import random
from game import *
deck = util.deckInit()
random.shuffle(deck)
print(deck)
#Creating the Pythonic equivalent of a do...while loop
#create an infinte loop and then a fail condition
#fairly common, although poor practice
while True:
winner = playHand(deck)
print()
if winner == WinReason.PLAYER_BUST:
print("\nThe dealer won (you busted).")
elif winner == WinReason.PLAYER_21:
print("\nYou won (you got a 21)!")
elif winner == WinReason.DEALER_BUST:
print("\nYou won (the dealer busted)!")
elif winner == WinReason.DEALER_21:
print("\nThe dealer won (you don't have a 21).")
#exit condition
#not is not a function, it is an operator
if not(countCards(deck) > 15 and
askPlayer("Do you want to play again?")):
break
'''
Card iing key:
- rank will be A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, or K
- suit will be displayed using the ASCII character
values 3 (heart), 4 (diamond), 5 (club), 6 (spade)
- takes a 3 digit number denoting the suit and card number
- 1st digit is the ASCII value of the suit
- Last 2 digits are the number of card
- 305 = 3 of hearts
- 512 = Jack of clubs
'''
'''
FUNCTION: DeckInit
DESCRIPTION: Initializes a "deck" of 52 cards to the correct numbers
and suits
RETURN: The generated deck
'''
def deckInit():
i = 0
card = 0
deck = []
while i < 13:
deck.append(card + 1 + 300)
card += 1
i += 1
card = 0
while i < 26:
deck.append(card + 1 + 400)
card += 1
i += 1
card = 0
while i < 39:
deck.append(card + 1 + 500)
card += 1
i += 1
card = 0
while i < 52:
deck.append(card + 1 + 600)
card += 1
i += 1
card = 0
return deck
# The deck can be printed directly, Python does not need to loop through and print
'''
Gets the suit of a card and outputs the unicode
value of the suit.
'''
def getSuit(card):
suit = int(card / 100)
if suit == 3: # heart
return '\u2665'
elif suit == 4: # diamond
return '\u2666'
elif suit == 5: # club
return '\u2663'
elif suit == 6: # spade
return '\u2660'
'''
FUNCTION: CardPrint
DESCRIPTION: displays the given card's rank and suit
PARAMETERS:
-I card: the card value to print
RETURN VALUES: prints the card and suit character
'''
def cardPrint(card):
num = card % 100
if num == 13: # king
print('K', getSuit(card), sep='', end=' ')
elif num == 12: # queen
print('Q', getSuit(card), sep='', end=' ')
elif num == 11: # jack
print('J', getSuit(card), sep='', end=' ')
elif num == 1: # ace
print('A', getSuit(card), sep='', end=' ')
else:
print(num, getSuit(card), sep='', end=' ')
'''
FUNCTION: HandPrint
DESCRIPTION: prints an array of cards with the option to hide the first,
uses the same numbering system as CardPrint()
PARAMETERS:
-I cards[]: the cards to print
-I CardCount: number of cards to print
-I message: message to print in front of cards
-I OwnLine: creates new line for cards to print
-I HideTopCard: option to hide the top card (for the dealer in 21)
RETURN VALUES: prints cards
'''
def handPrint(cards, message, ownLine=True, hideTopCard=False):
i = 0
if ownLine:
print()
print(message, end=' ')
if hideTopCard:
print('XX', end=' ')
i = 1
for i in range(i, len(cards)):
#assert i < len(cards)
if cards[i] == 0:
continue
cardPrint(int(cards[i]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment