How to apply nested while loops in python function - python

I am learning python and trying to build a number guessing game.
The game will randomly generate integer between 1 to 250 (both inclusive) for user to guess. When user input is out of the range, it will prompt user that it is our of range and request another input. Likewise, it will prompt user if it is too high or too low until correct number is guessed. At any point in time if user input 'stop', it will end the game.
As part of the assignment requirement, i need to code 2 new functions on top of those already provided and incorporate it in the final run of the game.
I am trying to convert the while loops below to a function with not much progress. It either end with positional argument error or endless loop.
the_number = random.randint(1,250)
# capture initial user input
user_input = get_user_input()
# repeat code below as long as the user has not guessed the right number
while user_input != the_number:
# repeat code below as long as user has not entered STOP
while user_input != 'STOP':
# verify user input is within range
check_range(user_input)
if user_input < the_number:
slow_print("{} is too low". format(user_input))
print('\n')
user_input = get_user_input()
elif user_input > the_number:
slow_print("{} is too high". format(user_input))
print('\n')
user_input = get_user_input()
else:
slow_print("Congratulations you have guessed the correct number")
break
else:
slow_print('\nGame stopped by user. Thank you for playing')
break
Please can anyone suggest how I can convert the while loops into a function that works.

I'm not certain what you are trying to achieve, but if all you need to do is add a further 2 functions then perhaps this is what you're looking for;
the_number = random.randint(1,250)
# capture initial user input
user_input = get_user_input()
# repeat code below as long as the user has not guessed the right number
while user_input != the_number:
# repeat code below as long as user has not entered STOP
while user_input != 'STOP':
# verify user input is within range
check_range(user_input)
if user_input < the_number:
tooLow(user_input)
user_input = get_user_input()
elif user_input > the_number:
tooHigh(user_input)
user_input = get_user_input()
else:
slow_print("Congratulations you have guessed the correct number")
break
else:
slow_print('\nGame stopped by user. Thank you for playing')
break
def tooLow(number):
slow_print("{} is too low". format(number))
print('\n')
def tooHigh(number):
slow_print("{} is too high". format(number))
print('\n')

Related

How do I compare the input value from one function, to the return value of another function?

I have a class project, where I am making a number guessing game. I have the following requirements:
#1. A main() function that holds the primary algorithm, but itself only passes information among other functions. main() must have the caller for random_int()
#2. A function called in main() (not nested in main()!) that compares the user's guess to the number from random_int() and lets the user know if it was too high or too low.
#3. A function called in main() that asks the user for a new guess.
#4. A function that prints out a string letting the user know that they won.
#5. Tell the user how many guesses it took them to get the correct answer.
I am currently having an issue trying to take the user inputted value "guess" and compare it with the value of a randomly generated integer "random_int" in a while loop in the function def high_low():
def random_int(size): #Generates a random integer from given parameters (size)
return randrange(1, size+1)
def new_guess(): #Prompts the user to enter an integer as their guess
guess = (input("Enter your guess (between 1 - 1000): "))
return guess
def high_low(random_int, new_guess): #Lets the user know if the number they guessed is too high or too low
while guess != random_int: #While loop to continue until user guesses correct number
if guess > random_int:
print("The number you guessed is too high, guess again.")
elif guess < random_int:
print("The number you guessed is too low, guess again.")
attempts+=1
I either get the error "guess not defined" or '>' not supported between instances of 'function' and 'function'
Here is all of the code for context, note though that most of it below what I have posted above is pseudocode for the purposes of figuring out the logic of the game's function, and I have not yet gone through with debugging.
#Python number guessing game
#Import randrange module
from random import randrange
#Initialize variables
attempts = 0
def random_int(size): #Generates a random integer from given parameters (size)
return randrange(1, size+1)
def new_guess(): #Prompts the user to enter an integer as their guess
guess = (input("Enter your guess (between 1 - 1000): "))
return guess
def high_low(random_int, new_guess): #Lets the user know if the number they guessed is too high or too low
while guess != random_int: #While loop to continue until user guesses correct number
if guess > random_int:
print("The number you guessed is too high, guess again.")
elif guess < random_int:
print("The number you guessed is too low, guess again.")
attempts+=1
new_guess()
def win(random_int, new_guess): #Prints that the answer is correct, along with the number of guesses it took
while guess == random_int:
if attempts >= 2: #If it took the user more than 1 attempt, uses "guesses" for proper grammar
print("You guessed the correct number, you win! It took you ", str(attempts()), " guesses.")
input("Would you like to play again? (Y/N): ")
if input == Y: #If user inputs "Y", runs the program again
main()
elif input == N: #If user inputs "N", terminates the program
break
elif attempts < 2: #If it took the user only 1 attempt, uses "guess" for proper grammar
print("You guessed the correct number, you win! It took you ", str(attempts()), " guess.")
input("Would you like to play again? (Y/N): ")
if input == Y: #If user inputs "Y", runs the program again
main()
elif input == N: #If user inputs "N", terminates the program
break
def main(): #Function to call all functions in the program
random_int(1000)
new_guess()
high_low(random, new_guess)
win()
main() #Calls the "main" function, runs the program
The code has a couple of issues I'll walk through all of them with an explanation so that we understand the reason why they happen at all. First we'll address all errors one by one.
Error-1
The first error on executing the code is '>' not supported between instances of 'function' and 'function'.
To understand that, notice the difference between Call-1 and Call-2 in below example code:
def f1():
return 1
def f2():
return 2
def less_than(n1, n2):
return n1 < n2
less_than(f1, f2) # Call-1: this will not work and give you error similar to what you get
less_than(f1(), f2()) # Call-2: this works
Call-1 passes the function itself, whereas Call-2 passes result of f1() and f2(), which are integers and can be compared by <.
In the code the main() needs to be rewritten like this:
def main(): #Function to call all functions in the program
r = random_int(1000)
n = new_guess()
high_low(r, n)
win()
Error-2
After above fix, executing will give another error:
NameError: name 'guess' is not defined
It means guess has not been defined. That's fixed by re-writing high_low() again like this. Notice the name new_guess replaced with guess. One is the function and other is the variable.
def high_low(random_int, guess): #Lets the user know if the number they guessed is too high or too low
while guess != random_int: #While loop to continue until user guesses correct number
if guess > random_int:
print("The number you guessed is too high, guess again.")
elif guess < random_int:
print("The number you guessed is too low, guess again.")
attempts+=1
guess = new_guess()
Error-3
Again running would give this error:
TypeError: '>' not supported between instances of 'str' and 'int'
Fix is simple, the new_guess() function needs to convert input to int as calling input returns everything as string.
def new_guess(): #Prompts the user to enter an integer as their guess
guess = int(input("Enter your guess (between 1 - 1000): "))
return guess
Error-4
Last error would be:
UnboundLocalError: local variable 'attempts' referenced before assignment
This simply means no value has been set to attempts before using it in attempts += 1
This gets fixed again by updating high_low and adding attempts = 0:
def high_low(random_int, guess): #Lets the user know if the number they guessed is too high or too low
attempts = 0
while guess != random_int: #While loop to continue until user guesses correct number
if guess > random_int:
print("The number you guessed is too high, guess again.")
elif guess < random_int:
print("The number you guessed is too low, guess again.")
attempts+=1
guess = new_guess()
Final code looks like this:
from random import randrange
#Initialize variables
attempts = 0
def random_int(size): #Generates a random integer from given parameters (size)
return randrange(1, size+1)
def new_guess(): #Prompts the user to enter an integer as their guess
guess = int(input("Enter your guess (between 1 - 1000): "))
return guess
def high_low(random_int, guess): #Lets the user know if the number they guessed is too high or too low
attempts = 0
while guess != random_int: #While loop to continue until user guesses correct number
if guess > random_int:
print("The number you guessed is too high, guess again.")
elif guess < random_int:
print("The number you guessed is too low, guess again.")
attempts+=1
guess = new_guess()
def win(random_int, new_guess): #Prints that the answer is correct, along with the number of guesses it took
while guess == random_int:
if attempts >= 2: #If it took the user more than 1 attempt, uses "guesses" for proper grammar
print("You guessed the correct number, you win! It took you ", str(attempts()), " guesses.")
input("Would you like to play again? (Y/N): ")
if input == Y: #If user inputs "Y", runs the program again
main()
elif input == N: #If user inputs "N", terminates the program
break
elif attempts < 2: #If it took the user only 1 attempt, uses "guess" for proper grammar
print("You guessed the correct number, you win! It took you ", str(attempts()), " guess.")
input("Would you like to play again? (Y/N): ")
if input == Y: #If user inputs "Y", runs the program again
main()
elif input == N: #If user inputs "N", terminates the program
break
def main(): #Function to call all functions in the program
r = random_int(1000)
n = new_guess()
high_low(r, n)
win()
main() #Calls the "main" function, runs the program
your high_low function has no reference to a variable named guess. I think the solution is to just add the line guess = new_guess() right before the while loop.

I need help fixing my first program's bugs

I'm trying to write my first program that just gets an input from the user, selects a random number from 1 - 10, and checks to see if the user's number and computer's number matched.
Here's the code I tried:
def Num_Guess():
print("Hello! Welcome to the \"Guessing Game!\"")
import time
time.sleep(2)
print("Input a number from 1-10 and see if the computer has the same number!")
time.sleep(2)
User_Guess = input("Pick a number between 1 and 10: ")
def int_check(User_Guess):
if User_Guess.isnumeric() == True:
User_Guess = int(User_Guess)
def range_check(User_Guess):
if User_Guess == range(1,10):
print("Great! Your guess was", User_Guess, end='')
print("!")
return User_Guess
else:
print("Sorry, please pick a number between 1 and 10.")
time.sleep(2)
#Deletes the variable so that the global version does not override the local one.
del User_Guess
User_Guess = input("Pick a number between 1 and 10: ")
int_check(User_Guess)
range_check(User_Guess)
else:
print("Sorry, please pick a NUMBER between 1 and 10.")
time.sleep(2)
del User_Guess
User_Guess = input("Pick a number between 1 and 10: ")
int_check(User_Guess)
int_check(User_Guess)
time.sleep(2)
#Picks a random number between 1 and 10.
import random
n = random.randint(1, 10)
print("The computer picked" , n , end='')
print("!")
time.sleep(2)
if User_Guess == n:
print("The numbers match! You and the computer both picked" , User_Guess, end='')
print("!")
elif not User_Guess == n:
print("The numbers did not match. You picked" , User_Guess , "and the computer picked" , n , end='')
print(".")
time.sleep(2)
def Reset_Quit():
rq = input("Restart or quit? (r/q): ")
if rq == "r":
print("\n")
Num_Guess()
if rq == "q":
print("Quiting...")
time.sleep(2)
quit()
else:
print("Sorry, please say either \"r\" or \"q\".")
time.sleep(2)
Reset_Quit()
Reset_Quit()
Num_Guess()
What I'm trying to accomplish is:
Checking if the user's input is numeric or not. If yes, it will move on to the next step which is converting the string to an integer. If it is not, then it will simply make the user re-enter their input.
The next step will be checking if the input is within the range of 1 - 10. If it is, it will move on to comparing the user's input and the computer's to see if they match. If it is not, it will make the user redo their input and have it go through the numeral checking process again.
The final step is making the reset/quit promptly to not allow numbers or any other character that could cause the program to crash other than "r"/"R" or "q"/"Q".
I understood what the problem is.
In your range_check function, you are trying to match the user input with a range (which is a generator object) using ==. So instead use in keyword -
def range_check(User_Guess):
if User_Guess in range(1,11): # Here was the error
print("Great! Your guess was", User_Guess, end='')
...
Edit:
The program asks user to enter a number from 1-10, but program logic only accepts numbers 1-9. Rest of your code also uses the logic for including numbers 1-9 only. So correct the user input prompt to "number between 0-10" or "number from 1-9".
If you want to include 10 also:
use range(1, 11) and randint(1, 11)

How to stop for loop from iterating when condition is successfully met?

So, I'm working on Hand Cricket script & i want to stop "for" loop from iterating when a user's choice of number & CPU's choice of number are equal & if it's unequal it should keep iterating until it doesnt reach the final range's value
for i in range(1,7):
print("Ball %d"%i)
user_choice =int(input("Enter a number between 1 to 6 --> "))
cpu_choice=random.randint(1,6)
if user_choice < 7:
print("CPU picked --> ",cpu_choice)
run=cpu_choice+run
if user_choice == cpu_choice:
print("User is OUT!!")
run -= cpu_choice
print("Runs = %d \t Over = %d.%d\n"%(run,i//6,i%6))
break
print("Runs = %d \t Over = %d.%d\n"%(run,i//6,i%6))
else:
print("\nWRONG CHOICE!! %d ball is cancelled.\n"%i)
break
I might be missing something in your question, but it looks like you've already got it. break will force the for loop to exit. So if you wrap your break-statement in a conditional gate (if statement), you can set the criteria that must be met for the break.
Something like this comes to mind:
# Calculate the CPU's Random Integer ONCE
cpu_choice=random.randint(1,6)
# Iteratively Ask User for Input and Validate
for i in range(1,7):
# Capture Input from User
user_choice =int(input("Enter a number between 1 to 6 --> "))
# Verify Input in Specific Range
if user_choice not in range(1,7):
print("{} is not in the valid range. Try again.".format(user_choice))
else:
# Check if User Input Matches CPU's Selection
if user_choice == cpu_choice:
print("You've got the right number! The number was: {}".format(user_choice))
break # break out of the `for` loop!
# Not Correct Input from User
else:
print("{} is not the correct number. Try again.".format(user_choice))
Again, it seems like you've already come to this answer in a way. Are you asking something else instead?

I want to setup a would you like to retry

I have created a guess the number game, at the end of it I want it to ask the user if they would like to retry. I got it to take invalid responses and if Yes then it will carry on, but when I say no it still carries on.
import random
from time import sleep
#Introduction & Instructions
print ("Welcome to guess the number")
print ("A random number from 0 - 1000 will be generated")
print ("And you have to guess it ")
print ("To help find it you can type in a number")
print ("And it will say higher or lower")
guesses = 0
number = random.randint(0, 1)#Deciding the number
while True:
guess = int (input("Your guess: "))#Taking the users guess
#Finding if it is higher, lower or correct
if guess < number:
print ("higher")
guesses += 1
elif guess > (number):
print ("lower")
guesses += 1
elif guess == (number):
print ("Correct")
print (" ")
print ("It took you {0} tries".format(guesses))
#Asking if they want another go
while True:
answer = input('Run again? (y/n): ')
if answer in ('y', 'n'):
break
print ('Invalid input.')
if answer == 'y':
continue
if answer == 'n':
exit()
First of all, when you check :
if answer in ('y','n'):
This means that you are checking if answer exists in the tuple ('y','n').
The desired input is in this tuple, so you may not want to print Invalid input. inside this statement.
Also, the break statement in python stops the execution of current loop and takes the control out of it. When you breaked the loop inside this statement, the control never went to the printing statement or other if statements.
Then you are checking if answer is 'y' or 'n'. If it would have been either of these, it would have matched the first statement as explained above.
The code below will work :
#Asking if they want another go
while True:
answer = input('Run again? (y/n): ')
if answer == 'y':
break
elif answer == 'n':
exit()
else:
print ('Invalid input.')
continue
Also, you might want to keep the number = random.randint(0, 1)#Deciding the number statement inside the while loop to generate a new random number everytime the user plays the game.
This is because of the second while loop in your code. Currently when you put y or n it will break and run again (you don't see the invalid message due to the break occurring before reaching that code), it should be correct if you change it to the following:
while True:
answer = input('Run again? (y/n): ')
# if not answer in ('y', 'n'):
if answer not in ('y', 'n'): # edit from Elis Byberi
print('Invalid input.')
continue
elif answer == 'y':
break
elif answer == 'n':
exit()
Disclaimer: I have not tested this but it should be correct. Let me know if you run into a problem with it.

Never Ending Validation Check in Python

Working on a battleship game in python. My function to check the user's 'guess' input in resulting in an endless validation loop. I want a guess in the format of 'a10' on a 10x10 grid. The validation function i have built to help validate is as follows:
def validate_guess(self,guess):
while True:
if (len(guess)) in range(2, 4):
if guess[0] not in 'abcdefghij' or guess[1:] not in '1,2,3,4,5,6,7,8,9,10':
print("Sorry the Grid is a 10x10 square you must enter a valid position. Try again...")
continue
else:
return guess
else:
if len(guess) < 2 or len(guess) > 3:
print("Oops! That's too not the right amount of characters. Please try again...")
continue
If the user guesses an incorrect value--it does spot it--but the error is returning a never ending loop with the printed error statement.
This is the portion of my game where the validation function is being used:
while True:
print("\n")
# get guess from player one in coordinate form (example: a10)
guess = input("{}'s turn to guess: ".format(player1.player))
# strip characters from the guess input
guess = guess.strip()
# validate the guess
guess = self.validate_guess(guess)
# append the guess to a list for player 1
player1.guesses.append(guess)
# break down the coordinates into x and y variables
x, y = ship1.split_guess(guess)
# increment guesses
guesses += 1
# loop to assess whether, hit, miss or a won game
if any(guess in ship for ship in grid2.play_two_board):
print("HIT")
grid2.print_guess_board(x, y, "h")
for ship in grid2.play_two_board:
try:
ship.remove(guess)
print(len(Board.play_two_board))
self.check_if_sunk(ship)
win = self.play_one_win_check(player1.player)
if win == 1:
print ("GAVE OVER!")
break
except ValueError:
pass
else:
print("Miss!")
grid2.print_guess_board(x, y, "m")
Not sure if it might be because i have two While statements? Just really stuck here would appreciate any guidance. Thanks.
*****************************8
edit --changed function to include the guess without actually passing it that value from the input statement but still getting same problem.
def validate_guess(self):
guess = input("Please enter a location:")
while True:
if len(guess) in range(2, 4):
if guess[0] not in 'abcdefghij' or guess[1:] not in '1,2,3,4,5,6,7,8,9,10':
print("Sorry the Grid is a 10x10 square you must enter a valid position. Try again...")
continue
else:
return guess
else:
if len(guess) < 2 or len(guess) > 3:
print("Oops! That's too not the right amount of characters. Please try again...")
continue
and just calling it like this:
while True:
print("\n")
# get guess from player one in coordinate form (example: a10)
# guess = input("{}'s turn to guess: ".format(player1.player))
# strip characters from the guess input
# guess = guess.strip()
# validate the guess
guess = self.validate_guess()
Within validate_guess, when the user enters a bad value, you have to get new input before you check again. See here.
Either return an error code (True/False ?) from your function, or have the function loop until the input is valid. Just add a command for new input at the bottom of the function's while loop.

Categories