I am working on a RPi blackjack project. Before I add the Pi into the mix, I want to get the Python code working by itself. The problem is mainly the Ace. I can't figure out a way to get it to switch to a "low ace" if, after hitting, the total goes over 21.
I believe that it might actually be switching, but when added up, the cards still go over. I think it has something to do with my overflow() function.
import random
alt = {"A(l)" : 1}
nums = {
"A" : 11,
"2" : 2,
"3" : 3,
"4" : 4,
"5" : 5,
"6" : 6,
"7" : 7,
"8" : 8,
"9" : 9,
"10": 10,
"J" : 10,
"Q" : 10,
"K" : 10
}
suits = ["D", "H", "S", "C"]
playerCards = []
dealerCards = []
def overflow(cards):
try:
ace = cards.index("A")
except:
ace = -1
if sum([nums[card] for card in cards]) > 21:
if ace != -1:
cards[ace] = "A(l)"
else:
return True
else:
return False
while True:
winner = "none"
playerCards.clear()
dealerCards.clear()
playerCards.append(random.choice(list(nums.keys())))
playerCards.append(random.choice(list(nums.keys())))
dealerCards.append(random.choice(list(nums.keys())))
print("Player:")
print(" ".join(playerCards), ":", sum([nums[card] for card in playerCards]))
print("Dealer:")
print(" ".join(dealerCards))
print()
while True:
if not overflow(playerCards):
hitStand = input("'hit' or 'stand'?: ")
if(hitStand == "hit"):
playerCards.append(random.choice(list(nums.keys())))
print(" ".join(playerCards), ":",
sum([nums[card] for card in playerCards]))
print()
else:
break
else:
winner = "dealer"
print()
print("Dealer wins")
print("-----------")
break
while sum([nums[card] for card in dealerCards]) < 17 and winner == "none":
print()
print("Dealer:")
if not overflow(dealerCards):
dealerCards.append(random.choice(list(nums.keys())))
print(" ".join(dealerCards), ":", sum([nums[card] for card in dealerCards]))
else:
winner = "player"
print()
print("Player wins")
print("-----------")
break
if winner == "none":
if(sum([nums[card] for card in playerCards]) ==
sum([nums[card] for card in dealerCards])):
print()
print("Tie")
print("-----------")
break
elif (sum([nums[card] for card in playerCards]) >
sum([nums[card] for card in dealerCards]) or overflow(dealerCards)):
winner = "player"
print()
print("Player wins")
print("-----------")
continue
else:
winner = "dealer"
print()
print("Dealer wins")
print("-----------")
continue
It doesn't have to be that complicated.
def overflow(cards):
val = sum([nums[card] for card in cards)
if val > 21 and 'A' in cards:
val -= 10
return val > 21
Notice that this condition is traditionally called "bust", not "overflow".
I would probably do two functions:
def score(cards):
val = sum([nums[card] for card in cards)
if val > 21 and 'A' in cards:
val -= 10
return val
def overflow(cards):
return score(cards) > 21
Related
I have to create a blackjack game in python in which the user inputs the number of decks that are being used and the amount of money the user wants to bet. The rules are: o The player places his bet (should be read from the keyboard).
o The dealer and player are dealt two cards (one card of the dealer should be hidden).
o If the player has 21 he wins his bet; else if the dealer has 21 then the dealer wins and the player loses his bet.
o The player can only select to draw a new card (hit) or pass. Repeat until the player passes or busts. If the player goes above 21 then he busts.
o Then the dealer draws cards (automatically) until he either busts or reaches 17 or higher.
o Values of cards: A= 1 or 11 (the highest that does not bust you) and J=Q=K=10
o Note: in blackjack there are more actions: insurance, double, split; those are not required to be implemented as they would make the code you have to produce much, much longer and harder
I will show you my code below when I tried to run it, it said that the name "total" is not defined on the function game, but earlier on I have already defined it. I don't know how can i fix it.
import random
N=int(input("Please enter number of decks of cards used: "))
deck= [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]*N
wins=0
losses=0
chip_pool = 100
bet = 1
def deal(deck):
hand = []
for i in range(2):
random.shuffle(deck)
card=deck.pop()
if card == 11:
card = "J"
if card == 12:
card = "Q"
if card == 13:
card = "K"
if card == 14:
card = "A"
hand.append(card)
return hand
def play_again():
again = input("Do you want to play again? (Y/N) : ").lower()
if again == "y":
dealer_hand = []
player_hand = []
deck = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]*N
game()
else:
print("Thank you for playing.")
exit()
def total_hand():
total = 0
for card in hand:
if card == "J" or card == "Q" or card == "K":
total = total + 10
elif card == "A":
if total >=11:
total = total + 1
else:
total = total + 11
else:
total = total + card
return total
def hit(hand):
card = deck.pop()
if card == 11:
card = "J"
if card == 12:
card = "Q"
if card == 13:
card = "K"
if card == 14:
card = "A"
hand.append(card)
return hand
def print_results(dealer_hand, player_hand):
clear()
print("\n WELCOME TO BLACKJACK!\n")
print("The dealer has a " + str(dealer_hand) + "for a total of" + str(total(dealer_hand)))
print("You have a" + str(player_hand) + "for a total of" + str(total(player_hand)))
def blackjack(dealer_hand, player_hand):
global wins
global losses
if total(player_hand) == 21:
print_results(player_hand,dealer_hand)
print("Congratulations! You got a blackjack.\n")
wins = wins + 1
play_again()
elif total(dealer_hand) == 21:
print_results(dealer_hand,player_hand)
print("Sorry you lose. The dealer got a blackjack.\n")
chip_pool -= bet
loses = loses + 1
play_again()
def score(dealer_hand,player_hand):
if total(player_hand) == 21:
print_results(dealer_hand, player_hand)
print("Congratulations! You got a blackjack1\n")
elif total(dealer_hand) == 21:
print_results(dealer_hand, player_hand)
print("Sorry you lose. The dealer go a blackjack\n")
elif total(player_hand) > 21:
print_results(dealer_hand, player_hand)
print("Sorry, you busted. You lose.\n")
elif total(dealer_hand) > 21:
print_results(dealer_hand, player_hand)
print("Dealer busts. You win!\n")
chip_pool += bet
elif total(player_hand) < total(dealer_hand):
print_results(dealer_hand, player_hand)
print("Sorry, the score is not higher than the dealer. You lose.\n")
chip_pool -= bet
elif total(player_hand) > total(dealer_hand):
print_results(dealer_hand, player_hand)
print("Congratulations. Your score is higher than the dealer. You win.\n")
chip_pool += bet
elif total(player_hand) == total(dealer_hand):
print_results(playe_hand, dealer_hand)
print("There is a tie. In a tie dealer always wins!\n")
chip_pool -= bet
def make_bet():
global bet
bet = 0
print("What amount of chips would you like to bet? ")
while bet == 0:
bet_comp = input()
bet_comp = int(bet_comp)
if bet_comp >= 1 and bet_comp <= chip_pool:
bet = bet_comp
else:
print("Invalid bet, you only have" + str(chip_pool) + "remaining")
def game():
choice = 0
print("Welcome to Blackjack!\n")
dealer_hand = deal(deck)
player_hand = deal(deck)
print("The dealer is showing a " +str(dealer_hand[0]))
make_bet()
print("You have a " + str(player_hand))
blackjack(dealer_hand, player_hand)
quit = False
while not quit:
choice = input("Do you want to [H]it, [S]tand, or [Q]uit: ").lower()
if choice == 'h':
hit(player_hand)
print(player_hand)
if total(player_hand) > 21:
print("You busted")
chip_pool -= bet
play_again()
elif choice == "s":
while total(dealer_hand) < 17:
hit(dealer_hand)
print(dealer_hand)
if total(dealer_hand) > 21:
print("Dealer busts. You win!")
chip_pool += bet
play_again()
score(dealer_hand, playe_hand)
play_again()
elif choice == "q" :
print("Thank you for playing. Hope you enjoyed!")
quit = True
exit()
if __name__ == "__main__":
game()
You have not defined the function total that you call. Try adding this to your code
def total(array):
total = 0
for card in array:
if card == "J" or card == "Q" or card == "K":
total = total + 10
elif card == "A":
if total >=11:
total = total + 1
else:
total = total + 11
else:
total = total + card
return total
However I see some more issues in your code that will need fixing later on! Stand or Quit do nothing currently, and on busting there is an exception thrown since chip_pool never had a value assigned to it
EDIT 1:
You defined a function
def total_hand():
total = 0
for card in hand:
if card == "J" or card == "Q" or card == "K":
total = total + 10
elif card == "A":
if total >=11:
total = total + 1
else:
total = total + 11
else:
total = total + card
return total
Similar to what I suggested. Maybe it was just a typo but you need to do the following
Rename the function from total_hand to total OR call total_hand
Change the definition from total_hand() to total_hand(hand)
I am totally new to programming. This is my second program so far. I have two challenges in this code.
For most of the initial runs this works fine in pycharm but after few runs this gives an error message like below. The bloc of code which is causing this error seems to be executing in the beginning and then its giving this error. Please someone help me with this.
Error message:
Traceback (most recent call last):
File "D:\Python\Practice\100 Days of coding\Day 11\Black Jack.py", line 81, in <module>
play_game()
File "D:\Python\Practice\100 Days of coding\Day 11\Black Jack.py", line 70, in play_game
while comp_score < 17:
TypeError: '<' not supported between instances of 'NoneType' and 'int'
Challenge 2: I have overserved that the cards stored for computer alter occasionally. I am unable to figure out why. Please help.
import random
def play_game():
def deal_card():
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
card = random.choice(cards)
return card
def calculate_score(card_list):
if sum(card_list) == 21:
if len(card_list) == 2:
return 0
else:
if 11 in card_list and sum(card_list) > 21:
card_list.remove(11)
card_list.append(1)
return sum(card_list)
def game_result():
print(f"Computer cards are {comp_cards} and computer score is {comp_score}.")
print(f"Your cards are {user_cards} and score is {user_score}.")
if comp_score == user_score:
print("Your scores are equal. Match Draw.")
elif user_score == 0:
print("Yay Black Jack! You win!")
elif comp_score == 0:
print("Computer has Black Jack. You loose.")
elif user_score > 21:
print("You went over 21. You loose.")
elif comp_score > 21:
print("Computer score went over 21. You win!")
elif user_score > comp_score:
print("You won!")
else:
print(f"Computer score {comp_score} is greater than your score {user_score}.\n You loose.")
print("Welcome to BlackJack!")
comp_cards = []
user_cards = []
for _ in range(2):
comp_cards.append(deal_card())
user_cards.append(deal_card())
user_score = calculate_score(user_cards)
print(f"Computer cards {comp_cards}")
print(f"Your cards are {user_cards} and your score is: {user_score}")
pass_ = False
while pass_ == False:
deal_a_new_card = input("Type 'y' to get another card and 'n' to pass. : ")
if deal_a_new_card == "y":
user_cards.append(deal_card())
user_score = calculate_score(user_cards)
else:
pass_ = True
if user_score > 21:
pass_ = True
print(f"Your cards are {user_cards} and your score is: {user_score}")
comp_score = calculate_score(comp_cards)
while comp_score < 17:
comp_cards.append(deal_card())
comp_score = calculate_score(comp_cards)
game_result()
play_again = 'y'
while play_again == "y":
play_game()
play_again = input("\nWould you like to play again? Enter 'y' to play. : ")
This occurs because there are some circunstances where calculate_score() is not returning any value.
You are only returning a value when 'the sum isn't 21' or 'when it's equal to 21 AND there are 2 cards'. But you should also return value if you got a sum of 21 in more than 2 cards.
So you need to include in line 13th of your code:
if sum(card_list) == 21:
if len(card_list) == 2:
return 0
#From here on:
else:
return another_value
I'm writing a casino-based game and I'm having some trouble with coding blackjack, I run into a problem where you only have the option to "hit" once, and I'm not sure how to make it loop. Once you've "hit" it just settles with your score as if it was final even tho you might still be far under 21. Every time I try to fix it some other part of the code just breaks.
(keep in mind this is not the full code but just the blackjack part)
import os
import random
deck = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]*4
bal = 100
balstr = str(bal) + "$"
def clear():
os.system('cls')
def deal(deck):
hand = []
for i in range(2):
random.shuffle(deck)
card = deck.pop()
if card == 11:card = "J"
if card == 12:card = "Q"
if card == 13:card = "K"
if card == 14:card = "A"
hand.append(card)
return hand
def newRound():
again = input("Do you want to play again? (Y/N): ").lower()
if again == "y":
blackjack()
else:
#takes you back to main menu in the full code, just ignore this
position()
def total(hand):
total = 0
for card in hand:
if card == "J" or card == "Q" or card == "K":
total+= 10
elif card == "A":
if total >= 11:
total+= 1
else: total+= 11
else:
total += card
return total
def hit(hand):
card = deck.pop()
if card == 11:
card = "J"
if card == 12:
card = "Q"
if card == 13:
card = "K"
if card == 14:
card = "A"
hand.append(card)
return hand
def currentHands(dealerHand, playerHand):
clear()
print(("The dealer has a ") + str(dealerHand) + " for a total of " + str(total(dealerHand)))
print(("You have a ") + str(playerHand) + " for a total of " + str(total(playerHand)))
def score(dealerHand, playerHand, usrbetint):
global bal
if total(playerHand) == 21 or total(dealerHand) > 21 or total(playerHand) > total(dealerHand) and total(playerHand) < 21:
currentHands(dealerHand, playerHand)
bal += usrbetint
print("Congratulations, you win!\n \nYour new balance is {}$".format(bal))
else :
currentHands(dealerHand, playerHand)
bal -= usrbetint
print("Sorry, you lose.\n \nYour new balance is {}$".format(bal))
def blackjack():
choice = 0
clear()
print("Let's play blackjack!\n")
userbet = input("(for help type help) How much money do you want to use: ").upper()
if userbet == "HELP" :
if userbet == "HELP" :
print("Instructions")
else :
print("Something went wrong")
pass
else :
usrbetint = int(userbet)
dealerHand = deal(deck)
dealerHandShow = [dealerHand[0]]
dealerHandShow = total(dealerHandShow)
playerHand = deal(deck)
print(("The dealer is showing a ") + str(dealerHand[0]) + " for a total of " + str(dealerHandShow))
print(("You have a ") + str(playerHand) + " for a total of " + str(total(playerHand)))
choice = input("Do you want to [H]it or [S]tand?: ").lower()
clear()
if choice == "h":
hit(playerHand)
while total(dealerHand) < 17:
hit(dealerHand)
score(dealerHand, playerHand, usrbetint)
newRound()
elif choice == "s":
while total(dealerHand) < 17:
hit(dealerHand)
score(dealerHand, playerHand, usrbetint)
newRound()
blackjack()
i assume the fix would be somewhere around the last 20 lines of the "blackjack" function but didnt know how to explain everything without sending the clump of code.
If someone please could give me tips on where to change stuff i'd really appreciate that and ignore the "global bal" part, it was the only way i knew to add a truly global variable.
Since you don't know how many times you'll be looping (it is based on user input), you probably want a while loop. Your current code mixes the dealer behavior into the player handling, you you'll need to separate that out, since we don't want to loop it.
print("You have a " + str(playerHand) + " for a total of " + str(total(playerHand)))
choice = input("Do you want to [H]it or [S]tand?: ").lower()
while choice == "h":
clear()
hit(playerHand)
print("You have a " + str(playerHand) + " for a total of " + str(total(playerHand)))
choice = input("Do you want to [H]it or [S]tand?: ").lower()
while total(dealerHand) < 17:
hit(dealerHand)
score(dealerHand, playerHand, usrbetint)
You might want to add an additional condition to stop asking the player if they want to hit when they've already busted.
I am currently trying to program a mathematical card trick, which asks the user what pile their random card is in. However, the second time it runs (the 'trick phase' has to occur 3 times for the trick to work) the list index becomes out of range. I am unsure where exactly the problem lies and will attach the current version so you can try to run it to see clearer. Thanks!
import random
def makedeck():
listy = []
cardsindeck = 0
while cardsindeck != 21:
suit = random.randint(1,4)
if suit == 1:
suit = "D"
elif suit == 2:
suit = "H"
elif suit == 3:
suit = "S"
else:
suit = "C"
cardtype = random.randint(1,13)
if cardtype == 1:
card = "A"
elif cardtype == 2:
card = "2"
elif cardtype == 3:
card = "3"
elif cardtype == 4:
card = "4"
elif cardtype == 5:
card = "5"
elif cardtype == 6:
card = "6"
elif cardtype == 7:
card = "7"
elif cardtype == 8:
card = "8"
elif cardtype == 9:
card = "9"
elif cardtype == 10:
card = "10"
elif cardtype == 11:
card = "J"
elif cardtype == 12:
card = "Q"
else:
card = "K"
cardandsuit = (card + suit)
if cardandsuit not in listy:
listy.append(cardandsuit)
cardsindeck = cardsindeck + 1
return listy
def dealdeck(listy):
list1 = []
list2 = []
list3 = []
for i in range(len(listy)):
if i % 3 == 0:
list1.append(listy[i])
elif i % 3 == 1:
list2.append(listy[i])
else:
list3.append(listy[i])
return[list1, list2, list3]
def makepiles(pile1,pile2,pile3):
print("Pile 1\t\tPile 2\t\t Pile 3\t\t")
for i in range(7):
print(pile1[i],"\t\t",pile2[i],"\t\t",pile3[i],"\t\t")
def usercardpile():
userinput = input("What pile is your card in?")
if userinput == "1" or userinput.title() == "One":
return 1
elif userinput == "2" or userinput.title() == "Two":
return 2
elif userinput == "3" or userinput.title() == "Three":
return 3
else:
print("Please only write 1, 2 or 3")
return usercardpile()
listy = makedeck()
pile1, pile2, pile3 = dealdeck(listy)
for i in range(1,4):
newlisty = makepiles(pile1,pile2,pile3)
userspile = usercardpile()
if userspile == 1:
newlisty = (pile2,pile1,pile3)
elif userspile == 2:
newlisty = (pile1,pile2,pile3)
else:
newlisty = (pile1,pile3,pile2)
pile1, pile2, pile3 = dealdeck(newlisty)
print("Your card is",newlisty[10])
One issue is with this line of code:
newlisty = makepiles(pile1, pile2, pile3)
You're expecting makepiles to return 3 lists, whereas it returns None (no explicit item returned).
I imagine if you were to return the piles from that function, it'd work.
The other thing is, You are doing this:
newlisty = (pileX, pileY, pileZ)
This will create a tuple of lists, and you will iterate over the entire lists rather than the individual cards. I believe you want
newlisty = pile1 + pile3 + pile2`
This'll create a composite list of 21 elements by linearly combining the smaller piles.
Other comments:
Consider storing your decktype and card type in dicts. That way, you can quickly lookup and generate your piles without having to write a long set of if statements. Example:
You can reduce
cardtype = random.randint(1,13)
if cardtype == 1:
card = "A"
elif cardtype == 2:
card = "2"
elif cardtype == 3:
card = "3"
elif cardtype == 4:
card = "4"
elif cardtype == 5:
card = "5"
elif cardtype == 6:
card = "6"
elif cardtype == 7:
card = "7"
elif cardtype == 8:
card = "8"
elif cardtype == 9:
card = "9"
elif cardtype == 10:
card = "10"
elif cardtype == 11:
card = "J"
elif cardtype == 12:
card = "Q"
else:
card = "K"
To...
cardtype_lookup = { 1 : 'A', 2 : '2', 3 : '3', .... 12 : 'K' }
card = cardtype_lookup[random.randint(1, 13)]
...And so on.
I think you are hitting a few issues with your code beyond just the final iterations. Below are some suggestions along with comments that I believe accomplishes your purpose.
from random import shuffle
# Function for generating 21 random cards
def makedeck():
# Create 52 cards by suit and cardtype
listy = [card + suit for card in ['A','2','3','4','5','6','7','8','9','10','J','Q','K'] for suit in ['D','H','S','C']]
# Shuffle the list
shuffle(listy)
# Choose only the first 21 items of that list
listy = listy[:21]
return listy
# Function for dividing 21-card deck into 3 equally-sized piles
def dealdeck(listy):
# Iterate over listy, stepping by 3, starting with the first, second, and third item
list1 = listy[::3]
list2 = listy[1::3]
list3 = listy[2::3]
# Return the three lists as three items to correspond to the three piles of the call
return list1, list2, list3
# This works
def makepiles(pile1,pile2,pile3):
print("Pile 1\t\tPile 2\t\t Pile 3\t\t")
for i in range(7):
print(pile1[i],"\t\t",pile2[i],"\t\t",pile3[i],"\t\t")
# This works
def usercardpile():
userinput = input("What pile is your card in?")
if userinput == "1" or userinput.title() == "One":
return 1
elif userinput == "2" or userinput.title() == "Two":
return 2
elif userinput == "3" or userinput.title() == "Three":
return 3
else:
print("Please only write 1, 2 or 3")
return usercardpile()
listy = makedeck()
pile1, pile2, pile3 = dealdeck(listy)
for i in range(1,4):
# Because this function does not return anything, it should be run on its own, and not assigned to a variable
makepiles(pile1,pile2,pile3)
userspile = usercardpile()
# Now you want to re-order the piles based on user input. Because these are lists, you can simply add them together in a new order to create a newly arranged list
if userspile == 1:
newlisty = pile2 + pile1 + pile3
elif userspile == 2:
newlisty = pile1 + pile2 + pile3
else:
newlisty = pile1 + pile3 + pile2
# Now you create new piles based on the re-sorted list and re-iterate
pile1, pile2, pile3 = dealdeck(newlisty)
# Uses .format method instead
print("Your card is {}".format(newlisty[10]))
I want this game to start each hand with the cards left over from the previous hand. Instead, it begins with a complete, newly-shuffled deck. How can I fix it to just continue?
I updated the code based in your advice but it doesnt display my show card thanks a lot
import random, sys
suits = ('Clubs', 'Spades', 'Hearts', 'Diamonds')
pip = ('Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King')
pipValues = {'Ace':11, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10, 'Jack':10, 'Queen':10, 'King':10}
class Card:
def __init__(self, suit, pip):
self.suit = suit
self.pip = pip
self.value = pipValues.get(pip)
def __str__(self):
thisCard = ""
thisCard += str(self.pip)
thisCard += str(self.suit)
return (thisCard)
def __repr__(self):
thisCard = ""
thisCard += str(self.pip)
thisCard += str(self.suit)
return (thisCard)
class Player:
def __init__(self):
self.hand = []
self.handTotal = 0
def __str__(self):
printHand = ""
for i in self.hand:
printHand += str(i) + " "
return (printHand)
def __repr__(self):
printHand = ""
for i in self.hand:
printHand += str(i) + " "
return (printHand)
class Deck:
def __init__(self):
self.cardList = []
#for each suit take every card
for i in range(len(suits)):
for j in range(len(pip)):
self.cardList.append(Card(suits[i], pip[j]))
def shuffle(self):
random. shuffle (self.cardList)
def dealOne(self, player):
(player.hand).append(self.cardList[0])
player.handTotal += self.cardList[0].value
del self.cardList[0]
print self.cardList
return self.cardList
def __str__(self):
printString = ""
for i in range(len(self.cardList)):
if i % 13 == 0:
printString += "\n \t"
printString += str(self.cardList[i]) + " "
else:
printString += str(self.cardList[i]) + " "
printString += "\n"
return printString
def showHands(player, opponent):
print ('Dealer shows ' + str(opponent.hand[0]) + ' faceup')
print ('You show ' + str(player.hand[0]) +str(player.hand[0] ))
def playerTurn(deck, player, other):
#First, check scores to see if either player has a blackjack:
if player.handTotal == 21 or other.handTotal == 21:
if other.handTotal == 21:
print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("Dealer has " + str(other) + "for a total of 21")
print ("Dealer has a Blackjack! Dealer wins!")
print ("Thanks for playing. Come back again soon! ")
message()
else:
print ("You hold " + str(player) + "for a total of 21")
print ("You have a Blackjack! You win!")
print ("Thanks for playing. Come back again soon! ")
message()
hitOrStand = 0
aces = False
#IF TWO ACES
if player.hand[0].pip == "A" and player.hand[1].pip == "A":
player.hand[0].pipValue = 1
if player.handTotal == 21:
print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("Blackjack! You win!")
print ("Thanks for playing. Come back soon!")
print()
message()
while hitOrStand != 2:
#check for aces
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
print()
hitOrStand = input('Do you hit or stand? Enter "1" for hit and "2" for stand: ')
while hitOrStand != 1 and hitOrStand != 2:
try:
hitOrStand = int(hitOrStand)
break
except ValueError:
print ("Enter a valid integer \n")
hitOrStand = input('Do you hit hit or stand? Enter "1" for hit and "2" for stand: ')
print()
if hitOrStand == 1:
print('Card dealt: ' + str(deck.cardList[0]))
print()
deck.dealOne(player)
#check if an ace was drawn
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
if player.handTotal == 21:
print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("Blackjack!! You Win!")
print()
print ("Thanks for playing. Come back soon!")
message()
if player.handTotal > 21:
#check for aces
if aces:
print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("Over 21. Value of ace changed to 1")
#chanlge value of ace and hand
player.handTotal = player.handTotal - 10
for i in player.hand:
if i.pip == "A" and i.value == 11:
i.value = 1
#check for other standard aces
aces = False
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
else:
print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("You Bust! Dealer Wins!")
#exit, since you're a loser
print ("Thanks for Playing! Come Back Soon!")
print()
raise SystemExit
if hitOrStand == 2:
print ('You stand at: ' + str(player.handTotal))
print()
print ("Now Dealer's Turn")
print ()
def message():
again = raw_input("Do you want to play again? (Y/N) : ")
if(again == "Y" or again == "y"):
main()
else:
print "\n\n-------Thank you for playing!--------\n\n"
exit()
def opponentTurn(deck, player, other):
if other.handTotal == 21:
raise SystemExit
aces = False
hitOrStand = 0
#IF TWO ACES
if player.hand[0].pip == "A" and player.hand[1].pip == "A":
player.hand[0].pipValue = 1
while hitOrStand != 2:
#check for aces
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
print()
#if blackjack
if player.handTotal == 21:
print ("Dealer has a BlackJack! Dealer Wins!")
break
if player.handTotal <21 and other.handTotal == 21:
print ("Dealer's hand is " + str(player.handTotal) + ". You have a Blackjack! Congratulations! You win! ")
break
if player.handTotal < other.handTotal:
hitOrStand = 1
if player.handTotal >= other.handTotal:
hitOrStand = 2
if hitOrStand == 1:
print("Dealer hits. " + 'Card dealt: ' + str(deck.cardList[0]))
deck.dealOne(player)
#check if an ace was drawn
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
if player.handTotal > 21:
#check for aces
if aces:
print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("Over 21. Value of ace changed to 1")
#chanlge value of ace and hand
player.handTotal = player.handTotal - 10
for i in player.hand:
if i.pip == "A" and i.value == 11:
i.value = 1
#check for other standard aces
aces = False
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
else:
print ('Dealer holds ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("Dealer Busts! You Win!")
message()
if hitOrStand == 2:
print ("Dealer stands at " + str(player.handTotal))
print ("Your score is " + str(other.handTotal))
print ("Dealer Wins!")
message()
#who won
def main():
cardDeck = Deck()
print ('Initial Deck: ')
print(cardDeck)
cardDeck.shuffle()
print ('Shuffled Deck: ')
print(cardDeck)
keep_playing = True
while keep_playing:
player = Player()
opponent = Player()
#give each player 2 cards, alternating
cardDeck.dealOne(player)
cardDeck.dealOne(opponent)
cardDeck.dealOne(player)
cardDeck.dealOne(opponent)
print ('Deck after giving 2 cards each')
print (cardDeck)
#show 1 faceup card for each player
showHands(player,opponent)
#start playing
playerTurn(cardDeck,player, opponent)
opponentTurn(cardDeck, opponent, player)
again = raw_input("Do you want to play again? (Y/N) : ")
keep_playing = again in "Yy"
# Reach here after dropping out of the while loop
print "\n\n-------Thank you for playing!--------\n\n"
main()
Yes, you can have one game continue from where the previous one left off. The current problem is that you call main recursively. This starts over from the beginning, shuffling a full deck, etc.
Instead, you would want a main program something like this:
def main():
cardDeck = Deck()
print ('Initial Deck: ')
print(cardDeck)
cardDeck.shuffle()
print ('Shuffled Deck: ')
print(cardDeck)
keep_playing = True
while keep_playing:
player = Player()
opponent = Player()
#give each player 2 cards, alternating
cardDeck.dealOne(player)
cardDeck.dealOne(opponent)
cardDeck.dealOne(player)
cardDeck.dealOne(opponent)
print ('Deck after giving 2 cards each')
print (cardDeck)
#show 1 faceup card for each player
showHands(player,opponent)
#start playing
playerTurn(cardDeck,player, opponent)
opponentTurn(cardDeck, opponent, player)
again = raw_input("Do you want to play again? (Y/N) : ")
keep_playing = again in "Yy"
# Reach here after dropping out of the while loop
print "\n\n-------Thank you for playing!--------\n\n"
This gets rid of your message function and the recursive call to main.
See the repl.it for a complete solution:
There are a lot of issues, here are a few of overarching themes:
If you're having to repeat yourself, you're doing it wrong:
aces = False
#IF TWO ACES
if player.hand[0].pip == "A" and player.hand[1].pip == "A":
player.hand[0].pipValue = 1
#check for aces
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
#check if an ace was drawn
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
#check for aces
if aces:
print ('You hold ' + str(player) + 'for a total of ' + str(player.handTotal))
print ("Over 21. Value of ace changed to 1")
#chanlge value of ace and hand
player.handTotal = player.handTotal - 10
for i in player.hand:
if i.pip == "A" and i.value == 11:
i.value = 1
#check for other standard aces
aces = False
for i in player.hand:
if i.pip == "A" and i.value == 11:
aces = True
Each of those is used twice... I replaced it by letting my players hand decide it's own value:
#property
def handTotal(self):
while sum(card.value for card in self.hand) > 21 and \
any(card.pip == 'Ace' and card.value == 11 for card in self.hand):
for card in self.hand:
if card.pip == 'Ace' and card.value == 11:
card.value = 1
break
return sum(card.value for card in self.hand)
The #property decorator forces it to recalculate every time someone asks for the handTotal.
Telling main you want to keep playing
You need to return a value all the way back to main, in some way. Because you already have some global state variables, I added playing = True, then:
def message():
global playing
again = input("Do you want to play again? (Y/N) : ")
if again.lower() == "n":
print("\n\n-------Thank you for playing!--------\n\n")
playing = False
return True # Tells `turn()` the game is over