Infinite While Loop while making a simple logic game "Bagels" - python

I am using The Big Book of Small Python projects to increase my skills in python, and on the very first project, which is making a simple logic game, On the first try, the code goes all the way however if you get it wrong you it won't run properly.
Here is the code and a description of the game, the while loop with chances is supposed to run for the whole game, until you run out of chances, the second while loop is supposed to run in case user enters below or more than length three for the number
import re
import random
#In Bagels, a deductive logic game, you
#must guess a secret three-digit number
#based on clues. The game offers one of
#the following hints in response to your guess:
#“Pico” when your guess has a correct digit in the
#wrong place, “Fermi” when your guess has a correct
#digit in the correct place, and “Bagels” if your guess
#has no correct digits. You have 10 tries to guess the
#secret number.
choice_of_nums=['123','345','674','887','356','487','916']
random_three_num=random.choices(choice_of_nums)
count_bagel=0
count_fermi=0
Chances=10
while Chances!=0:
guess = input(f'Guess the three digit number! You have {Chances} to guess! ')
while len(guess)!=3:
guess=input('You must choose a three digit number! Try again! ')
for i in range(0,len(random_three_num)):
if guess==random_three_num:
print('YOU WIN! Well done')
break
elif guess[i] not in random_three_num:
count_bagel+=1
if count_bagel==len(random_three_num):
print('Bagels')
Chances=Chances-1
elif guess[i]==random_three_num[i]:
count_fermi+=1
Chances=Chances-1
print('Fermi')
elif guess in random_three_num:
print('Pico')

import random
choice_of_nums = ['123', '345', '674', '887', '356', '487', '916']
random_three_num = random.choice(choice_of_nums)
count_bagel = 0
count_fermi = 0
chances = 10
while chances > 0:
guess = input(f'Guess the three digit number! You have {chances} to guess! ')
while len(guess) != 3:
guess = input('You must choose a three digit number! Try again! ')
while not guess.isdigit():
guess = input('You must choose integer values! ')
number_is_present = any(number in guess for number in random_three_num)
if guess == random_three_num:
print('YOU WIN! Well done')
chances = 1 # combined w/ the last line, chances will become = 0
elif not number_is_present:
print('Bagel')
else:
index_is_right = False
for i in range(len(guess)):
if guess[i] == random_three_num[i]:
index_is_right = True
if index_is_right:
print('Fermi')
else:
print('Pico')
chances -= 1
(06/28/22) added chances = 1 if the guess is right, so to exit the while loop
random.choices returns a list
you don't need the re module
use snake case as suggested in PEP8

The break after print('YOU WIN! Well done') exits the for loop not the while loop. Put Chances = 0 before the break:
if guess==random_three_num:
print('YOU WIN! Well done')
Chances = 0
break

You should never check a while loop with a condition like x != 0. Always use <= or >=. The reason being, that if somehow the number zero is skipped and you end up at -1 then the loop will still exit.
Couldn't your check if guess==random_three_num: be done before the for loop? Then the break statement would actually break the while loop. Now it's only breaking the for loop. This is one reason that could lead to a infinite loop.
Your second to last line elif guess in random_three_num: should probably be elif guess[1] in random_three_num:.
Chances=Chances-1 could probably be outside the for loop also, as the number of chances should decreasing only one per guess. Currently the number of chances decreases up to 3 times during the for loop (every time you hit 'Fermi'). This could lead to issue described in "1."

Related

While loop keeps printing constantly, doesn't allow for user input

I'm trying to complete this assignment asking user for a number and if it's not -1 then it should loop. if it's -1 then to calculate the average of the other numbers.
I'm getting stuck with the actual loop - it endlessly keeps printing the message to user to enter a different number - as in the picture - and doesn't give user a chance to enter a different number. Please help, I've been through so many videos and blogs and can't figure out what's actually wrong.
#creating a list for later calculations:
wrong = []
#asking for input:
input("Hi, We're gonna play a guessing game. When asked enter a number between -10 and 10.\nIf not correct you'll have to guess again ^-^")
num =int(input("number:"))
#looping
while num != -abs(1):
wrong.append(num)
print("Nope, guess again:")
if num == -abs(1):
break
av = sum(wrong) / len(wrong)
print ("You got it! The average of your wrong answers is: ")
print(av)
print("The End")
print("Nope, guess again:")
You need to include the input function in the loop if you want it to work. I corrected the rest of your code as well, you don't need the if condition. More generally you should avoid to use break, it often means you are doing something wrong with your loop condition. Here it is redondant and the code after break is never executed.
wrong = []
input("Hi, We're gonna play a guessing game. When asked enter a number between -10 and 10.\nIf not correct you'll have to guess again ^-^")
num = int(input("Number: "))
while num != -1 :
wrong.append(num)
num = int(input("Nope, guess again: "))
av = sum(wrong) / len(wrong)
print(f"You got it! The average of your wrong answers is: {av}\nThe End")
You are just breaking the loop before printing the results, first print the results, then break the loop.
And a while loop isn't necessary for your program, use if condition wrapped in a function instead:
#creating a list for later calculations:
wrong = []
#asking for input:
input("Hi, We're gonna play a guessing game. When asked enter a number between -10 and 10.\nIf not correct you'll have to guess again ^-^")
#looping
def go():
num =int(input("number:"))
if num != -abs(1):
wrong.append(num)
print("Nope, guess again:")
if num == -abs(1):
av = sum(wrong) / len(wrong)
print ("You got it! The average of your wrong answers is: ")
print(av)
print("The End")
break
print("Nope, guess again:")
go()
There are lots of issues in the code.
If you want to get inputs in while looping, you should include getting input code inside the while loop like below,
while num != -1:
......
num =int(input("number:"))
......
Also you don't have to include 'break' inside the while loop because, when num != 1, the loop will stop.
You should ask for input inside your loop, but you just print "Nope, guess again:".
wrong = []
print("Hi, We're gonna play a guessing game. When asked enter a number between -10 and 10.\n"
"If not correct you'll have to guess again ^-^")
num = int(input("number: "))
# looping
while num != -1:
wrong.append(num)
num = int(input("Nope, guess again: "))
av = sum(wrong) / len(wrong)
print(f"You got it! The average of your wrong answers is: {av}\nThe End")

How do I stop a while loop if something happens inside a function that should stop the itterations?

Hello fellow programmers! I am a beginner to python and a couple months ago, I decided to start my own little project to help my understanding of the whole development process in Python. I briefly know all the basic syntax but I was wondering how I could make something inside a function call the end of the while loop.
I am creating a simple terminal number guessing game, and it works by the player having several tries of guessing a number between 1 and 10 (I currently made it to be just 1 to test some things in the code).
If a player gets the number correct, the level should end and the player will then progress to the next level of the game. I tried to make a variable and make a true false statement but I can't manipulate variables in function inside of a while loop.
I am wondering how I can make it so that the game just ends when the player gets the correct number, I will include my code down here so you guys will have more context:
import random
import numpy
import time
def get_name(time):
name = input("Before we start, what is your name? ")
time.sleep(2)
print("You said your name was: " + name)
# The Variable 'tries' is the indication of how many tries you have left
tries = 1
while tries < 6:
def try_again(get_number, random, time):
# This is to ask the player to try again
answer = (input(" Do you want to try again?"))
time.sleep(2)
if answer == "yes":
print("Alright!, well I am going to guess that you want to play again")
time.sleep(1)
print("You have used up: " + str(tries) + " Of your tries. Remember, when you use 5 tries without getting the correct number, the game ends")
else:
print("Thank you for playing the game, I hope you have better luck next time")
def find_rand_num(get_number, random, time):
num_list = [1,1]
number = random.choice(num_list)
# Asks the player for the number
ques = (input("guess your number, since this is the first level you need to choose a number between 1 and 10 "))
print(ques)
if ques == str(number):
time.sleep(2)
print("Congratulations! You got the number correct!")
try_again(get_number, random, time)
elif input != number:
time.sleep(2)
print("Oops, you got the number wrong")
try_again(get_number, random, time)
def get_number(random, try_again, find_rand_num, time):
# This chooses the number that the player will have to guess
time.sleep(3)
print("The computer is choosing a random number between 1 and 10... beep beep boop")
time.sleep(2)
find_rand_num(get_number, random, time)
if tries < 2:
get_name(time)
tries += 1
get_number(random, try_again, find_rand_num, time)
else:
tries += 1
get_number(random, try_again, find_rand_num, time)
if tries > 5:
break
I apologize for some of the formatting in the code, I tried my best to look as accurate as it is in my IDE. My dad would usually help me with those types of questions but it appears I know more python than my dad at this point since he works with front end web development. So, back to my original question, how do I make so that if this statement:
if ques == str(number):
time.sleep(2)
print("Congratulations! You got the number correct!")
try_again(get_number, random, time)
is true, the while loop ends? Also, how does my code look? I put some time into making it look neat and I am interested from an expert's point of view. I once read that in programming, less is more, so I am trying to accomplish more with less with my code.
Thank you for taking the time to read this, and I would be very grateful if some of you have any solutions to my problem. Have a great day!
There were too many bugs in your code. First of all, you never used the parameters you passed in your functions, so I don't see a reason for them to stay there. Then you need to return something out of your functions to use them for breaking conditions (for example True/False). Lastly, I guess calling functions separately is much more convenient in your case since you need to do some checking before proceeding (Not inside each other). So, this is the code I ended up with:
import random
import time
def get_name():
name = input("Before we start, what is your name? ")
time.sleep(2)
print("You said your name was: " + name)
def try_again():
answer = (input("Do you want to try again? "))
time.sleep(2)
# Added return True/False to check whether user wants to play again or not
if answer == "yes":
print("Alright!, well I am going to guess that you want to play again")
time.sleep(1)
print("You have used up: " + str(tries) + " Of your tries. Remember, when you use 5 tries without getting the correct number, the game ends")
return True
else:
print("Thank you for playing the game, I hope you have better luck next time")
return False
# Joined get_number and find_random_number since get_number was doing nothing than calling find_rand_num
def find_rand_num():
time.sleep(3)
print("The computer is choosing a random number between 1 and 10... beep beep boop")
time.sleep(2)
num_list = [1,1]
number = random.choice(num_list)
ques = (input("guess your number, since this is the first level you need to choose a number between 1 and 10 "))
print(ques)
if ques == str(number):
time.sleep(2)
print("Congratulations! You got the number correct!")
# Added return to check if correct answer is found or not
return "Found"
elif input != number:
time.sleep(2)
print("Oops, you got the number wrong")
tries = 1
while tries < 6:
if tries < 2:
get_name()
res = find_rand_num()
if res == "Found":
break
checker = try_again()
if checker is False:
break
# Removed redundant if/break since while will do it itself
tries += 1

How can I make this code less verbose?

I am making a simple 'guess a number between one and ten' game. I have used some basic error handling and am printing the number generated by the random module for testing purposes.
However I would like to know if there is a less verbose way to write this.
This is the code:
import random
while True:
"""Variable declaration"""
number_of_attempts = 1
number = random.randrange (1,11)
print (number)
print("Time to play a guessing game! Muhahaha...")
"""Error handling and main game code/while loop"""
while True:
try:
guess = int(input("Guess a number between one and ten."))
except ValueError:
print("Input a whole number between one and ten silly!")
continue
if guess >= 1 and guess <= 10:
pass
else:
print("Input a number between one and ten silly!")
continue
if guess == number:
print("You were successful and it took you", number_of_attempts, "attempts!!!")
break
else:
print("Try again!")
number_of_attempts = number_of_attempts +1
"""Game Exit/Restart"""
play_again = input("Would you like to play again, y/n?")
if "y" in play_again or "yes" in play_again:
continue
else:
break
Thanks,
Ben
if guess >= 1 and guess <= 10:
Can be written as:
if 1 <= guess <= 10:
Also, your first conditional can simply be written as:
if not 1 <= guess <= 10:
print("Input a number between one and ten silly!")
continue
But this can also be put inside the try bit, saving you from writing continue twice:
try:
guess = int(input("Guess a number between one and ten."))
if not 1 <= guess <= 10:
print("Input a number between one and ten silly!")
continue
except ValueError:
print("Input a whole number between one and ten silly!")
continue
Finally your last conditional can simply be:
if play_again not in ('y', 'yes'):
break
The continue isn't needed.
You may also want to wrap this all up into a function as well, to get rid of those infinite while loops and to prevent you from using continue and break so much.
Why not put the actual conditions on the while loops so you don't have to hunt for breaks to understand the loops? It would make your code clearer and smaller.
if guess == number:
print("You were successful and it took you", number_of_attempts, "attempts!!!")
break
For instance if you put guess == number as the while loop conditional then the print would be the first thing after the loop. Initialize guess to -1 so it always works the first time. The play again if statement could also disappear into the loop conditional as well.

Am I allowing 3 guesses or 2?

I am learning Python on Codecademy, and I am supposed to give the user 3 guesses before showing "you lose". I think my code allows 3 entries, but the website shows "Oops, try again! Did you allow the user 3 guesses, or did you incorrectly detect a correct guess?" unless the user guesses correctly within 3 trials. Can someone tell me what's wrong?
from random import randrange
random_number = randrange(1, 10)
count = 0
# Start your game!
guess= int(raw_input("Please type your number here:"))
while count < 2:
if guess==random_number:
print "You win!"
break
else:
guess=int(raw_input("Please guess again:"))
count+=1
else:
print "You lose!"
print random_number
Your loop will indeed ask the user for three guesses. (As can be trivially seen by running the code—ignore those other answers telling you to change the loop condition, that's the wrong solution.)
The problem with your loop is a more subtle one: because of the way it's structured, the third guess is never tested! You can see this by setting random_number to a constant and guessing wrong twice, then right on the last try; you still lose.
Your best bet is to use a more straightforward loop structure, where the asking and the checking happens in the same iteration of the loop.
for attempt in xrange(3):
guess = int(raw_input("Please enter a number: "))
if guess == random_number:
print "You win!"
break
print "Wrong! Try again."
else:
print "You lose! The number was", random_number
If you want a different prompt on the second and subsequent guesses, try this:
prompt = "Please enter a number"
for attempt in xrange(3):
guess = int(raw_input(prompt + ": "))
if guess == random_number:
print "You win!"
break
prompt = "Wrong! Try again"
else:
print "You lose! The number was", random_number
You need while count <= 2. Your count starts at 0. Then it goes through the body of your loop once. Then it gets incremented to 1. Then it goes through your loop body another time. Finally, once it increments to 2, your while condition evaluates to false, and the loop body doesn't execute a third time.
Be careful with corner cases when you're setting up conditions. :)
The condition should be:
while count < 3:
To make it easier to understand, I suggest you start the counter in count = 1 and write the condition like this:
while count <= 3:
Now it's more clear that exactly 3 repetitions are allowed. But let's see why your code was wrong:
count starts at 0, and it's true that 0 < 2, so we enter the loop
At the first failed attempt, count gets incremented to 1, and it's true that 1 < 2 so we enter the loop once more
At the second failed attempt, count gets incremented to 2, and it's no longer true that 2 < 2 so we exit the loop
So you see, only two attempts were being considered.

Modfying current code

My next task is modifying current code. In a previous exercise, I've written a basic application that covers a numbers guessing game. The code is as follows: -
# Guess My Number
#
# The computer picks a random number between 1 and 100
# The player tries to guess it and the computer lets
# the player know if the guess is too high, too low
# or right on the money
import random
print("\tWelcome to 'Guess My Number'!")
print("\nI'm thinking of a number between 1 and 100.")
print("Try to guess it in as few attempts as possible.\n")
# set the initial values
the_number = random.randint(1, 100)
guess = int(input("Take a guess: "))
tries = 1
# guessing loop
while guess != the_number:
if guess > the_number:
print("Lower...")
else:
print("Higher...")
guess = int(input("Take a guess: "))
tries += 1
print("You guessed it! The number was", the_number)
print("And it only took you", tries, "tries!\n")
input("\n\nPress the enter key to exit.")
My task is to modify this so that there is a limited number of goes before a failure message is given to the user. Thus far, the chapter has covered "if, elif, else, for, loops, avoiding infinte loops." As such, I'd like to limit my response to these concepts only. For loops are covered next chapter.
What have I tried?
So far, I've tried amending the block in another while loop using 5 goes and the tries variable but it doesn't seem to work.
# guessing loop
while tries < 6:
guess = int(input("Take a guess: "))
if guess > the_number:
print("Lower...")
elif guess < the_number:
print("Higher...")
elif guess == the_number:
print("You guessed it! The number was", the_number)
print("And it only took you", tries, "tries!\n")
break
tries += 1
input("You didn't do it in time!")
input("\n\nPress the enter key to exit.")
Any pointers or highlighting what I've missed would be appreciated plus any explanation as to what I'd missed. Teaching myself to think programatically is aslo proving tricky.
What doesn't work
When I run it, the loop conditions't don't appear to work. My idle feedback is as follows.
This means my question can be summarised as
Where is my looping logic broken?
>>> ================================ RESTART ================================
>>>
Welcome to 'Guess My Number'!
I'm thinking of a number between 1 and 100.
Try to guess it in as few attempts as possible.
Take a guess: 2
Take a guess: 5
Higher...
You didn't do it in time!
Press the enter key to exit.
The problem is that your break statement is not indented to be included in your elif:
elif guess == the_number:
print("You guessed it! The number was", the_number)
print("And it only took you", tries, "tries!\n")
break
Thus, the loop always stops after the first iteration. Indent the break to be included within the elif and it should work.
The break is not in the conditional.
Add a tab before it.

Categories