This is a piece of code that allows the user to choose a number and the computer guesses the number. However, when the computer is guessing it sometimes guesses the same number more than once. How do I stop the computer from guessing a number it has already guessed.
import random
print('This is a game where the user chooses\n' +
'a number for the computer to guess.')
guess = random.randint(1, 50)
number = int(input('\n\nChoose a number between 1 and 50: '))
while guess != number:
if guess > number:
guess = random.randint(number, 50)
else: guess < number
guess = random.randint(1, number)
print(guess)
input('Enter to see the next number')
print('The computer guessed your number:', guess,'!')
input('\n\n\nPress enter to exit!')
without rewriting other aspects of your game...
try this for not choosing the same number twice:
numbers = range(1,51)
ind = random.randint(0, len(numbers)-1)
guess = numbers[ind]
numbers.remove(ind+1)
numbers will contain only the list of unguessed numbers in the range to be guessed
(and won't take forever to find the unguessed number when you have a list of 49 guessed numbers!)
[EDIT] and from the comment below:
numbers = range(1,51)
guess = numbers.pop(random.randint(0,len(numbers)-1))
You can keep a cache of all of the numbers that the computer has guessed. Maybe using a dict or list or something.
However, this doesn't prevent the computer from guessing the same number (it just means it'll pick another number if it's already seen it).
If you want to NEVER guess the same number twice, you need to randomly draw numbers from a fixed set of numbers and then remove the number from the set. This guarantees that you will never pick the same number twice. However, depending on the number of candidates, this may or may not be a feasible solution (for example, if there are infinite number of possibilities).
The problem is you are only keeping the last guess information and guessing between that and the max or min of the total range. This will maintain the same approach but restrict guesses based on already knowing if its higher or lower then numbers already guessed.
max_guess = 50
min_guess = 1
guess = random.randint(min_guess, max_guess)
while guess != number:
if guess > number:
max_guess = guess - 1
else:
min_guess = guess + 1
guess = random.randint(min_guess, max_guess)
Do you want real random numbers and you are connected to Internet? https://pypi.python.org/pypi/randomdotorg/
I suggest also playing with random.seed or/and random.choice(range(min,max))
You could try this:
#!/usr/bin/env python
import random
print('This is a game where the user chooses a number for the computer to guess.')
guesses = range(1,51)
random.shuffle(guesses)
number = int(input('\n\nChoose a number between 1 and 50: '))
while True:
guess=guesses[0]
print "The computer guessed %d" % (guess)
if guess > number:
guesses=[x for x in guesses if x<guess]
elif guess < number:
guesses=[x for x in guesses if x>guess]
else:
break
print('The computer guessed your number!')
We'll store all possible guesses and randomize their order. Then we'll use information from the user to progressively eliminate potential guesses. We don't have to reshuffle or choose random numbers as we go because removing elements from a randomly ordered array maintains the "randomness" of the next element we'll pull from it.
While fixing the range on your random.randint() call would also resolve the problem (and in a cleaner fashion), the method I describe offers an alternative approach which is more general (say, for instance, if the user suddenly tells you that their number is odd).
Since this appears to be the "greater than, less than" game, I propose that the issue can be resolved by fixing the logic used for the range supplied to the random generator.
The computer should never guess from the same range twice as any choice the computer makes will always be "higher" or "lower" or "equal" to the number being sought - this information should be used to update the range of the next random number chosen. The updated range excludes the previous random guess.
Using number in the random range selection is wrong because it is independent of the guess made; it is simply what is being sought. You probably want two additional variables, minGuess and maxGuess, that are updated each loop and are used to limit the range of the random values.
Try to play the game against another person - how do you quickly "guess" the right number? If you're playing for minimum "guesses", you'll always divide the range directly in half, but you can pick randomly from the remaining range like the computer does (or should).
Related
On line 7 and 14 I cant figure out how to divide the variable.
import keyboard
import random
def main(Number, Start):
Number = random.randrange(1,100)
Start = False
QA = input('Press "K" key to begin')
if keyboard.is_pressed('K'):
Start = True
input('I"m thinking of a random number and I want that number divisible by two')
print(Number)
input('Please divide this by two. *IF IT IS NOT POSSIBLE RESTART GAME*\n')
if QA == int(Number) / 2:
print('.')
else:
print('.')
main(Number=' ' ,Start=' ')
What you probably want:
Pick a random number
Make user divide this number by two (?)
Do something based on whether the guess is correct
What is wrong with your code:
You are not picking a number divisible by two. The easiest way to ensure that your number is, indeed, divisible by two, is by picking a random number and then multiplying it by two: my_number = 2 * random.randrange(1, 50). Note the change in the range. Also note that the upper limit is not inclusive, which may be not what your meant here. A typical check for divisibility by N is using a modulo operator: my_number % N == 0. If you want users to actually handle odd numbers differently, you would need to write a separate branch for that.
input returns a string. In your case, QA = input('Press "K" key to begin') returns "K" IF user has actually done that or random gibberish otherwise. Then you are checking a completely unrelated state by calling keyboard.is_pressed: what you are meant to do here is to check whether the user has entered K (if QA == "K") or, if you just want to continue as soon as K is pressed, use keyboard.wait('k'). I would recommend sticking to input for now though. Note that lowercase/uppercase letters are not interchangeable in all cases and you probably do not want users to be forced into pressing Shift+k (as far as I can tell, not the case with the keyboard package).
input('I"m thinking of does not return anything. You probably want print there, possibly with f-strings to print that prompt along with your random number.
input('Please divide this by two. does not return anything, either. And you definitely want to store that somewhere or at least immediately evaluate against your expected result.
There is no logic to handle the results any differently.
Your function does not really need any arguments as it is written. Start is not doing anything, either.
Variable naming goes against most of the conventions I've seen. It is not a big problem now, but it will become one should you need help with longer and more complex code.
Amended version:
import random
import keyboard
def my_guessing_game():
my_number = random.randrange(1, 50) * 2
# game_started = False
print('Press "K" to begin')
keyboard.wait('k')
# game_started = True
print(f"I'm thinking of a number and I want you to divide that number by two. My number is {my_number}")
user_guess = input('Please divide it by two: ')
if int(user_guess) == my_number / 2:
# handle a correct guess here
print('Correct!')
pass
else:
# handle an incorrect guess here
pass
Alternatively, you can use the modulo operator % to test whether Number is divisible by 2:
if Number % 2 == 0:
print('.')
else:
print('.')
This will check whether the remainder of Number divided by 2 is equal to 0, which indicates that Number is divisible by 2.
I'm having a little trouble with this program. I'm a newbie to recursion by the way. Anyway I'm running this and i feel like it should work but it just becomes an infinite loop. Error message is "maximum recursion depth exceeded in comparison". I'm just taking a number, upper and lower limit from the user and having the computer guess it recursively. Any help would be greatly appreciated!
game where computer guesses user's number using recursion
import random as rand
def recursionNum(compGuess, magicNum):
#if the number that the user inputs for the computer to
#guess is to low it multiplies the number by 2 and then subtracts 1
#if the number is to high its divided(//) by 2 and then adds 1
if compGuess == magicNum:
print('You guessed right') #basecase
elif compGuess > magicNum:
print('Guess is', compGuess, '...Lower')
return recursionNum(compGuess //2+1, magicNum)
else:
print('Guess is', compGuess,'....Higher')
return recursionNum(compGuess *2-1, magicNum)
userNum =0
lowerLim = 0
upperLim = 0
while userNum not in range(lowerLim, upperLim):
lowerLim = int(input('What your lower limit: '))
upperLim = int(input('What is yor upper limit: '))
userNum = int(input('pick a number within your set limits:'))
compGuess = rand.randint in range(lowerLim, upperLim)
recursionNum(compGuess, userNum)
First of all, you will never print anything because the print statement is after the return. Return returns control back to the calling scope and so lines following a return statement are ignored. Second, there is no reason to use recursion for this. A simple for loop is much better suited for this. If you are just looking for an application to practice recursion on, may I suggest a Fibonacci number generator? It is a fairly popular example for the topic.
I am currently attempting to solve a homework problem. The problem states to collect user inputted numbers and then arrange them using asterisks to display a graph, with the largest number having forty asterisks and the rest becoming smaller as the numbers decrease.
_NumberList= []
print("Please type 'quit' to stop entering numbers.")
print("Please type 'print' to view the list that has been entered so far.")
a= True
while a:
_number= input("Please enter a number or make a selection. ")
if _number.isdigit():
_number=int(_number)
_NumberList.append(_number)
elif _number.isalpha():
_number= _number.lower()
if _number== 'quit':
a= False
if _number== 'print':
print(_NumberList)
else:
print("Please use digits to enter a number.")
print("For exmaple: 'ten' should be typed at '10'")
else:
print("Invalid entry.")
_NumberList.remove(max(_NumberList))
for i in range(len(_NumberList)):
_NumberList.remove(max(_NumberList))
However, I am unsure as to how to find the given proportions utilizing the numerical data. Thus far, I have considered utilizing the .pop function, but it simply isn't making a ton of sense so far. I considered making them go up by one step, but again, that doesn't seem logical, and the program can run for more than forty numbers. I know I will need to utilize a loop, hence the for loop at the end, but I'm not sure as to how to continue from there.
Your variable name _NumberList makes my eyes hurt, so I'll call it number_list
largest_number = max(number_list)
scale_factor = 40 / largest_number
scaled_number_list = [int(x * scale_factor) for x in number_list]
for scaled_number in scaled_number_list:
print('*' * scaled_number)
When I attempt to print a different message for there being more than one guess I am getting a double print message for when there is it is guessed in one iteration.
if guess >= 2:
print ('Your number is %d. I found it in %d guesses.' % (guess, iteration))
if iteration == 1:
print ('I found your number in 1 guess.')
current output:
Enter two numbers, low then high.
low = 2
high = 8
Think of a number in the range 2 to 8.
Is your number Less than, Greater than, or Equal to 4?
Type 'L', 'G', or 'E'): e
Your number is 4. I found it in 1 guesses.
I found your number in 1 guess.
You didn't defined what is "min_no" and "max_no" at first loop iteration in this line:
guess = guess_number(min_no, max_no)
And the last if is comparing the "guess" number instead of the "iteration" counter:
if guess == 1:
print ('I found your number in 1 guess.')
I can't figure out how to get the program to print a different message for the program guessing the number in 1 guess vs. it guessing it in more than one guess.
You are checking the wrong value. Change this:
if guess == 1:
to:
if iteration == 1:
I need the program to give me a message about input being inconsistent when the user fails to respond to the less than/greater than prompts properly.
You are using an else in a situation where it can never be true, since hint.lower() is already certainly a valid letter, and you already checked all possible values. Adding an else to that is futile and not what you need. An inconsistency is detected when min_no becomes greater than max_no. So change:
else:
raise ValueError('Your answers have not been consistent.')
to this:
if min_no > max_no:
raise ValueError('Your answers have not been consistent.')
Other improvements
For getting a random integer between two integers, including both as possible outcomes, don't use randrange, but randint. Otherwise the second value will never be selected.
Your code will sometimes produce the same number as the previous guess, even if the user answered with L or G. This is because you keep that guess in the new range of possible values. So change:
max_no = guess
to this:
max_no = guess - 1
And also:
min_no = guess
to this:
min_no = guess + 1
I am relatively new to programming with python (actually programming in general). I am making this 'Guess My Age' program that only has one problem:
import random
import time
import sys
print("\tAge Guesser!")
print("\t8 tries only!")
name = input("\nWhat's your name? ")
num = 80
min_num = 6
tries = 1
number = random.randint(min_num, num)
print("\nLet me guess... You are", number, "years old?")
guess = input("'Higher', 'Lower', or was it 'Correct'? ")
guess = guess.lower()
while guess != "correct":
if tries == 8:
print("\n I guess I couldn't guess your age....")
print("Closing...")
time.sleep(5)
sys.exit()
elif guess == "higher":
print("Let me think...")
min_num = number + 1 #### Here is my trouble - Don't know how to limit max number
time.sleep(3) # pause
elif guess == "lower":
print("Let me think...")
num = number - 1
time.sleep(3) # pause
number = random.randint(min_num, num) #<- Picks new random number
print("\nLet me guess... You are", number, "years old?")
guess = input("'Higher', 'Lower', or was it 'Correct'? ")
guess = guess.lower() #<- Lowercases
tries += 1 #<- Ups the tries by one
print("\nPfft. Knew it all along.")
time.sleep(10)
As you can see, I have 'num' as the max number for the random integer getting picked, but with:
elif guess == "higher":
print("Let me think...")
min_num = number + 1
it can go back up to however high it wants.
I want it to remember the last integer that 'num' was.
Say the program guessed 50 and I said 'Lower'. Then it said 30 and I said 'Higher'
I know I am probably sounding confusing, but please bear with me.
You need to define a maximum number as well as a minimum number. If they say their age is lower than a given age, you should set that age minus 1 as the maximum.
Of course, you also need to set an initial maximal age.
You might find it more useful to look into recursive functions for this kind of problem. If you define a function which takes min_age, max_age and tries_left as parameters, which comes up with a random number with between min_age and max_age and queries the user, you can then rerun the function (within itself) with a modified min_age, max_age and tries_left - 1. If tries_left is zero, concede defeat. This way you might get a better understanding of the logical flow.
I have left code out of this answer because, as you are a beginner, you will find it a useful exercise to implement yourself.
Cant you split out your guess into something like
max_num = 0
min_num = 0
elif guess =="lower":
max_num = number
if min_num!=0:
number = min_num+(max_num-min_num)/2
else:
number = max_num-1
elif guess =="higher":
min_num = number
if max_num!=0:
number=min_num+(max_num-min_num)/2
else:
number=min_num+1
Sorry it's not meant to be fully rigorous, and its a slight change on the logic you have there, but splitting out your variables so you have a higher and lower cap, that should help a lot?
Cheers
Please let me know if you need more elaboration, and I can try to write out a fully comprehensive version
It seems as though I was wrong in the fact that it did not remember the older integers. Before when running the program it would guess a number higher than the 'num' had specified. I don't know what I changed between then and now? But thank you for the help! #.#
This seems to work.
The only changes I really made:
-Variable names were confusing me, so I changed a couple.
-Note that if you try to mess with it (lower than 5, higher than 3... "Is it 4?" if you say it's higher or lower, you'll get an error).
The first time you set min and max numbers, you do it outside of the loop, so this script does "remember" the last guess and applies it to the new min, max inside of the loop. Each time it runs, the min will get higher or the max will get lower, based on the feedback from when the user checks the guess. If you had stuck the "min_num=6" and the "num=80" inside of the loop, the guesses would never get better.
import random
import time
import sys
print("\tAge Guesser!")
print("\t8 tries only!")
name = input("\nWhat's your name? ")
max_num = 10
min_num = 1
tries = 1
guess = random.randint(min_num, max_num)
print("\nLet me guess... You are", guess, "years old?")
check = raw_input("'Higher', 'Lower', or was it 'Correct'? ")
check = check.lower()
while check != "correct":
if tries == 8:
print("\n I guess I couldn't guess your age....")
print("Closing...")
time.sleep(5)
sys.exit()
elif check == "higher":
print("Let me think...")
min_num = guess + 1
time.sleep(3) # pause
elif check == "lower":
print("Let me think...")
max_num = guess - 1
time.sleep(3) # pause
guess = random.randint(min_num, max_num) # <- Picks new random number
print("\nLet me guess... You are", guess, "years old?")
check = input("'Higher', 'Lower', or was it 'Correct'? ")
check = check.lower() # <- Lowercases
tries += 1 # <- Ups the tries by one
print("\nPfft. Knew it all along.")
time.sleep(10)