This program is an implementation of the Blackjack which is similar to what is played in the casinos.
Here were the requirements:
- I needed to create a simple text-based BlackJack game
- The game needs to have one player versus an automated dealer
- The player can stand or hit
- The player must be able to pick their betting amount
- Keep track of the player's total money
- Alert the player of wins, losses, or busts, etc...
I need advice on the following topics:
- My method and approach
- Efficiency of my code and scope for cutting it short
- Implementation of OOP
- Suggestions for best practices
- Styling approach
- Readability
- Comments and variable naming practices (Use of docstring)
Since I am new to CS and to Python and this is my first ever OOP program, please feel free to give me suggestions that could help me to better my programs in future.
import random # Random library is imported to enable us choose a random card
class Deck():
"""This is an abstract class. Player and Dealer
are meant to inherit its pick function for picking
a random card from the deck """
deck_cards = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2'] * 4
#represents all the cards in the deck
def pick(self, num):
'''
Picks the specified number of cards from the existing
desk and returns it in a form of a list.
'''
picked = []
for _ in range(num):
choosen = random.randint(0, len(self.deck_cards) - 1)
picked.append(self.deck_cards[choosen])
#Removes the card that is picked up
self.deck_cards.pop(choosen)
return picked
class Player(Deck):
"""An object of this class keeps the track of players
progress in the game including its cards, money, burst
situation. It also initiates the player with 500 units"""
cards = []
burst = False
def __init__(self):
self.money = 500
class Dealer(Deck):
"""An object of this class keeps the track of dealers
progress in the game including its cards, and burst
situation."""
cards = []
burst = False
#FUNCTIONS
def print_cards(cards):
"""prints the card value inside a box """
for i in range(len(cards)):
print("{0:^4}-----".format(''))
print("{0:^4}|{1:^3}|".format('', cards[i]))
print("{0:^4}-----".format(''))
def print_board(cards1, cards2):
"""Prints the complete board situation including both
the players as well as the dealers cards"""
print("\n"*50)
print("*************")
print("Player cards:")
print("*************")
print_cards(cards1)
print("*************")
print("Dealer cards:")
print("*************")
print_cards(cards2)
print("*************")
def find_value(cards):
"""It finds the total value of the cards"""
card_value = []
total = 0
ace = False
value_dict = {'A': 11, 'K': 10, 'Q': 10, 'J': 10, '10': 10,
'9': 9, '8': 8, '7': 7, '6': 6, '5': 5, '4': 4, '3': 3, '2': 2, }
#makes a corrosponding car_value list
for i in range(len(cards)):
card_value.append(value_dict[cards[i]])
if cards[i] == 'A':
ace = True
for i in range(len(card_value)):
total += card_value[i]
#Ace value can be 11 or 1 depending on the situation
#makes sure that the 'Ace' value is taken in player's favour
if total > 21 and ace:
total -= 10
return total
#GAMEPLAY
p1 = Player()
d1 = Dealer()
#Game stops only if the player wants to quit
#Or if he runs out of cash
while True:
p1.cards = p1.pick(2)
d1.cards = d1.pick(1)
dealer_won = False
print_board(p1.cards, d1.cards)
#Asks for the bet amount till the player enter a valid amount
while True:
try:
bet = int(input("Enter the amount of money you want to bet: "))
if bet > p1.money:
print("You dont have sufficient funds!")
print("Your account balance is: {}".format(p1.money))
raise Exception
break
except Exception as e:
print("Please enter a valid amount!")
p1.money -= bet
#Player turns continues till he passes or bursts
while True:
#Asks player choice for action till a valid choice is put
while True:
try:
choice = input("Do you want to hit or pass? [h/p]: ")
if choice.lower() not in ['h', 'p']:
raise Exception
break
except Exception as e:
print("Oops! Please enter a valid choice")
if choice.lower() == 'h':
p1.cards += p1.pick(1)
print_board(p1.cards, d1.cards)
else:
break
if find_value(p1.cards) > 21:
p1.burst = True
dealer_won = True
break
#Dealer only plays if the player is not bursted yet
if not dealer_won:
while True:
d1.cards += d1.pick(1)
if find_value(d1.cards) > 21:
d1.burst = True
break
if find_value(d1.cards) > find_value(p1.cards):
dealer_won = True
break
print("\n" *50)
print_board(p1.cards, d1.cards)
#Winner determination and result printing
if dealer_won:
print("_"*50)
print("Sorry you lost the game and the money.")
if p1.burst:
print("Your cards value exceeded 21. Be careful next time!")
print("_"*50)
else:
print("Dealer got very lucky! Better luck next time! :)")
print("_"*50)
else:
p1.money += 3*bet
print("_"*67)
print("Bingo! You won the game! Twice the bet is credited to your account.")
if d1.burst:
print("Dealer's total card value exceeded 21. You got lucky, well played!")
print("_"*67)
print("Your account balance is: {}".format(p1.money))
#Asks if the player wants to play again
while True:
try:
play_again = input("Do you want to play again? [y/n]: ")
if play_again.lower() not in ['y', 'n']:
raise Exception
break
except Exception as e:
print("Oops! Please enter a valid choice")
if play_again == 'n':
break
elif p1.money == 0:
print("You did not have sufficient to continue playing!")
break