-2

Python 3.7

Trying to make a number guessing game. Here is my code:

#This is the guess the number game!
import random
secretNumber = random.randint(0,20)

print('I am thinking of a secret number between 0 and 20, can you guess what it is in six tries or less?')

for guessTimes in range(1,7):
    try:
        guessNumber = int(input())
        print(type(guessNumber))
        print('Guess Number: ' +str(guessNumber))
    except ValueError:
        guessNumber = None
        print('Secret Number: ' +str(secretNumber))
        print('You have to give me a valid integer for your guess.', end = ' ')
    if guessNumber and guessNumber < secretNumber:
        print('You have guessed a number that is too low...')
    elif guessNumber and guessNumber > secretNumber:
        print('You have guessed a number that is too high...')
    elif guessNumber and guessNumber == secretNumber:
        print('Great job, you guessed the secret number in only ' +str(guessTimes)+ ' tries!')
        print('You should go PRO!')
        break
    if guessTimes > 6:
        print('Sorry, that was six tries and lots of fail, better luck next time!')
    elif guessTimes == 1:
        print('That is ' +str(guessTimes)+ ' failed attempt thus far, you have ' +str(6-guessTimes)+ ' chances remaining. Please try again.')
    elif guessTimes > 1:
        print('That is ' +str(guessTimes)+ ' failed attempts thus far, you have ' +str(6-guessTimes)+ ' chances remaining. Please try again.')
    guessTimes += 1
    continue

This all appears to work just fine for all values of guessNumber that are between 1 and 123,412,351. But for some reason, whenever I input 0 as a guessNumber, the code skips the line:

if guessNumber and guessNumber < secretNumber:
        print('You have guessed a number that is too low...')

I'm sorry this isn't a super-relevant question, but I've been banging my head against this for a while now and can't figure out why that line doesn't evaluate to True when guessNumber == 0.

T_J
  • 27
  • 5
  • 1
    Is there any reason for writing you evaluation like : if guessNumber and guessNumber < secretNumber: rather writing if guessNumber < secretNumber: – H_J Feb 22 '19 at 04:30
  • 1
    `if guessNumber` will evaluate as False for `guessNumber==0` – Sociopath Feb 22 '19 at 04:33
  • You might want to use a [debugger](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) for that or look at [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Feb 22 '19 at 04:42
  • When the someone inputs a string that can't be converted to int (eg. 'asdfasdf') for their guess and the exception is raised, if I don't set the guessNumber = None, then: {if guessNumber < secretNumber:} {NameError: name 'guessNumber' is not defined} so I'm using {if guessNumber and guessNumber < secretNumber} to get a False boolean and skip the clause. Otherwise, if I simply use {if guessNumber < secretNumber:} {TypeError: '<' not supported between instances of 'NoneType' and 'int'} – T_J Feb 22 '19 at 04:51

2 Answers2

2

Both None and 0 are "falsy" in Python, so if guessNumber and guessNumber < secretNumber: shortcircuits when testing guessNumber, since it's 0 and 0 is falsy.

You'll need to narrow your check to only catch None, changing tests of the form if guessNumber and ...: to if guessNumber is not None and ...:.

An alternative solution is to avoid checking the guess entirely when they gave an invalid value. You can do this fairly easily by expanding from try/except to try/except/else:

for guessTimes in range(1,7):
    try:
        guessNumber = int(input())
        print(type(guessNumber))
        print('Guess Number: ' +str(guessNumber))
    except ValueError:
        print('Secret Number: ' +str(secretNumber))
        print('You have to give me a valid integer for your guess.', end = ' ')
    else:
        # Only run when no ValueError occurs
        if guessNumber < secretNumber:
            print('You have guessed a number that is too low...')
        elif guessNumber > secretNumber:
            print('You have guessed a number that is too high...')
        elif guessNumber == secretNumber:
            print('Great job, you guessed the secret number in only ' +str(guessTimes)+ ' tries!')
            print('You should go PRO!')
            break

    if guessTimes == 1:
        print('That is ' +str(guessTimes)+ ' failed attempt thus far, you have ' +str(6-guessTimes)+ ' chances remaining. Please try again.')
    else:
        print('That is ' +str(guessTimes)+ ' failed attempts thus far, you have ' +str(6-guessTimes)+ ' chances remaining. Please try again.')
else:
    # Run when loop exits without break
    print('Sorry, that was six tries and lots of fail, better luck next time!')

The advantage here is that you don't bother setting or testing guessNumber at all when it's garbage (no using None as a flag value or the like), so when it's not garbage, you don't need to check for the flag of None at all.

Side-note: In the new code, I removed the guessTimes += 1 and continue, since the for i in range(1, 7): already did the increment for you, and a continue as the last statement in a loop is nonsensical. I also moved the "too many guesses" output to an else on the for loop; you'd never have hit that code as written (since the loop ends with guessTimes as 6, guessTimes > 6 is always false), and it saves checks to just have it happen automatically if the loop ends without a break.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • That's elegant. I feel like a caveman stacking rocks next to the Taj Mahal. I will do my best to learn this well and implement these solutions in my future code. Thank you very much, ShadowRanger. – T_J Feb 22 '19 at 05:14
1

A number if used in conditional statement like if is treated as boolean (false if 0, true otherwise)

if guessNumber and guessNumber < secretNumber:
     print('You have guessed a number that is too low...')

There are two conditions here in the if statement and the first one goes false since guessNumber for input 0 is false and thus the line gets skipped.

Remove the guessNumber from the condition and you are good

if guessNumber < secretNumber:
     print('You have guessed a number that is too low...')
Ubercool
  • 1,029
  • 2
  • 14
  • 29
  • Thank you for taking the time to reply with a correct answer, Ubercool. I chose the one from ShadowRanger because it pointed out a variety of flaws in the code that I hadn't even noticed. Upvoted for sure. – T_J Feb 22 '19 at 05:16