Simple Validation Lead to a Infinite While Loop - python

I'm currently making a scoring system for an event and I'm having trouble using while loops as way to validate user input. For example I want to force the user enter their name so it can be added to a spot for a sport like tennis which I used a dictionary for. Everytime I am done asking them for their user input the while loop keeps apearing leading to a never ending while loop. Here's what I've done.
```solo_player = {
"Contestant 1":{"Player 1":[],"Score":[],"Event":[]},
"Contestant 2":{"Player 2 ":[],"Score":[],"Event":[]},
"Contestant 3":{"Player 3":[],"Score":[],"Event":[]},
"Contestant 4":{"Player 4":[],"Score":[],"Event":[]}}
def individual():
solo_name = False
while not solo_name:
solo_name = input("What is your name:")
print(""" \nIndividual Menu and Available Spots\n
1) Player 1
2) Player 2
3) Player 3
\n4) Go back to Main Menu\n""")
solo_menu = ["1","2","3","4"] #valid choices for this menu
solo_menu = False
while not solo_menu:
solo_menu = input("Please enter your choice here:")
if solo_menu == "1":
solo_player["Contestant 1"]["Player 1"].append(solo_name)
print(solo_player["Contestant 1"])
print("Thank you for taking the spot of Player 1")
solo_menu = True
elif solo_menu == "2":
solo_player["Contestant 2"]["Player 2"].append(solo_name)
print(solo_player["Contestant 2"])
print("Thank you for taking the spot of Player 2")
solo_menu = True
else:
print("Enter a value between 1-4)
solo_menu = False```
My ideal output would be that the while loop will stop after I picked one spot from the available spots. Sorry for the long if/else statements I'm quite new to it so I don't know how to make it shorter
EDIT: I fixed the issue. It was caused by calling the individual func outside my menu def.

Here's what I believe you are after.
A couple of changes:
Your while loops can contain the validation that you are wanting to perform as their condition. If your validation becomes more complex then you can consider moving back to a boolean to break the while loop, but it feels overly complex for your requirements.
Removal of the if statements. The whole idea of a dictionary is that you can specific a key and get a value, so having an elif for every potential key is overly cumbersome. Just concatenate the validated user input to derive the key.
solo_player = {
"Contestant 1":{"Player 1":[],"Score":[],"Event":[]},
"Contestant 2":{"Player 2":[],"Score":[],"Event":[]},
"Contestant 3":{"Player 3":[],"Score":[],"Event":[]},
"Contestant 4":{"Player 4":[],"Score":[],"Event":[]},
"Contestant 5":{"Player 5":[],"Score":[],"Event":[]},
"Contestant 6":{"Player 6":[],"Score":[],"Event":[]},
"Contestant 7":{"Player 7":[],"Score":[],"Event":[]}}
solo_name=""
while solo_name == "":
solo_name = input("What is your name:")
print(""" \nIndividual Menu and Available Spots\n
1) Player 1
2) Player 2
3) Player 3
4) Player 4
5) Player 5
6) Player 6
7) Player 7
\8) Go back to Main Menu\n""")
#prompt for player slot
solo_menu_options = ["1","2","3","4","5","6","7","8"] #valid choices for this menu
solo_menu=""
while solo_menu not in solo_menu_options:
solo_menu = input("Please enter your choice here:")
solo_player["Contestant "+solo_menu]["Player "+solo_menu].append(solo_name)
print(solo_player["Contestant "+solo_menu])
print("Thank you for taking the spot of Player "+solo_menu)

Related

Accessing lists / data passing to class from list

I recently was trying to work on a twist to a program I am writing for my first program really. And I have everything working if the user is told to enter some values each time the game runs.
However, I was thinking that it should have a default set of characters that my program/game would use every time. My first goal was to get this to just give every player the same default 3 characters. But eventually this would need to have a have a list expanded of at least the character names.
My trouble comes in that I have taken a if loop that gathered the data each time if they said they have new characters to create, and have tried to modify it to the best of my knowledge to use a list and have it use the position in the loop to get that list number.
Then pass that data down the same paths I had created in the class. But it seems to be just skipping this section which right now I cant see why(I am sure this is a inexperienced moment) Or I am trying to access the list incorrectly? Anyway help on this would be huge, I have included my code below.
I have added commented lines to indicate the section of code that appears to be skipping.
And clarification I hope on this question is Is the for in loop the right way to solve this issue? And if so am I accessing this the correct way?
print ("Welcome to Chose your own adventure python edition")
print ("")
players = []
playerCharacters = []
def playerNames():
playerNum = int(input("How many players are playing? "))
if playerNum > 4:
print("I am sorry, unfortunately only four players are permitted.")
return
for playerId in range(playerNum):
newPlayerName = input(f"What is player {playerId + 1}'s name?")
players.append(newPlayerName)
print(f"Welcome: {' & '.join(players)}!")
def characters():
charAmount = 3
for index, player in enumerate(players):
playerCreate = input("{} (player {}), do you have a character to create. (y/n)".format(
player, str(index+1)))
if playerCreate.lower() =="y":
charAmount = int(input("How many characters does this player begin the game with?"))
for x in range(0,(charAmount)):
getCharName = input("Enter Next Char name ")
getCharDice = input("Please enter the number of dice this char will use. ")
getCharRole = input("Please enter the villagers role. ")
charData = {
"name": getCharName,
"diceCount": getCharDice,
"role": getCharRole,
"playerName": player
}
newCharacter = Character(characterData=charData)
newCharacter.printSummary()
playerCharacters.append(newCharacter)
if playerCreate.lower() == "n":
defaultCapture = input("Would you like to begin with the default charatures. (y/n)?" )
if defaultCapture.lower() == "y":
###Beginning of skipped code
for x in range (0,3):
DefaultCharName = ["Bob", "Sally", "Tommy"]
DefaultDiceCount = 1
DefaultRole = ['Builder', "Recruiter" , "Nothing"]
charData = {
"name": DefaultCharName(x),
"diceCount": DefaultDiceCount,
"role": DefaultRole(x),
"playerName": player
}
DefaultCharacters = Character(characterData=charData)
DefaultCharacters.printSummary()
playerCharacters.append(DefaultCharacters)
###End of skipped section
if defaultCapture.lower == "n":
print("Well it looks as though you dont really want to play.")
continue
print("Summary ==========================")
for player in playerCharacters:
print("{characterName} Controlled by {playerName}".format(
playerName=player.playerName,
characterName=player.name ))
return
class Character:
name = "default name"
playerName = "john/jane doe"
diceCount = "1"
role = "vanillaPaste"
def __init__(self, characterData):
self.playerName = characterData['playerName']
self.role = characterData['role']
self.diceCount = characterData['diceCount']
self.name = characterData['name']
def printSummary(self):
print("{player} summary: \r\n \r\nCharacters:\r\nName: {characterName} \r\nDice: {dice} \r\nRole: {role} \r\n"
.format(
characterName=self.name,
player=self.playerName,
dice=self.diceCount,
role=self.role
);
playerNames()
characters()
While your code is, like the comments say, a little too long for a minimal SO question, in this case it's an easy fix.
Just before your "start of skipped section", you have
if defaultCapture.lower == "y":
which is missing the parentheses to actually call .lower(), to lower-case the string. (Comparing a function to a string would always be false.)
That expression should be
if defaultCapture.lower() == "y":
try to check the indentation of the for loop and when you enter something, do not have spaces. You should use
defaultCapture.lower().split =="y"
OR
defaultCapture.lower().split.contains("y")// Add the brackets()

Python Main Loop + Sub Loop with timeout

I would like to achieve the following.
I have a proof of concept I am working.
I have Individual "Named RFID"Cards, then I have "Action RFID Cards".
So I might have cards like this:
Names
John - 12345
Mary - 12346
Actions
Start Work - 111
Finish Work - 222
Lunch - 333
So John Swipes his own card, then swipes an action card, which logs his action.
-Start Script
-Wait for User Card Input
-Once Input Received and Validated
- Wait for Action Card Input
- Start Timer
- Wait until Action Card Input matches a valid Action
- If a match, exit back to the main loop
- If no match, wait for one minute, then exit
-Continue Main Loop
I am reusing code from :
How would I stop a while loop after n amount of time?
import time
timeout = time.time() + 60*5 # 5 minutes from now
while True:
test = 0
if test == 5 or time.time() > timeout:
break
test = test - 1
and a Python Game example which waits and loops forever playing the game
https://dbader.org/blog/python-intro-reacting-to-user-input
My code for testing is as follows (I am not doing a card or action lookup at this point, expecting the user to be 12345 and card to be 54321: (the requirement for four spaces for indent has possibly broken Python Indent)
#
# Guess My Number
#
import random
import time
# Set our game ending flag to False
game_running = True
while game_running:
# Greet the user to our game
print()
print("I'm thinking of a number between 1 and 10, can you guess it?")
# Have the program pick a random number between 1 and 10
#secret_number = random.randint(0, 10)
secret_number = 12345
card_number_list = 54321
# Set the player's guess number to something outside the range
guess_number = -1
# Loop until the player guesses our number
while guess_number != secret_number:
# Get the player's guess from the player
print()
guess = input("Please enter a number: ")
# Does the user want to quit playing?
if guess == "quit":
game_running = False
break
# Otherwise, nope, the player wants to keep going
else:
# Convert the players guess from a string to an integer
guess_number = int(guess)
# Did the player guess the program's number?
if guess_number == secret_number:
print()
print("Hi you have logged on, please swipe Card- if you don't Swipe - will timeout in 1 minute!")
timeout = time.time() + 60*1 # 1 minutes from now
while True:
test = 0
if test == 1 or time.time() > timeout:
card = input("Please enter your card number")
card_number = int(card)
if card_number == card_number_list:
print("Thanks for your card number")
test = 1
break
test = test - 1
# Otherwise, whoops, nope, go around again
else:
print()
print("You need to use your wrist band first...")
# Say goodbye to the player
print()
print("Thanks for playing!")
But instead of exiting, the script waits...
Any feedback appreciated - I have basic python skills and am trying to reuse existing code where possible (with thanks to the creators!).
The python input() function will always wait for response from the keyboard before returning. Take a look at this answer for a technique to accomplish what you want.

My display menu repeats multiple times when an input is entered

I'm practice classes and inheritance in a program idea that I came up with myself. Basically Im making an arcade game menu simulator that can play two modes, single player and multiplayer. Every time I enter a choice, either 1 or 2, the menu displays a couple times and then it proceeds to accept the input, I only want the menu to be displayed once. Heres my code:
# Suppose you are at an arcade and you and your friend want to play a multiplayer game that requires UI.
# Make the game ask for the users name and age to see if they can play, make the program so that it can add a friend.
# If any of the players are under the age of 18, they are not allowed to play, otherwise proceed.
# **EXTRA CREDIT** --> Add a functionality which adds the players to a list until the list reaches 4 players, then stop adding to the list.
# arcade_game.py
import sys
# give the user a greeting
import self as self
lst = []
class menu:
def __init__(self, ready):
self.ready = ready
#display menu
#classmethod
def display_menu(self):
print("Pick from one of the choices below, type in the corressponding number")
print("1. single player \n"
"2. Multiplayer")
choice = int(input("Enter your choice here: "))
return choice
# ready or not function to see if the user is ready to play
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
# add players class
class player(menu):
# add a default player to __init__(), **(since there has to be at least one player)**
def __init__(self, ready, player1):
super().__init__(ready)
self.player1 = player1
# single player method
def set_name(self):
self.player1 = input("Enter your name for single player mode")
print("Lets play! ", self.player1)
# multiplayer method
def set_names(self):
try:
self.player1 = input("Enter your name to begin")
lst.append(self.player1)
# add another player to continue
while len(lst) <= 4:
add = input("Add player here: ")
lst.append(add)
if len(lst) == 4:
print("Player limit reached!")
break;
except ValueError:
print("You didnt enter valid input, please try again")
# get the names of the players only if 1 is picked from display_menu() above, including player1
def check_choice(self):
if self.display_menu() == 1:
self.set_name()
elif self.display_menu() == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
m = menu("yes")
m.ready_or_not()
p = player("yes", "test")
p.check_choice()
ready_or_not calls self.display_menu():
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
check_choice also calls self.display_menu() at least once, and twice if you type anything other than 1 the first time:
def check_choice(self):
if self.display_menu() == 1:
self.set_name()
elif self.display_menu() == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
Your top-level code calls ready_or_not() on one menu instance:
m = menu("yes")
m.ready_or_not()
… and check_choice() on another:
p = player("yes", "test")
p.check_choice()
So, your program displays the menu twice, and then a third time if you type anything but 1.
If you don't want the menu displayed two or three times, don't call the method two or three times.
If you want to display the menu only once and remember the choice, instead of displaying it two or three times, you need to use that self.ready attribute that you create in ready_or_not, instead of calling the method again.
However, that still isn't going to work as-is, because your class design is weird. You've made two separate instances, m and p, each of which has its own independent attributes. I'm not sure why player inherits from menu in the first place (or why display_menu is a #classmethod, or why it calls its parameter self rather than cls if it is one, and various other things), but, given that a player is a menu in your design, you probably just want a single player instance, like this:
p = player("yes", "test")
p.ready_or_not()
p.check_choice()
And then, you can change check_choice like this:
def check_choice(self):
if self.choice == 1:
self.set_name()
elif self.choice == 2:
self.set_names()
else:
print("Exiting....")
print("Goodbye!")
sys.exit(0)
Took me a while to figure out, but it seems like when you are done with display_menu() your calling ready_or_not() so you need to remove display_menu() from ready or not like this
# ready or not function to see if the user is ready to play
def ready_or_not(self):
# see if user types 1 or 2 with try & except
try:
# ask user if they are ready
self.ready = int(input("Are you ready to play? Type 1 for yes, 2 for no"))
# self.display_menu()
except ValueError:
print("You did not type 1 or 2, please try again!")
EDIT
looks like im late to the party

User prompt to Continue or Clear a time duration calculator

I am very inexperienced with any programming language. I decided for my first for-fun/leaning project to be creating a calculator to add different durations of time (ex. add the length of several songs to find how long an album is).
So far the user input method is pretty basic, and I'll work to fix that once the basics work, so bear with me on that. The calculator is currently capable of adding two times together and printing the correct answer.
My main problem is creating a functional Continue/Clear user prompt. I have a loop asking if the user wants to continue, clear, or exit. User input works correctly, but I don't know how to actually "continue or clear".
My idea: Upon hitting continue, the previous total will become firstNumber, and the user will only be prompted for the second number (nextNumber) and will be given a new sum and receive the same continue/clear/exit prompt. If the user hits clear, it will start at the very beginning and the user will be prompted for a new firstNumber.
Any help is greatly appreciated.
Below is the code:
import datetime
# holds first entry
print("Enter the first number")
seconds_1 = int(input("Seconds: "))
minutes_1 = int(input("Minutes: "))
hours_1 = int(input("Hours: "))
# holds second entry
print("Enter another number")
seconds_2 = int(input("Seconds: "))
minutes_2 = int(input("Minutes: "))
hours_2 = int(input("Hours: "))
# calculation
duration_1 = datetime.timedelta(hours=hours_1, minutes=minutes_1, seconds=seconds_1)
duration_2 = datetime.timedelta(hours=hours_2, minutes=minutes_2, seconds=seconds_2)
total = duration_1 + duration_2
print(total)
# continue, clear, or exit
contClear = input("Continue: Y | Clear: N | Exit: X: ")
cont = False
while cont == False:
if contClear.upper() == "Y" or contClear.upper() == "YES":
print("Next")
cont = True
elif contClear.upper() == "N" or contClear.upper() == "NO":
print("Cleared")
cont = True
elif contClear.upper() =="X" or contClear.upper() == "EXIT":
print("Exiting")
cont = True
else:
print("Invalid Entry")
contClear = input("Continue: Y | Clear: N | Exit: X: ")
print("DONE")

python -- Crash when trying to deal with unexpected input

So, I'm just fooling around in python, and I have a little error. The script is supposed to ask for either a 1,2 or 3. My issue is that when the user puts in something other than 1,2 or 3, I get a crash. Like, if the user puts in 4, or ROTFLOLMFAO, it crashes.
EDIT: okay, switched it to int(input()). Still having issues
Here is the code
#IMPORTS
import time
#VARIABLES
current = 1
running = True
string = ""
next = 0
#FUNCTIONS
#MAIN GAME
print("THIS IS A GAME BY LIAM WALTERS. THE NAME OF THIS GAME IS BROTHER")
#while running == True:
if current == 1:
next = 0
time.sleep(0.5)
print("You wake up.")
time.sleep(0.5)
print("")
print("1) Go back to sleep")
print("2) Get out of bed")
print("3) Smash alarm clock")
while next == 0:
next = int(input())
if next == 1:
current = 2
elif next == 2:
current = 3
elif next == 3:
current = 4
else:
print("invalid input")
next = 0
Use raw_input() not input() the latter eval's the input as code.
Also maybe just build a ask function
def ask(question, choices):
print(question)
for k, v in choices.items():
print(str(k)+') '+str(v))
a = None
while a not in choices:
a = raw_input("Choose: ")
return a
untested though
since the input() gives you string value and next is an integer it may be the case that crash happened for you because of that conflict. Try next=int(input()) , i hope it will work for you :)

Categories

Resources