Can someone tell me why this wont loop? - python

I'm making a number guessing game and can someone tell me why it wont work properly?
import random
import time
time.time()
count=0
a = random.randint(0,100)
b = int(input("What number will you guess?"))
while b != a:
if b > a:
print("TOO BIG")
count = count + 1
elif b < a:
print("TOO SMALL")
count = count + 1
else b == a:
print("YOU WIN")
count = count + 1
time=time.time()
print("You took",count,"tries")
print("It took you",time,"second")

The reason this isn't working properly is because you're calling b = input outside of your while loop. As it stands, the user will be asked a single time what their guess is, then the loop will just move infinitely, because b is never being modified.
This loop will accomplish more what you want:
a = random.randint(0,100)
b = -1
while b != a:
b = int(input("What number will you guess?"))
A few notes, though:
Firstly, as Lee Daniel Crocker points out, the user will actually never see "YOU WIN", because you've structured your if-elif-else statement incorrectly. else by definition cannot have a condition - it exists purely in exclusion to all other conditionals in the same block. Additionally, your else statement is the opposite of your while condition. When that else becomes true, the loop exits. You'll need to handle printing "YOU WIN" somewhere else.
Second, you're not validating the user's input in any way - if they enter 'a', the program will crash, because you can't cast 'a' to an int. Either add an exception handler (for ValueError) or using isdigit() on the string, then casting it.
Third, you're not using time.time() correctly - you need to subtract the time at which the user wins from the time at which they started, then represent that value, which is in seconds, in some meaningful way. As it stands you're telling each player that they took the number of seconds since the beginning of the UNIX epoch to complete the game.
Also, for usability reasons, you should probably provide the user some way to break out - a string like "QUIT" - because as it stands, the only way to restart/quit is to either close the application or KeyboardInterrupt.

You need to accept input in the loop. Move the line b = int(input("What number will you guess?")) within the loop.

Related

Does if/else statements require continue?

I am a beginner in Python and from what I understand, the continue statement in Python returns the control to the beginning of the while loop.
guesses = [0]
while True:
# we can copy the code from above to take an input
guess = int(input("I'm thinking of a number between 1 and 100.\n What is your guess? "))
if guess < 1 or guess > 100:
print('OUT OF BOUNDS! Please try again: ')
continue
# here we compare the player's guess to our number
if guess == num:
print(f'CONGRATULATIONS, YOU GUESSED IT IN ONLY {len(guesses)} GUESSES!!')
break
# if guess is incorrect, add guess to the list
guesses.append(guess)
# when testing the first guess, guesses[-2]==0, which evaluates to False
# and brings us down to the second section
if guesses[-2]:
if abs(num-guess) < abs(num-guesses[-2]):
print('WARMER!')
else:
print('COLDER!')
else:
if abs(num-guess) <= 10:
print('WARM!')
else:
print('COLD!')
Above is the code for the game called 'guess the number from 1 - 100'.
The first if statement where guess < 1 or guess > 100, it will print "Out of bounds!" and then continue which loops to the top of the code and asks for the user's input again.
But for the 3rd if statement where if guesses[-2]:, it does not require continue for neither if nor else.
Sorry if you do not understand what I am asking. But essentially, I want to know why 'continue' statement is not required after print('WARMER!), print('COLDER!'), print('WARM!') and print('COLD!').
guesses = [0]
while True:
# we can copy the code from above to take an input
guess = int(input("I'm thinking of a number between 1 and 100.\n What is your guess? "))
if guess < 1 or guess > 100:
print('OUT OF BOUNDS! Please try again: ')
continue
# here we compare the player's guess to our number
if guess == num:
print(f'CONGRATULATIONS, YOU GUESSED IT IN ONLY {len(guesses)} GUESSES!!')
break
# if guess is incorrect, add guess to the list
guesses.append(guess)
# when testing the first guess, guesses[-2]==0, which evaluates to False
# and brings us down to the second section
if guesses[-2]:
if abs(num-guess) < abs(num-guesses[-2]):
print('WARMER!')
**continue**
else:
print('COLDER!')
**continue**
else:
if abs(num-guess) <= 10:
print('WARM!')
**continue**
else:
print('COLD!')
**continue**
Note that all four of these print statements are the last of their execution branch.
Meaning, if guesses[-2] evaluates as true, than the else part won't be executed at all. Then, if abs(num-guess) < abs(num-guesses[-2]) evaluates to true, again - its else won't be executed. It means that for this execution branch the print('WARMER!') is the last statement of the loop and hence continue is not needed.
Same logic applies to all other 3 print statements.
In the case "guess < 1 or guess > 100" you want to skip the rest of the loop since you dont want to append the guess to the guesses list. Therefore you use continue.
The 'continue' statement is not required after print('WARMER!) etc because you dont need to skip any code afterwards. In this case because there wont be any lines executed after the print statement anyway.
First of all, if/else doesn't require continue. It's optional.
From what I understand you want to know why you used continue in the first if/else and not in the last if/else.
In the first one, after executing if statement it will transfer the control to while True: but for the last if/else statement it is not needed as the control will automatically go to while True: as it is the end of the loop and even if you had used continue it wouldn't have made a difference.
For further references
If you want to know why the continue is not always in if or else, this is due to the fact that when the operation arrives (true), the loop is exited and the code continues to run.

My function is too long and I'm told to optimize

So I'm doing a project for an online class and when i got it scored it came back as not passed because my "play game" function was more than 18 lines long and I'm supposed to optimize it. The problem is they didn't make any suggestions as to what i should do and I keep looking at it and feel as if I need everything in it to make the fill in the blank quiz I'm building work. Any suggestions would be great as I am still very new to coding, and maybe what they are asking me to do is easy and I'm over complicating it in my head. This is the part of the code they want optimized...
def play():
'''
This is the main function which allows to play the game/quiz.
It calls the previous functions we have written.
'''
quiz = difficulty_level(user_level) #gives the difficulty
paragraph that the user asks for.
print quiz
print "\nYou will get maximum 3 guesses for each blank. Good luck.\n"
answers_list = relate_answer(user_level) #makes sure that the right
list is called up
blanks_index = 0
answers_index = 0
number_of_guesses = 3
while blanks_index < len(blanks): #This loop keeps going if all the
blanks are not replaced.
user_answer = raw_input("type in your answer for " + blanks[blanks_index] + ": ")
if check_answer(user_answer,answers_list,answers_index) == "Correct":
print "Awesome job! You gave the right answer!\n"
quiz = quiz. replace(blanks[blanks_index],user_answer)
blanks_index += 1
answers_index += 1
number_of_guesses = 3
print quiz
else:
number_of_guesses -= 1
if number_of_guesses == 0:
print "Game over! But try again!"
break
elif number_of_guesses < 0:
print "invalid"
break
else:
print "please try again."
print "You have " + str(number_of_guesses) + " guesses left."
print "Congratulations! You really know your stuff!."
play()
A quick summation of changes:
It looks like answers_index and blanks_index share the same state, no matter what, so we can generalize that to one variable idx. That cuts down on the number of variables you have to keep track of.
As others have suggested, initializing variables as a tuple like var1, var2 = 1, 2 decreases length and makes code more readable (to a point). If you have lots of variables to initialize, you can break the initialization into groups of related variables.
Setting a default value to user_level increases readability, and also gives an easy place to start debugging your function. This occurs in the def statement, so if you don't pass the argument, user_level will be 1, otherwise it will be whatever you give it in the function call. Example play(user_level=40) will overwrite that default value.
Putting the game loss condition at the start of the while loop increases visibility of the checks the code goes through before executing anything unnecessary. This should help you avoid the case where guess would be less than 0, because that code won't execute when guess==0 is True.
Setting a lose boolean with the check after exiting the while loop will also prevent the wrong print statement at the end from executing. That way, if the player loses, you will print the proper message.
Breaking the update of quiz into another function adds a more compact breakpoint into the code. In general, smaller functions that do less are preferable to large functions that do a lot. The smallest number of changes necessary is a good standard for what should be wrapped into a function, though this could be considered a stylistic convention more than a hard and fast rule.
The correct_answer method allows you to update quiz and guess in one line, and if something is wrong with the update itself, you don't have to run the entire script over and over. Instead you can take the quiz that might be causing the problem and plug it into that function until you find what's causing the problem.
I've made some minimal updates to the function you've provided which keep most of your conventions so far. Hopefully this is helpful, and happy coding!
def correct_answer(quiz, blank, answer):
"""
Function to update the quiz and return
both the quiz and reset guess to 3
"""
print("Awesome job! You gave the right answer!\n")
quiz = quiz.replace(blank, answer)
return quiz, 3
def play(user_level=1):
'''
This is the main function which allows to play the game/quiz.
It calls the previous functions we have written.
'''
idx, guess, lose = 0, 3, False
quiz = difficulty_level(user_level) #gives the difficulty paragraph that the user asks for.
print(quiz)
print("\nYou will get maximum 3 guesses for each blank. Good luck.\n")
answers_list = relate_answer(user_level) #makes sure that the right list is called up
while idx < len(blanks): #This loop keeps going if all the blanks are not replaced.
if guess <= 0:
lose = True
break
user_answer = raw_input("type in your answer for %s:" %str(blanks[idx]))
if check_answer(user_answer,answers_list,idx) == "Correct":
quiz, guess = correct_answer(quiz, blanks[idx], user_answer)
print(quiz)
else:
guess -= 1
print("please try again.\nYou have %s guesses left.\n"%str(guess))
idx += 1
if lose:
print("Game over, try again")
else:
print("Congratulations! You really know your stuff!.")
play(user_level = 3)

Write a simple looping program

I want to write a program with this logic.
A value is presented of the user.
Commence a loop
Wait for user input
If the user enters the displayed value less 13 then
Display the value entered by the user and go to top of loop.
Otherwise exit the loop
You just need two while loops. One that keeps the main program going forever, and another that breaks and resets the value of a once an answer is wrong.
while True:
a = 2363
not_wrong = True
while not_wrong:
their_response = int(raw_input("What is the value of {} - 13?".format(a)))
if their_response == (a - 13):
a = a -13
else:
not_wrong = False
Although you're supposed to show your attempt at coding towards a solution and posting when you encounter a problem, you could do something like the following:
a = 2363
b = 13
while True:
try:
c = int(input('Subtract {0} from {1}: '.format(b, a))
except ValueError:
print('Please enter an integer.')
continue
if a-b == c:
a = a-b
else:
print('Incorrect. Restarting...')
a = 2363
# break
(use raw_input instead of input if you're using Python2)
This creates an infinite loop that will try to convert the input into an integer (or print a statement pleading for the correct input type), and then use logic to check if a-b == c. If so, we set the value of a to this new value a-b. Otherwise, we restart the loop. You can uncomment the break command if you don't want an infinite loop.
Your logic is correct, might want to look into while loop, and input. While loops keeps going until a condition is met:
while (condition):
# will keep doing something here until condition is met
Example of while loop:
x = 10
while x >= 0:
x -= 1
print(x)
This will print x until it hits 0 so the output would be 9 8 7 6 5 4 3 2 1 0 in new lines on console.
input allows the user to enter stuff from console:
x = input("Enter your answer: ")
This will prompt the user to "Enter your answer: " and store what ever value user enter into the variable x. (Variable meaning like a container or a box)
Put it all together and you get something like:
a = 2363 #change to what you want to start with
b = 13 #change to minus from a
while a-b > 0: #keeps going until if a-b is a negative number
print("%d - %d = ?" %(a, b)) #asks the question
user_input = int(input("Enter your answer: ")) #gets a user input and change it from string type to int type so we can compare it
if (a-b) == user_input: #compares the answer to our answer
print("Correct answer!")
a -= b #changes a to be new value
else:
print("Wrong answer")
print("All done!")
Now this program stops at a = 7 because I don't know if you wanted to keep going with negative number. If you do just edited the condition of the while loop. I'm sure you can manage that.

I need to figure out how to make my program repeat. (Python coding class)

I am a beginner student in a python coding class. I have the majority of the done and the program itself works, however I need to figure out a way to make the program ask if wants a subtraction or an adding problem, and if the user would like another question. I asked my teacher for assistance and he hasn't gotten back to me, so I'm simply trying to figure out and understand what exactly I need to do.
import random
x = int(input("Please enter an integer: "))
if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('More')
maximum = 10 ** x;
maximum += 1
firstnum = random.randrange(1,maximum) # return an int from 1 to 100
secondnum = random.randrange(1, maximum)
compsum = firstnum + secondnum # adds the 2 random numbers together
# print (compsum) # print for troubleshooting
print("What is the sum of", firstnum, " +", secondnum, "?") # presents problem to user
added = int(input("Your answer is: ")) # gets user input
if added == compsum: # compares user input to real answer
print("You are correct!!!")
else:
print ("Sorry, you are incorrect")
You'll want to do something like this:
def foo():
print("Doing good work...")
while True:
foo()
if input("Want to do more good work? [y/n] ").strip().lower() == 'n':
break
I've seen this construct (i.e., using a break) used more often than using a sentinel in Python, but either will work. The sentinel version looks like this:
do_good_work = True
while do_good_work:
foo()
do_good_work = input("Want to do more good work? [y/n] ").strip().lower() != 'n'
You'll want to do more error checking than me in your code, too.
Asking users for input is straightforward, you just need to use the python built-in input() function. You then compare the stored answer to some possible outcomes. In your case this would work fine:
print('Would you like to test your adding or subtracting skills?')
user_choice = input('Answer A for adding or S for subtracting: ')
if user_choice.upper() == 'A':
# ask adding question
elif user_choice.upper() == 'S':
# ask substracting question
else:
print('Sorry I did not understand your choice')
For repeating the code While loops are your choice, they will repeatedly execute a statement in them while the starting condition is true.
while True: # Condition is always satisfied code will run forever
# put your program logic here
if input('Would you like another test? [Y/N]').upper() == 'N':
break # Break statement exits the loop
The result of using input() function is always a string. We use a .upper() method on it which converts it to UPPERCASE. If you write it like this, it doesn't matter whether someone will answer N or n the loop will still terminate.
If you want the possibility to have another question asked use a while loop and ask the user for an input. If you want the user to input whether (s)he want an addition or substraction you already used the tools to ask for such an input. Just ask the user for a string.

Loop and validation in number guessing game

I have previously studied Visual Basic for Applications and am slowly getting up to speed with python this week. As I am a new programmer, please bear with me. I understand most of the concepts so far that I've encountered but currently am at a brick wall.
I've written a few functions to help me code a number guessing game. The user enters a 4 digit number. If it matches the programs generated one (I've coded this already) a Y is appended to the output list. If not, an N.
EG. I enter 4567, number is 4568. Output printed from the list is YYYN.
import random
def A():
digit = random.randint(0, 9)
return digit
def B():
numList = list()
for counter in range(0,4):
numList.append(A())
return numList
def X():
output = []
number = input("Please enter the first 4 digit number: ")
number2= B()
for i in range(0, len(number)):
if number[i] == number2[i]:
results.append("Y")
else:
results.append("N")
print(output)
X()
I've coded all this however theres a few things it lacks:
A loop. I don't know how I can loop it so I can get it to ask again. I only want the person to be able to guess 5 times. I'm imagining some sort of for loop with a counter like "From counter 1-5, when I reach 5 I end" but uncertain how to program this.
I've coded a standalone validation code snippet but don't know how I could integrate this in the loop, so for instance if someone entered 444a it should say that this is not a valid entry and let them try again. I made an attempt at this below.
while myNumber.isnumeric() == True and len(myNumber) == 4:
for i in range(0, 4)):
if myNumber[i] == progsNumber[i]:
outputList.append("Y")
else:
outputList.append("N")
Made some good attempts at trying to work this out but struggling to patch it all together. Is anyone able to show me some direction into getting this all together to form a working program? I hope these core elements that I've coded might help you help me!
To answer both your questions:
Loops, luckily, are easy. To loop over some code five times you can set tries = 5, then do while tries > 0: and somewhere inside the loop do a tries -= 1.
If you want to get out of the loop ahead of time (when the user answered correctly), you can simply use the break keyword to "break" out of the loop. You could also, if you'd prefer, set tries = 0 so loop doesn't continue iterating.
You'd probably want to put your validation inside the loop in an if (with the same statements as the while loop you tried). Only check if the input is valid and otherwise continue to stop with the current iteration of your loop and continue on to the next one (restart the while).
So in code:
answer = [random.randint(0, 9) for i in range(4)]
tries = 5
while tries > 0:
number = input("Please enter the first 4 digit number: ")
if not number.isnumeric() or not len(number) == len(answer):
print('Invalid input!')
continue
out = ''
for i in range(len(answer)):
out += 'Y' if int(number[i]) == answer[i] else 'N'
if out == 'Y' * len(answer):
print('Good job!')
break
tries -= 1
print(out)
else:
print('Aww, you failed')
I also added an else after the while for when tries reaches zero to catch a failure (see the Python docs or maybe this SO answer)

Categories