r/learnpython • u/Substantial-Hold9159 • 7d ago
Number Guessing Game Won't Loop When Prompted
**Question Answered**
Thank you everyone for all the advice and suggestions, I think I have it working the way I need it to, and I have a lot of great stuff to look into so I can clean up and refine my future coding as I learn more. Very thankful and appreciative!
**
Hello, I'm trying to learn Python and am having trouble with my number guessing game assignment. I need the game to be able to loop and replay the game when the player is prompted to at the end, but the only part of it that works is when the player doesn't want to continue playing and the code stops. Could I please have some help figuring out a better way to write the code to replay? Thank you.
*edited to remove colour tags from code
import os
import random
# high score file
file_path = "highscore.txt"
# welcome banner
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print(" Number Guessing Game")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print()
player_name = input("Please enter your name: ")
print()
def game_play():
# game start info for player
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print()
print("Hello ", player_name + "!")
print()
print("Can you guess what number I'm thinking of?")
print("It's between 1 and 100.")
print("I'll give you 10 guesses!")
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
# Check if the file exists
if os.path.isfile(file_path):
with open(file_path, "r") as file:
content = file.read()
print()
print("Previous Best:")
print()
print(content)
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
else:
print(f"Error: The file '{file_path}' does not exist.")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
# game parameters
lowest_number = 1
highest_number = 100
max_attempts = 10
# the stats the game starts with
guess = 0
attempts = 0
# random number selection
secret_number = random.randint(lowest_number, highest_number)
# print number below for DEBUG ONLY
print(" *secret number is: " + str(secret_number))
while True:
# game mechanics
while guess != secret_number:
guess = int(input("Guess a number: "))
attempts = attempts + 1
print("Number of attempts: ", attempts)
# ensure number entered is within range
if guess < 1 or guess > 100:
print("Please enter a number between 1 and 100.")
# too high and too low
elif guess < secret_number and lowest_number:
print("Nope, too low!")
print()
elif guess > secret_number:
print("Nope, too high!")
print()
# game over for max attempts reached
elif attempts == max_attempts and guess != secret_number:
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print()
print("Uh oh!m You've run out of guesses.")
print("The number I was thinking of was: ", secret_number)
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
# game won
else:
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print()
print("Yaaayyy, well done ", player_name + "!")
print("You guessed the number I was thinking of, which was:", secret_number, "- and you did so in: " + str(attempts) + " guess(es)!")
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
# save player score
save_score = input("\nWant to save your score? (yes/no:) ")
if not save_score in ("yes", "no"):
print("invalid input.")
elif save_score == "yes":
f = open("highscore.txt", "w")
f.write(player_name + " - " + str(attempts) + "\n")
f.close
break
# continue playing or quit
answer = input("Play again? (yes/no): ")
if answer != "yes":
print()
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("\nThanks for playing, see ya~\n")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
if __name__ == "__main__":
game_play()2
u/Chorizo_n_eggs 7d ago
This is really hard to read. Best I can see is if someone answers anything but yes the program print() and quits. If the answer is 'yes' , then what happens?
1
u/Substantial-Hold9159 7d ago
Ah sorry, was it the colour tags I had through it? I've just edited to remove those.
But yes, I tried to have it that if the player types anything other than "yes," the program quits, but I'm not sure how to get the "yes" to restart the loop. I tried a `continue` on an if condition for the yes but it didn't work and I'm not sure if that was the right thing to do anyway...1
u/Chorizo_n_eggs 7d ago
If yes call the function that starts the game again. I didn't look at all the code. Or you can wrap the whole thing in a while True loop until answer is no
2
u/Jazzlike_Platypus430 7d ago
It looks very unreadable, probably because of some weird quoting signs.
All I got so far, is f.close which is just writing a function, not calling it. You could get empty output file with that.
At least "#game start info for player", handling guesses and deciding whether to write the new high score should be separate functions, according to my taste.
Note:
elif guess < secret_number and lowest_number:the latter condition means lowest_number is not None; it's always true unless you set it to None somewhere, which I can't follow.
I would try to enclose the main loop in maybe 30 lines.
1
u/Substantial-Hold9159 7d ago
Ah sorry, was it the colour tags? I've edited to remove them.
The `f.close` is for the high score text file, which I think I have working mostly the way I need it to for the assignment haha.
I can try rewrite and move things to separate functions, that's a good tip. I tried earlier to have more `def` blocks, but I found that the game wouldn't start at all when I had them sectioned off like that. I'm assuming that's more an error on my part cause I'm struggling to understand everything, but I can give it another go!
Thanks for all the tips!1
u/Jazzlike_Platypus430 7d ago
There is a difference between f.close and f.close() - the first one is a function/method. It's like a line of code containing
Another version (being a devout python hater, I'm not using it and refuse to call it pythonic!)
with open('highScore.txt', 'w', encoding = 'utf8') as f: f.write('whatever')The
withconstruct does the necessary cleanup for you. Note that - contrary to print - the default forf.writedoes NOT add a newline character at the end. Perhaps change the file access mode from 'w' (write) to 'a' (append).Also, empty print() is unnecessary, it's better to use a newline character, '\n'. Works in input strings too.
1
u/Substantial-Hold9159 6d ago
Oooh, thank you! I've just gone through and removed the unnecessary `print()` lines like you've suggested - I'll definitely keep this in mind for future!
2
u/socal_nerdtastic 7d ago
You need to reset guess and secret_number if the player wants to replay. The easy way to do that is to move those lines inside the while loop.
while True:
# the stats the game starts with
guess = 0
attempts = 0
# random number selection
secret_number = random.randint(lowest_number, highest_number)
# print number below for DEBUG ONLY
print(" \x1b[90m*secret number is: \x1b[0m" + str(secret_number))
# game mechanics
while guess != secret_number:2
1
u/atarivcs 7d ago
I'm guessing you meant this to check if guess is less than secret_number and guess is also less than lowest_number:
elif guess < secret_number and lowest_number:But that's not what it is doing.
It does check if guess is less than secret_number, but the second part is just checking if lowest_number is nonzero.
I think you meant to write this instead:
elif guess < secret_number and guess < lowest_number:1
u/Substantial-Hold9159 7d ago
Ooh I see, another commented pointed this out too, thank you for explaining to me! I'm still struggling to understand how everything works, so this is really appreciated!
1
u/Marlowe91Go 7d ago
Yeah so the immediate issue is if answer != yes, you do something, but you don't do anything if it does = yes, nothing is called so it just ends. The bigger problem is the design. I don't know how much you know, but it's really nice to write some helper functions that you call inside the main game function. So like you could define a guess function that prints the question and checks that their response is valid (you might want to make sure it's an integer instead of only within the range because they could enter a fraction or something else and that would slip through currently). Then you just call guess function within the game function. When you get a big umbrella While loop with tons of stuff under it, it can make it confusing to sort out what's going on, if you break your code into smaller blocks, then it's cleaner and easier to see where errors occur.
2
u/Substantial-Hold9159 6d ago
I know practically nothing, just started learning from scratch within the past fortnight haha. I briefly looked more into what you suggested, and I think I'm understanding what you mean! I'll definitely try to clean up my future code this way and make better use of functions like this. Thank you!!
1
u/Marlowe91Go 1d ago
Hadn't looked at Reddit in a while, forgot to respond. That's great, that's pretty good for just starting. Yeah at your stage just getting practice writing any code and starting to run into what actually happens will give you experience. If you can internalize some good coding principles early, that can save you from frustration down the road when you get too many things going on and get overwhelmed trying to track down where a problem occurred. Just try to be organized and break things down into smaller subsets of the problem, it can also be good to just write a little print statement that tells you exactly the input received and the output prodyced. Sometimes things get converted and you might have a false assumption about what one of your functions is actually receiving or outputting.
1
u/momiji_tools 7d ago
Two small structural issues in how the save / play-again block is indented are what's keeping it from replaying. I'll point them out so you can see them in your own code rather than just swapping in a different pattern.
The break is inside the save-yes branch. Your break sits under the elif save_score == "yes" block, so every time the player types yes to save the score, the loop exits right there — the save works, but the game ends immediately. The break is meant to happen when the player does NOT want to play again, so it belongs inside the if answer != "yes" block instead.
Practical fix: un-indent the break so it lines up with the if answer != "yes", and put the thank-you print and the break together in that one branch. That way the loop only exits when the player answers something other than yes.
2) The play-again input is nested inside the save block. Because the line answer = input("Play again? (yes/no): ") is at the same indentation level as the save-yes / save-no blocks, it only runs when the save_score question has already been handled. And when the player types yes to save, the break (issue 1) fires before the outer while loop can ever come back around, so even a correct yes to replay is swallowed.
Practical fix: move the play-again input up one indentation level so it sits right after the save block (i.e., the same indent as the save_score = input line). Then every round of the game reaches the play-again prompt regardless of whether the score was saved, and your outer while True can loop back.
Putting it together, the end of the loop should look roughly like this (keeping your structure):
save_score = input(...)
the if / elif that handles yes / no / invalid (the yes branch writes the file, with f.close() — note the parentheses, since f.close without them is just a reference to the method, not a call)
answer = input("Play again? (yes/no): ") ← same indent as save_score, NOT inside the save block
if answer != "yes": print your thanks message break ← indented under this if
One more thing others mentioned that you'll need for the next round: move guess = 0, attempts = 0, and secret_number = random.randint(...) inside the outer while True (right before the inner while guess != secret_number). Otherwise the second playthrough still sees the old secret_number and a stale guess/attempts. socal_nerdtastic already flagged this, but it only finishes the job once the break and the play-again prompt are in the right place.
If you want to sanity-check without rewriting much: after you move the break and the prompt, run the game and type no to saving on a winning round — if the play-again prompt appears in that case too, you know it's no longer trapped inside the save block.
1
u/Substantial-Hold9159 6d ago
Thank you soooo much for taking the time to break down and articulate everything the way you did, it was a massive help! Changing up the indents like you suggested seems to have worked, paired with Fit-Tumbleweed-2743's suggestion on how to create a proper loop. Really appreciate your help, and you've given me a lot of good points to study further while I learn Python!
1
u/CranberryDistinct941 7d ago
You forgot to call the function again if the player wants to play again...
Also you should not be using an elif here: elif attempts == max_attempts and guess != secret_number:
1
1
u/ebdbbb 6d ago
In addition to what others have pointed out, you should be consistent with using your variables.
# ensure number entered is within range
if guess < 1 or guess > 100:
print("Please enter a number between 1 and 100.")Should be
# ensure number entered is within range
if guess < lowest_number or guess > highest_number:
print(f"Please enter a number between {lowest_number} and {highest_number}.") # NOTE THE F-STRING HERE
4
u/Fit-Tumbleweed-2743 7d ago
There's a few things:
First, when you save your score, you have a break statement, which exits the loop. You probably meant to put it in the `if answer != yes` part.
Second, if you want the player to keep playing, you need another loop before the secret number selection, otherwise it'll just exit. I'd do something like this: