0

In my code below I run a blackjack game and I want to total any hand (user or dealer's) with a function. When I run the code no errors appear, however when I call the function, the total hand value is not printed. It simply states "This provides you with a total of:" and the number is blank. See code below:

user_name = input("Please enter your name:")

print ("Welcome to the table {}. Let's deal!".format(user_name))

import random

suits = ["Heart", "Diamond", "Spade", "Club"]

ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

deck = [(suit, rank) for rank in ranks for suit in suits]

random.shuffle(deck,random.random)

user_hand = []

dealer_hand = []

user_hand.append(deck.pop())

dealer_hand.append(deck.pop())

user_hand.append(deck.pop())

dealer_hand.append(deck.pop())

def handtotal (hand):

    total = 0

    for rank in hand:

        if rank == "J" or "Q" or "K":

            total += 10

        elif rank == 'A' and total < 11:

            total += 11

        elif rank == 'A' and total >= 11:

            total += 1

        elif rank == '2':

            total += 2

        elif rank == '3':

            total += 3

        elif rank == '4':

            total += 4

        elif rank == '5':

            total += 5

        elif rank == '6':

            total += 6

        elif rank == '7':

            total += 7

        elif rank == '8':

            total += 8

        elif rank == '9':

            total += 9

    return total

    print (total)

print ("Your current hand is {}".format(user_hand))

print ("This provides you with a total of:")

handtotal(user_hand)
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
mtomney
  • 1
  • 2
  • 1
    Note that `if rank == "J" or "Q" or "K":` doesn't do what you think, see [this question](http://stackoverflow.com/questions/15112125/how-do-i-test-one-variable-against-multiple-values). – Daniel Roseman Aug 19 '15 at 12:06

2 Answers2

2

There's not much point in putting print(total) after return total, because return causes a function to terminate immediately and not evaluate any lines following the return statement*. Instead, try putting a print outside of the function definition:

print ("This provides you with a total of:")

print(handtotal(user_hand))

*(there are some corner cases with try-except-finally blocks, but this is true the majority of the time.)

Kevin
  • 74,910
  • 12
  • 133
  • 166
0

First answering your question:

The reason nothing is printing is because you are returning the value of the hand before you print it, thus never getting to your print statement.

return total #Stops the function

print (total) #Never gets reached

Why does this happen?

A Simple way to think about it is once you 'return' a value, you have essentially told python
"This is the answer, no need to do anything else, you have what you want"
Anything you put directly after a return statement will ever run.

There are multiple ways to solve this:
A) You move the print statement above the return:

print (total)

return (total)

B) You simply get rid of the print statement and reference the value of the function (which is the total because that is what is returned)

    return total

print ("Your current hand is {}".format(user_hand))

print ("This provides you with a total of:" + str(handtotal(user_hand)))

You could just str() the return statement, but I assume you want to be able to compare that value to the dealer's at some point.

But now to the three current biggest problems in your code:

1st. You are using input for a name.
-This is very bad practice because the user would have to know they were supposed to put quotations around their answer to signify it is a string.

Please enter your name:russell
Traceback (most recent call last):
  File "/test.py", line 1, in <module>
    user_name = input("Please enter your name:")
  File "<string>", line 1, in <module>
NameError: name 'russell' is not defined

Solution: Use raw_input() instead.
- This will convert the answer to a string for you.

2nd. The line:

if rank == "J" or "Q" or "K":

Does not check the value of rank against "J", "Q", and "K"

This actually means is: does rank == "J" OR is "Q" truthy OR is "K" truthy

Because "Q" and "K" are non empty strings, Python regards them as True, meaning that right now your value will always come out to 20 because the first if statement will Always be true no matter what.

What you actually want is:

if rank in {"J","Q","K"}

But This Also Won't Work Because:

3rd. just saying:

for rank in hand:

Won't make it look at the actual Value of the rank. It will still look at the whole tuple.
Ex.
rank = ('Diamond', '7')
rank != '7'

Solution: You actually want to reverse all of your if statements and use 'in':

    if "J" in rank or "Q" in rank or "K" in rank:

        total += 10

    elif 'A' in rank and total < 11:

        total += 11

    elif 'A' in rank and total >= 11:

        total += 1

    ...


P.S. This also only works because there is not a capital A, K, Q, or J in the words Spade, Diamond, Club, or Heart otherwise that suit would always get the value for the card rgardless of the actuall value. But that isn't a problem in this case.

ThatGuyRussell
  • 1,361
  • 9
  • 18