Restricting the domain of integer values accepted as input in python - python

I'm building a command line game using python.A main feature of this game is to get the user's input of either 1 or 2 as integer values.Any other character must be rejected.I used try-except & if-else condition to do this like shown below.I want to know whether there is any better method to get this done in one line or some other way without having to indent a whole bunch of code.
if __name__ == '__main__':
# INITIALIZE THE TOTAL STICKS , DEPTH OF THE TREE AND THE STARTINGG PLAYER
i_stickTotal = 11 # TOTAL NO OF STICKS IN THIS GAME
i_depth = 5 # THE DEPTH OF THE GOAL TREEE THE COMPUTER WILL BUILD
i_curPlayer = 1 # THIS WILL BE +1 FOR THE HUMAN AND -1 FOR THE COMPUTER
print("""There are 11 sticks in total.\nYou can choose 1 or 2 sticks in each turn.\n\tGood Luck!!""")
# GAME LOOP
while i_stickTotal > 0:
print("\n{} sticks remain. How many would you pick?".format(i_stickTotal))
try:
i_choice = int(input("\n1 or 2: "))
if i_choice - 1 == 0 or i_choice - 2 == 0:
i_stickTotal -= int(i_choice)
if WinCheck(i_stickTotal, i_curPlayer):
i_curPlayer *= -1
node = Node(i_depth, i_curPlayer, i_stickTotal)
bestChoice = -100
i_bestValue = -i_curPlayer * maxsize
# Determine No of Sticks to Remove
for i in range(len(node.children)):
n_child = node.children[i]
#print("heres what it look like ", n_child.i_depth, "and",i_depth)
i_val = MinMax(n_child, i_depth-1, i_curPlayer)
if abs(i_curPlayer * maxsize - i_val) <= abs(i_curPlayer*maxsize-i_bestValue):
i_bestValue = i_val
bestChoice = i
#print("Best value was changed # ", i_depth, " by " , -i_curPlayer, " branch ", i, " to ", i_bestValue)
bestChoice += 1
print("Computer chooses: " + str(bestChoice) + "\tbased on value: " + str(i_bestValue))
i_stickTotal -= bestChoice
WinCheck(i_stickTotal, i_curPlayer)
i_curPlayer *= -1
else:
print("You can take only a maximum of two sticks.")
except:
print("Invalid input.Only Numeric Values are accepted")

You can create a function to check user input and use below code.
while True:
var = int(input('Enter value (1 or 2) - '))
if var not in range(1, 3):
print('Invalid entry, please try again...')
continue
else:
break

Write a function that loops, calling input, until the value satisfies your constraint. Perhaps call it get_user_input. Then call that in your main function instead of input. For added value, pass a lambda into that function as a predicate to test the user input value - that'll make get_user_input more general.

Related

Harvard CS50P PSET 4: timed out while waiting for program to exit

I'm solving this problem.
My code works when I test it but it is failing the provided check with the error:
:( Little Professor accepts valid level // timed out while waiting for program to exit
It passes the three previous checks for invalid levels. Any insight to why this might be happening would help.
Here is my code:
def main():
level = get_level()
q=1
s=0
while q<=10:
try:
x = generate_integer(level)
y = generate_integer(level)
ans = x + y
eq = int(input(f'{x} + {y} = '))
if ans == eq:
s += 1
pass
elif ans != eq:
c = 1
while c <= 2:
print('EEE')
eq = int(input(f'{x} + {y} = '))
if ans == eq:
s += 1
break
else:
c += 1
if c == 3:
print('EEE')
print(f'{x} + {y} = {ans}')
q += 1
except EOFError:
pass
print(f'Score: {s}')
def get_level():
valid_inputs = (1,2,3)
while True:
try:
level = int(input('Level: '))
if level in valid_inputs:
return level
else:
pass
except ValueError:
pass
def generate_integer(level):
max = 10**level-1
min = 10**(level-1)
if level == 1:
min == 0
num = random.randint(min,max)
return num
main()
I ran your program (as-is) and found at least 1 problem. I'm not sure if it's why check50 flags that error, but you will need to fix it before it will pass. I entered Level: 1, then got a duplicate equation (4 + 5 = ). This violates a requirement buried under How to Test: "Your program should output 10 distinct problems" (emphasis mine). It's easy to miss - I didn't see it until someone mentioned it on the CS50P ED Forum.
Also, the last 2 lines of your program are supposed to be:
if __name__ == "__main__":
main()
Instead, only you have:
main()
Finally, this is an observation on your code structure. You have a lot of if statements for the 3 attempts to answer the question. It's overly complicated and kind of hard to follow. Hint: It can be simplified with another loop to prompt and check answers.

if, elif & !=, == boolean operations only return "false" with inputs

I am creating an Among Us ripoff (for fun!) and the while True & if/elif/else statements will only return false (not An Impostor) with the inputs. I had created a list for the names and 2 random elements from the list will be chosen as An Impostor. However, whenever I input a name that is The Impostor, it will only return
(player) was not An Impostor.
Here is my code;
import sys, time, random
names = ["player1", "player2", "player3", "player4", "player5", "player6", "player7", "player8", "player9", "player10"]
print("Players: ")
for x in names:
print(x)
print('—————————————————————————')
impostor1 = random.choice(names)
impostor2 = random.choice(names)
crewmates = 8
impostors = 2
tries = 6
while True:
talk = input("Guess who The Impostor(s) are. " + str(crewmates) + " Crewmates are left. " + str(impostors) + " Impostors are left. You have " + str(tries) + " tries left.")
if talk in names:
print(talk + " was voted for.")
time.sleep(0.1)
if talk != impostor1 or talk != impostor2:
notimp = talk + " was not An Impostor. "
names.remove(talk)
for y in notimp:
sys.stdout.write(y)
sys.stdout.flush()
time.sleep(0.05)
crewmates -= 1
tries -= 1
elif talk == impostor1 or talk == impostor2:
wasimp = talk + " was An Impostor. "
names.remove(talk)
for v in wasimp:
sys.stdout.write(v)
sys.stdout.flush()
time.sleep(0.1)
impostors -= 1
else:
print("That player was either ejected or is not a valid player.")
However, whenever I put the Impostor in the input, it says it isn't An Impostor?
I think this line is the source of the problem:
if talk != impostor1 or talk != impostor2:
Let's say impostor1 is player1 and impostor2 is player2 and someone input in player1, according to Python Boolean expression operator or that if statement will evaluate like this:
if player1 != impostor1 evaluated to False because player1 is indeed equals to impostor1.
So far so good, but because the first test is a False, Python simply evaluates and returns the right side operand which may be either True or False. In your case Python will evaluate if talk != impostor2 and return True, thereafter executes the nested block.

TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

I am having trouble with feeding a value into a function, and not having that values type be an int, instead it is a NoneType, which I cannot operate with. Here's the error message I am thrown:
Traceback (most recent call last):
File "NumberGame1.py", line 140, in <module>
main()
File "NumberGame1.py", line 29, in main
result = guessinggame(number)
File "NumberGame1.py", line 92, in guessinggame
if guess - number <= level * 0.1:
TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'
Here is all of the code:
import random
import timeit
def main():
print "\nWelcome to Ethan's Number Guessing Game!"
print "What would you like to do?: \n1. Play game\n2. View High Scores\n3. View Credits"
menuchoice = input()
## choice is Menu Decision
if menuchoice == 1:
difficulty = input("Pick a difficulty!: \n1: Easy\n2: Medium\n3: Hard\n4: Insane\n5. Out of control!\n6. Custom\n")
leveldif = difcalc(difficulty)
## Exits program if you don't choose a difficulty
global level
level = leveldif[0]
difmod = leveldif[1]
number = numbergenerator(level)
result = guessinggame(number)
totalTime = result[0]
tries = result[1]
scorer(tries, totalTime)
elif menuchoice == 2:
## Figure out how to access high scores
print "This feature is currently under development.\n"
elif menuchoice == 3:
print "\nDeveloped by Ethan Houston"
raw_input()
print "\nDeveloped in Python 2.7.9 using Sublime Text 2"
raw_input()
print "\nThanks for playing :)"
raw_input()
## Simple credits reel. Go me
def difcalc(difficulty):
if difficulty == 1:
leveldif = [10, 1]
elif difficulty == 2:
leveldif = [50, 1.5]
elif difficulty == 3:
leveldif = [100, 2]
elif difficulty == 4:
leveldif = [1000, 10]
elif difficulty == 5:
leveldif = [10000, 20]
elif difficulty == 0:
leveldif = [1, 1]
return leveldif
def guessinggame(number):
tries = 1
## Counter for number of attempts at guessing
guess = input("Guess a number between 1 and " + str(level) + "!: ")
## Takes input from user
while guess > level:
guess = input("Above range!\nMake sure to guess between 1 and " + str(level) + "!: ")
## If the user chooses a number above the range, makes you try again until within range
startTime = timeit.default_timer()
## Starts a timer once first valid number is selected
while guess != number:
## While loop that runs as long as guess isn't correct
if guess > number:
if guess - number <= level * 0.1:
guess = input("Too high, close!: ")
tries += 1
## If difference between guess and answer is less than or equal to 10% of level,
## prints different prompt
else:
guess = input("Too high, guess again: ")
tries += 1
## Normal behavior
elif guess < number:
if guess - number <= level * 0.1:
guess = input("Too low, close!: ")
tries += 1
## If difference between guess and answer is less than or equal to 10% of level,
## prints different prompt
else:
guess = input("Too low, guess again: ")
tries += 1
## Normal behavior
endTime = timeit.default_timer()
## Takes the time after the correct number is chosen
totalTime = endTime - startTime
## Calculates time difference between start and finish
result = [totalTime, tries]
return result
def numbergenerator(level):
global number
number = random.randint(1, level)
def scorer(tries, totalTime):
print "\nCorrect! It took you " + str(round(totalTime, 2)) + " seconds and " \
+ str(tries) + " tries to guess.\n"
## Once user guesses correct number, program tells how many tries it took, and how long
score = 1/(1+(tries * round(totalTime, 2))) * 1000 * difmod
## Calcualtes score, making lower times and fewer tries yield a higher score
## Difmod takes into account the difficulty
## Multiply by 1000 to make number more readable
print "Score: " + str(round(score, 2)) + "\n"
## Printsthe score, rounded to 1 decimal place
main()
When a python function does not explicitly return anything , it returns None . In your case, you have a function -
def numbergenerator(level):
global number
number = random.randint(1, level)
This does not return anything, instead you set a global variable number .
But when you are calling this function in main() , you do -
number = numbergenerator(level)
And here number is not a global variable (Even if it was a global it wouldn't matter) , so after calling numbergenerator() , since it does not return anything, it returns None , which gets set to number variable, and hence number is None, causing the issue you are having.
I believe you do not need to use global variable there, you should just return the number from numbergenerator() function , example -
def numbergenerator(level):
return random.randint(1, level)

python appears to be overwriting variables by itself [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 8 years ago.
As an attempt to pick up the basics of python I decided to try and recreate nim sticks in python 3. I'm using pyCharm for this development.
When the AI player checks for what sticks to remove the lines variable in the game_ai function appears to overwrite itself for no apparent reason.
main.py:
import ai
import helpers
lines = [1, 3, 5, 7]
winner = 0
# String introduction
print(' _____ _ _ _ ')
print(' / ____| | (_) | | ')
print(' | (___ | |_ _ ___| | _____ ')
print(' \___ \| __| |/ __| |/ / __| ')
print(' ____) | |_| | (__| <\__ \ ')
print(' |_____/ \__|_|\___|_|\_\___/ ')
print('The last one to pick up a stick loses!')
# Keep going till we have a winner!
while winner == 0:
# Redraw the stick board at the start of a turn
helpers.redraw_sticks(lines)
# Get user input and remove their sticks
line = helpers.check_input('Please select a line to remove (a) stick(s) from:', 0, 4, 'line', lines)
amount = helpers.check_input('Please select how many stick(s) you wish to remove:', 0, 7, 'amount', lines)
lines = helpers.remove_sticks(lines, line, amount)
# Check for winner
winner = helpers.winner_check(lines, 1)
# Only play the AI if the player doesn't win this go
if winner == 0:
# Redraw the board after a go
helpers.redraw_sticks(lines)
# Play the AI
ai_turn = ai.game_ai(lines)
lines = helpers.remove_sticks(lines, ai_turn[0], ai_turn[1] - 1)
# Check for winner
winner = helpers.winner_check(lines, 2)
# Declare the winner!
if winner == 1:
print('The Human Player wins the game!')
else:
print('The Computer Player wins the game!')
ai.py:
import helpers
import time
# Our cool kid AI
def game_ai(lines):
winning_data = [0, 0]
winning_combo = False
# Keep going till we get a winning nim sum
while not winning_combo:
line = 1
# Go through every line
while line <= 4 and not winning_combo:
# Reset amount value
amount = 7
# Make it look like there's actual heavy processing going on here
print('AI player is thinking...')
time.sleep(1)
# Only go if the line actually has sticks
if lines[line - 1] != 0:
# Test certain values in a line
while amount >= 1 and not winning_combo:
lines_test = helpers.remove_sticks(lines, line, amount)
# If we have a nim sum of 0 we go!
if helpers.nim_sum(lines_test) == 0:
winning_combo = True
winning_data[0] = line
winning_data[1] = amount
# I'm going to win, I shouldn't do this...
if helpers.lines_checksum(lines_test) == 0:
winning_data[1] = amount - 1
# Increment amount
amount -= 1
# Increment line
line += 1
# Return winning data
return winning_data
helpers.py:
import sys
# Redraws the stick board with updated values
def redraw_sticks(lines):
# Loop through each line
for (line, sticks) in enumerate(lines):
if sticks > 0:
# Output line number
sys.stdout.write(str(line + 1) + ': ')
# And output how many sticks there are
for x in range(0, sticks):
sys.stdout.write('|')
print('')
# Remove sticks on request
def remove_sticks(lines, line, amount):
# Set line to the correct pointer
line -= 1
if lines[line] < amount:
lines[line] = 0
else:
lines[line] = lines[line] - amount
return lines
# Check if an input is an integer and in the correct range
def check_input(request_message, min_value, max_value, check_type, lines):
inputting = True
user_input = 0
while inputting:
user_input = input(request_message)
try:
# Check if the input is an integer
user_input = int(user_input)
# Make sure the input fits in our defined range
if max_value >= user_input > min_value:
inputting = False
# Check if the line has any sticks left
if check_type == 'line' and lines[user_input - 1] <= 0:
print('Error: Line is already empty')
inputting = True
else:
print('Error: Invalid range value entered')
except ValueError:
print('Error: String input entered')
# Return the input after checks
return user_input
def nim_sum(lines):
# First we need to calculate the multiples
nim_sum_total = 0
for (pointer, sticks) in enumerate(lines):
# Calculate multiples of 4
nim_sum_total += sticks // 4
sticks %= 4
# Calculate multiples of 2
nim_sum_total += sticks // 2
sticks %= 2
# Calculate multiples of 1
nim_sum_total += sticks // 1
return nim_sum_total % 2
# Check how many sticks are left
def lines_checksum(lines):
checksum = 0
# Calculate remaining sticks
for sticks in lines:
checksum += sticks
return checksum
# Check if a winner has been found
def winner_check(lines, player):
checksum = lines_checksum(lines)
# Return if we have a winner
if checksum == 1:
return player
else:
return 0
Everything in Python is passed by reference, so the lines variable in game_ai refers to the same list as the lines variable in your main program. Thus when you remove sticks from it, you end up clearing the shared lines variable.
To resolve this, you can make a copy of the lines first in game_ai, as lines = lines.copy().

python: program hanging! (print issue maybe?)

So, I'm quite nooby at python. I decided to make a program that makes prime numbers. I know there's probably a function built in that does this but I decided to do it myself.
number = 1
numlist = list()
for x in range (0, 1000):
numlist.append("")
print "Created list entry " + str(x)
while True:
number = number + 1
if number % 2 != 0:
numscrollerA = 1
numscrollerB = 1
while numscrollerA <= number:
if float(number) / float(numscrollerA) == float(int(number)):
numlist[numscrollerA] = "true"
if float(number) / float(numscrollerA) != float(int(number)):
numlist[numscrollerA] = "false"
numscrollerA = numscrollerA + 1
while numscrollerB <= number:
if numscrollerB != 1 and numscroller != number and numlist[numscrollerB] == "true":
primestatus = "false"
else:
primestatus = "true"
if primestatus == "true":
print number
I get "Created list entry x" 1000 times as I should. Then the program just hangs.
while numscrollerB <= number:
if numscrollerB != 1 and numscroller != number and numlist[numscrollerB] == "true":
primestatus = "false"
else:
primestatus = "true"
You don't increase numscrollerB in this loop, so it runs infinitedly. Anyway, You should rather use 'for loop':
for numscrollerB in range(1, number+1):
pass # do something
Your code is very unpythonic. Typical of a newcomer experienced in a different style of coding.
Your list is uneccessary.
In python you could create the list like this
def check_even(val):
#this contains your logic
return val % 2 == 0
evenslist = [check_even(i) for i in xrange(1, 1001)]
print numlist

Categories

Resources