Is this decent coding? (Expanding on 8. Your own while / else)


#1

https://www.codecademy.com/courses/python-beginner-en-cxMGf/0/8?curriculum_id=4f89dab3d788890003000096#

The course requires you to build a rather simple word guesser so I wanted to expand on it a little bit.
Is this any good? Are there better way to do the things below?
Is using this many else and ifs inside a while a smart thing to do or should it be avoided generally?

Bonus question: How would you check if raw_input is actually a number? In case the user entered something else.

from random import randint

# Generates a number from 1 through 10 inclusive
random_number = randint(1, 10)

guesses_left = 4
# Start your game!
print "Welcome to number guesser!"
print "Pick a number from 1 to 10."
print "You get 4 tries, choose wisely."
print

while guesses_left != 0:
    guess = int(raw_input("Enter your guess: "))
    if guess > 10 or guess == 0:
        print
        print "Can't read the instructions, huh?"
        print
    elif guess == random_number:
        print
        print "Congratulations, you win!"
        break  
    else:
        guesses_left -= 1
        if guesses_left == 0:
            print "Ha! You lose, sorry."
        else:
            if guesses_left == 1:
                print
                print "Wrong, guess again."
                print "This is your final guess, pick carefully."
                print
            else: 
                print
                print "Wrong, guess again."
                print "Guesses left: %s" % guesses_left
                print

#2

Inspect the string or convert and see what happens. It's not though, that's a function. Its result on the other hand, you could look at.
https://docs.python.org/2/library/stdtypes.html#str.isdigit
or exception handling

Your code runs off to the right, it doesn't need to. Your last line could be deindented twice with very little editing


#3

Thanks, I'll have a look at that link.

And which part do you mean exactly? I'm not sure I get what you mean


#4

Not sure what you're referring to.


#5

Your last line could be deindented twice with very little editing

You don't literally mean "last line" because that's nothing more than an empty print, right?


#6

It's indented really far to the right. It should be less so. Obviously other parts of the code would have to be adjusted for that to make sense. Point is, you're nesting stuff a lot. Flatten it.


#7

Think of it like this:
Those groups of prints, they all happen in situations that are exclusive to each other. ONE of them happen. So they're in some sense all the same thing and should therefore be indented to the same level. The third one starts running off to the right, the fourth and fifth go even further to the right.


#8

Isn't that necessary though, to keep it all in the while loop?
Right now I'm not seeing how to easily flatten it, but that'll probably come when I learn more about python.


#9

This doesn't run off more than one level. Does your code not fit into this pattern?

if condition:
    statements
elif condition:
    statements
elif condition:
    statements
elif condition:
    statements

#10

Ah yes, now I see what you mean. thanks
I'll have a go at rewriting it like that.


#11

Hmm yeah, I'm not really succeeding though
Doesn't it need to be 2 separate groups inside the while because I need the guesses_left -= 1 only to happen in the last part
If i'd make it all elif there's no place to put guesses_left -= 1
Or am I missing something obvious?

edit: I changed to last part to, which gets rid of 1 unnecessary indentation

    else:
        guesses_left -= 1
        if guesses_left == 0:
            print "Ha! You lose, sorry."
        elif guesses_left == 1:
            print
            print "Wrong, guess again."
            print "This is your final guess"
            print
        else: 
            print
            print "Wrong, guess again."
            print "Guesses left: %s" % guesses_left
            print

#12

Is there a reason why you won't remove the else at the top?
And for that matter, is there a reason why the -1 has to happen between conditions?

You've got to be able to defend why something is required. If you can't, then it should be removed.


#13

In case of winning or checking the input there shouldn't be subtracted from guesses_left.
When the guess is wrong it should subtract and notify the user of his/her amount left. (and warn about final guess in a separate one)

Not sure about the else, i'm trying to find out if i can do it different but i'm not seeing it.


#14

loop:
    get input
    if bad input, start loop over
    if game ended, stop loop
    if wrong/last guess, then do that stuff

#15

Wait, i think I got it.

elif guess != random_number: 
...
...

#16

If you were to control the game manually, you wouldn't even be able to keep track of all that nesting without considerable effort. So considering how you would do it manually is another reference to use.


#18

Finally fixed it. Had to add another elif to get it to stop printing after the guesses were up.
Couldn't manage to figure out another way

thanks for your help.
Imagining code like doing it manually really helps, great tip.

from random import randint

# Generates a number from 1 through 10 inclusive
random_number = randint(1, 10)

guesses_left = 4
# Start your game!
print "Welcome to number guesser!"
print "Pick a number from 1 to 10."
print "You get 4 tries, choose wisely."
print

while guesses_left != 0:
    guess = int(raw_input("Enter your guess: "))
    if guess > 10 or guess == 0: #check input
        print
        print "Can't read the instructions, huh?"
        print
    elif guess == random_number: #win
        print
        print "Congratulations, you win!"
        break   
    elif guess != random_number and \
    guesses_left == 1:
        guesses_left -= 1   
    elif guess != random_number and \
    guesses_left == 2: #wrong and final guess
        guesses_left -= 1           
        print 
        print "Wrong, guess again."
        print "This is your final guess."
        print 
    elif guess != random_number: #wrong guess
        guesses_left -= 1   
        print
        print "Wrong, guess again."
        print "Guesses left: %s" % guesses_left
        print        
else:
    print
    print "Ha! You lose, sorry."

#19

You can decrement the number of remaining guesses immediately after accepting the guess.

That's when the user consumes their guess anyway, so that's when it needs to be updated. (look at how you check for 1 guesses left to see if game is over, would make more sense to check for 0 left)


#20

Yeah, it felt a little weird checking if the game was over with 1 guesses left, same with checking for 2 left to print the final guess.

So you mean after raw_input?
Then the #check input subtracts from guesses_left too, which it shouldn't.

Doing it like this works though, and looks a bit better than my previous attempt

while guesses_left != 0:
    guess = int(raw_input("Enter your guess: "))
    guesses_left -= 1   
    if guess > 10 or guess == 0: #check input
        guesses_left += 1   
        print
        print "Can't read the instructions, huh?"
        print
    elif guess == random_number: #win
        print
        print "Congratulations, you win!"
        break    
    elif guess != random_number and \
    guesses_left > 1: #wrong guess
        print
        print "Wrong, guess again."
        print "Guesses left: %s" % guesses_left
        print        
    elif guess != random_number and \
    guesses_left == 1: #wrong and final guess          
        print 
        print "Wrong, guess again."
        print "This is your final guess."
        print     
else:
    print
    print "Ha! You lose, sorry."
    print

#21

Also figured out how to work in the .isdigit()
probably not the most efficient way, but it works reliably

while guesses_left != 0:
    guess = raw_input("Enter your guess: ")
    if not guess.isdigit():
        print
        print "Error! Invalid input."
        print "--------------------------" 
    else:
        guess = int(guess)
        guesses_left -= 1   
        if guess > 10 or guess == 0: #check input
            guesses_left += 1   
            print
            print "Can't read the instructions, huh?"
            print "--------------------------" 
        elif guess == random_number: #win
            print
            print "Congratulations, you win!"
            break    
        elif guess != random_number and \
        guesses_left > 1: #wrong guess
            print
            print "Wrong, guess again."
            print "Guesses left: %s" % guesses_left
            print "--------------------------"        
        elif guess != random_number and \
        guesses_left == 1: #wrong and final guess          
            print 
            print "Wrong again, be careful."
            print "This is your final guess."
            print "--------------------------"    
else:
    print
    print "Ha! You lose, sorry."
    print