I don't understand why my function doesn't happen - python

I am trying to write a typing challenge game where the player has to type a word as fast as possible within the time limit. At the end of the game() function it is supposed to execute the round1() function when the timer gets to 0. However, nothing happens and it just stays on the number 1. Any ideas what is causing this behavior?
This is the code I am using:
import random
import time
global timer
timer = 20
global counting
counting = 10
global rounds
rounds = 0
def menu():
print ("Main Menu\nType in 'start' to begin the typing challenge")
start = input()
if start == "start":
game()
else:
menu()
def game():
global counting
choices = ["snazzy", "pizzas", "sizzle", "jackal"]
global word
word = (random.choice(choices))
print ("The word you must type is", word)
print ("You will be timed on how long it takes you to type the word.")
print ("Each round you will have a slightly smaller amount of time to type the word")
time.sleep(10)
print ("Starting in...")
for count in range(10):
print (counting)
time.sleep(1)
counting -=1
round1()
def round1():
useless = 100
global rounds
global word
global timer
while useless > 1:
for count in range(20):
time.sleep(1)
timer -=1
print ("Type", word)
attempt = input()
if attempt == word and timer > 0:
rounds = rounds+1
round2()
else:
lose()

You are getting into the function round1, but once you are there, you are caught in an infinite loop because the variable useless will never change.
Even if you take out the while loop, you will never be able to win because you do not take input in until after the timer has already run out.

Try this code from round 1 on:
def round1():
import sys, select
global rounds
global word
global timer
print ("Type", word)
input, out, error = select.select( [sys.stdin], [], [], timer)
if (input):
attempt = sys.stdin.readline().strip()
if attempt == word:
rounds = rounds+1
round2()
else:
lose()
else:
lose()
if __name__ == '__main__':
menu()
Note that, as-is, it will fail with a NameError since you don't have a round2() function defined. A better solution would be to generalize your function, with something like round_x(number, word, time_to_answer); That way you can reuse the same code and don't have to import globals.

I was playing a bit with your game you're doing too many overhead and mistakes
there so I just changed it's structure to simplify:
import random
import time
current_milli_time = lambda:int(time.time() * 1000)
timer = 20 #suppose user has 20 secs to enter a word
counting = 10
requested_word = ""
choices = ["snazzy", "pizzas", "sizzle", "jackal"]
rounds = 0
def menu():
print ("Main Menu\nType in 'start' to begin the typing challenge")
game() if input().lower() == "start" else menu()
#There is no need to split game and round but I didn't want to mess with
#your program structure too much
def game():
global requested_word
try:
requested_word = (random.choice(choices))
choices.remove(requested_word)
except IndexError:
print "Game is finished"
return
print ("The word you must type is", requested_word)
print ("You will be timed on how long it takes you to type the word.")
print ("Each round you will have a slightly smaller amount of time to type the word")
print ("Starting typing in in...")
for count in range(10,-1,-1):
print (count)
time.sleep(1)
round()
def round():
global timer
start = current_milli_time()
word = input("Enter word -> ")
stop = current_milli_time()
time_delta = stop-start #this is in milliseconds
if time_delta< timer*1000 and word == requested_word :
timer = timer-5 #lower the time to enter a word
game()
else:
print("Game OVER")
menu()
When prompt 'Enter word ->' appears the user has all the time he wants to enter a word, but after it time_delta is calculated and if it passes your limit, it's game over for him.

Related

if statements with while loops

I want to make it that after 10 sec you get and random letter of an random word and that the timer starts again like an infinite loop. Here is my code:
words = ["graveyard","church","apple","tree","crispy","air"]
hidden_word = random.choice(words)
hint = random.sample(hidden_word,1)
timer = 0
if timer == 10:
print(hint)
else:
while timer < 10:
timer = timer + 1
time.sleep(1)
print(timer)
I tried to place the if statement in the while loop but didn't work it only gave me errors
This will do what you described, but it will never stop:
import time
import random
words = ["graveyard","church","apple","tree","crispy","air"]
hidden_word = random.choice(words)
hint = random.sample(hidden_word,1)
def random_select():
while True:
time.sleep(10)
print(hint)
random_select()

How would I write a program that can call a variable from another def?

So I set out to make a simple game of hangman and everything worked fine, the whole code worked but it lacked the ability to allow the user to replay when the game is over. Thus I set out to put all the code I have written in various functions. So that I can call the functions when they are required (I thought it was the most logical way to allow replay-ability). Various problems followed but one stood out.
The main culprit (I think) is that I could not successfully get a value to update globally. I've read similar questions on the site but could not successfully adapt it to my case. I have a sample code to show what exactly I mean:
def GameMode():
choice = input('Play alone or play with friends? A F : ')
choice = choice.upper()
if choice == 'A':
wordslotmachine = ['stand','emerald','splash']
word = random.choice(wordslotmachine)
word = word.upper()
Rules()
elif choice == 'F':
word = input('Enter your word for your friends to guess: ')
word = word.upper()
Rules()
else:
choice = input('Please enter A or F: ')
choice = choice.upper()
I would need the program to remember what the value of "word" is and use this word in another method (this method is ran by another method showed below "Rules()"):
def MainGame():
guesses = ''
turns = 10
underscore = 0
seconds = 1
checker = 0
cheaterchance = 5
while turns > 0: #check if the turns are more than zero
for char in word: # for every character in secret_word
if char in guesses: # see if the character is in the players guess
print(char+' ', end='')
else:
print('_ ', end='')# if not found, print a dash
underscore += 1
if underscore == 0:
print(': You got it!')
Wait()
NewGame()
break
#A block of if's to check for cheating
if guess not in word:
print('Your guesses so far: '+guesses)
turns -= 1
if turns == 0:
break
else:
print('')
print('Try again. You have',turns,'more guesses')
print('Delayed chance to answer by',seconds,'seconds')
counter = 1
print(0,'.. ', end='')
while counter < seconds:
time.sleep(1)
print(counter,'.. ', end='')
counter += 1
if counter == seconds:
time.sleep(1)
print(counter,'.. done!', end='')
print('')
print('')
seconds += 1
underscore = 0
else:
print('Your guesses so far: '+guesses)
underscore = 0
#The else portion of the code to check for cheating
I have tried defining "word" outside of the function. Doing this doesn't fix the problem, GameMode() will not successfully update the value of "word". And whatever the value of "word" defined outside of the function will be called and used by MainGame(). However doing this shows another problem.
That being, the code that previously worked (it successfully read the input and correctly updated the game status) now does not work. Even if the correct letter is entered by the user, the program reads the input as incorrect.
These are the two problems I have faced so far and have yet to find a way to overcome them.
Note: I have successfully created a way to make the game replay-able by putting the entire original code (without the functions) inside a while loop. However I would still very much like to know how I can get the code to work using functions.
Edit: This is the function for Rules():
def Rules():
#Bunch of prints to explain the rules
MainGame()
print('Start guessing...')
Wait() is just a delay function with a countdown.
Global vs. Local variables.
You can reference and use a global variable from within a function, but you cannot change it.
It's bad practice, but you CAN declare a variable within your function to be global and then changes to it inside your function will apply to the variable of the same name globally.
HOWEVER, what I suggest is to return the word at the end of your function.
def whatever_function(thisword):
do some stuff
return word
new_word = whatever_function(thisword)
Functions can, and usually should, return values. Make GameMode() return the word to the caller;
def GameMode():
choice = input('Play alone or play with friends? A F : ')
choice = choice.upper()
if choice == 'A':
wordslotmachine = ['stand','emerald','splash']
word = random.choice(wordslotmachine)
word = word.upper()
Rules() #ignore this
elif choice == 'F':
word = input('Enter your word for your friends to guess: ')
word = word.upper()
Rules() #ignore this
else:
choice = input('Please enter A or F: ')
choice = choice.upper()
return word
From the main call GameMode and save the word;
def MainGame():
guesses = ''
turns = 10
underscore = 0
seconds = 1
checker = 0
cheaterchance = 5
word = GameMode() # add this here
You almost certainly want to use a class with instance variables
Contrived example:
class Hangman:
def __init__(self):
print("Starting hangman")
def mode(self):
# ...
self.word = 'whatever'
def play(self):
print("Look i have access to word", self.word)
if __name__ == '__main__':
hm = Hangman()
hm.mode()
hm.play() # may be what you want to put in a while loop
To access a global variable from inside a function, you have to tell python that it is global:
my_global_var = 1
def some_func():
global my_global_var
You have to use global keyword in every method that the global variable is being used or python will think you are defining/ using a local variable
Having said that, you should avoid globals as a coding practise.
global word #probably define this after imports.
def GameMode():
global word #add this
choice = input('Play alone or play with friends? A F : ')
choice = choice.upper()
if choice == 'A':
wordslotmachine = ['stand','emerald','splash']
word = random.choice(wordslotmachine)
word = word.upper()
Rules() #ignore this
elif choice == 'F':
word = input('Enter your word for your friends to guess: ')
word = word.upper()
Rules() #ignore this
else:
choice = input('Please enter A or F: ')
choice = choice.upper()
def MainGame():
guesses = ''
turns = 10
underscore = 0
seconds = 1
checker = 0
cheaterchance = 5
global word # add this here
use the code
global word
above the def or let the def return the value of word so it is stored in a variable outside the def

How do I run one def function inside of a different def function in python?

I'm trying to run a timer inside of a function of my code. I need to start the timer slightly before the user starts typing, then stop the timer when the user has entered the alphabet correctly.
Here is my code:
import time
timec = 0
timer = False
print("Type the alphabet as fast as possible.\nYou MUST be accurate!\nYou will be timed")
timer = True
attempt = input("The timer has started!\nType here: ")
while timer == True:
time.sleep(1)
timec = timec +1
if attempt == "abcdefghijklmnopqrstuvwxyz":
timer = False
print("you completed the alphabet correctly in", timec,"seconds!")
else:
print("There was a mistake! \nTry again: ")
The issue is that it will not let me enter the alphabet. In previous attempts of this code (Which I do not have) i have been able to enter the alphabet, but the timer would not work. Any help is appreciated
import time
start = time.time()
attempt = input("Start typing now: ")
finish = time.time()
if attempt == "abcdefghijklmnopqrstuvwxyz":
print "Well done, that took you %s seconds.", round(finish-start, 4)
else:
print "Sorry, there where errors."
Think carefuly about that you are dong
You ask for a user-entered string
While timer equals True, you sleep for one second and increase the count. In this loop, you do not change the timer.
Obviously, once user stopped entering the alphabet and pressed enter, you start an infinite loop. Thus, nothing seems to happen.
As other answers suggested, the best solution would be to save the time right before prompting user to enter the alphabet and compare it to the time after he finished.
you could do something like:
import datetime
alphabet = 'abcdefghijklmnopqrstuvwxyz'
print('Type the alphabet as fast as possible.\nYou MUST be accurate!\nYou will be timed"')
init_time = datetime.datetime.now()
success_time = None
while True:
user_input = input('The timer has started!\nType here: ')
if user_input == alphabet:
success_time = datetime.datetime.now() - init_time
break
else:
continue
print('you did it in %s' % success_time)

Doing a sort of a loop while avoiding a certain prerequisite (beginner/python)

A beginner's problem, here it goes:
I'm writing a program which keeps records of a game of darts. The user types in the players and their respective scores. It's possible to do a query about a player's scores and ask the program for the best overall score between all the players. I have the following functions:
add_score
return_players_score
return_best_score
exit_program
main
In main(), we begin by creating a new empty dictionary (say, players = {}). Then we ask the user to input a number that takes him/her to the function of choice (1: add_score etc.).
Now, once we're in add_score and have added a key:value pair (player:score), we need to go back to inputting the number taking to the function of choice. I implemented it simply by writing main() to the end of add_score.
That, however, takes us to the beginning, where there's players = {} and thus whatever data we input in add_score gets wiped out. This then affects other functions and the program remains useless as long as it forgets everything right away. How to solve this?
I'd paste the actual code but it's not in English and it's an assignment anyway...
Thanks.
Rather than calling main() from each of your other functions, you should just return (or run off the end of the function, which is equivalent to return None). Since you need the main function to run things repeatedly, you should use a loop.
def main():
players = {}
while True: # loop forever (until a break)
choice = input("what do you want to do (1-4)")
if choice == "1":
add_score(players)
elif choice == "2":
return_players_score(players)
#...
elif choice == "4":
break # break out of the loop to quit
else:
print("I didn't understand that.")
If you have a loop that does something like the following..
example:
while True:
players = {}
some code adding to players
This loop will always reset players to {}
However, if you do:
players = {}
while something:
some code adding to players
then players is not being reset at the start of each iteration through the loop
But your question is not clear
If you have something like this:
def add_score(dicccionary):
#do something with diccionary
main()
def main():
dicccionary = {}
while something:
option = input("option")
if option == 1:
addscore(dicccionary)
else:
#otherfunction
main()
your reset problem can be solve like:
dicccionary = {} #global variable
def add_score():
#do something with diccionary
main()
def main():
option = input("option")
if option == 1:
addscore()
else:
#otherfunction
main()
By the way, you shouldn't make it this way, try something as:
dicccionary = {} #global variable
def add_score():
#do something with diccionary
def main():
while somecondition:
option = input("option")
if option == 1:
addscore()
else:
#otherfunction
main()
If I was doing it for real then I would go for something like:
import sys
class ScoreKeeper(object):
def init(self):
self.scores = {}
def add_score(self, player, score):
self.scores[player] = score
def _print_player_score(self, player, score):
print 'player:', player, 'score:', score
def print_scores(self):
for player, score in self.scores.items():
self._print_player_score(player, score)
def best_score(self):
best, player = 0, "no player"
for player, score in self.scores.items():
if score > best:
best, player = score, player
self._print_player_score(player, best)
if __name__ == '__main__':
scorer = ScoreKeeper()
quit = lambda: sys.exit()
choices = quit, scorer.add_score, scorer.print_scores, scorer.best_score
def help():
print 'Enter choice:'
for index, c in enumerate(choices):
print '%d) %s' % (index, c.__name__)
def get_integer(prompt):
res = raw_input(prompt)
try:
return int(res)
except:
print 'an integer is required'
return get_integer(prompt)
def get_choice():
choice = get_integer('choice? ')
if not 0 <= choice < len(choices):
help()
return get_input()
return choice
help()
choice = get_choice()
while(choice):
args = []
if choices[choice] == scorer.add_score:
args.append(raw_input('player name? '))
args.append(get_integer('score? '))
choices[choice](*args)
choice = get_choice()
quit()

How do I have numbers increment slowly over a course of time throughout runtime

I am trying to make a text based game in which the user is a pilot in space. I want to create a movement system but am unsure how to do it. I want the user to be able to put in the desired grid coordinates, and his vehicle will begin to change its grid coords to get closer and closer to the ones he inputted.
Now, to do this I will probably need multithreading and a time element. But I am unsure how I can use a time element. Any advice is greatly appreciate, i'm just trying to learn here. Thanks guys!
from Gundam2 import Mobilesuits
#Main Variable/Object declarations:
Leo1=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,100,100])
Leo2=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[300,100,100])
Leo3=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,150,100])
currentmobilesuit=Leo1
#Main Function declarations
def commands(user_input,currentmobilesuit):
if user_input == "radar":
currentmobilesuit.radar()
elif user_input == "commands":
print("Command list:\nradar")
else:
print("Invalid command\nType 'commands' for a list of valid commands")
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
class Mobilesuits:
#class global variables/methods here
instances = [] #grid cords here
def __init__(self,armor,speed,name,description,cockpit_description,\
radar_range, coordinates):
Mobilesuits.instances.append(self)
self.armor=armor
self.speed=speed
self.name=name
self.description=description
self.cockpit_description=cockpit_description
self.radar_range=radar_range
self.coordinates=coordinates
def can_detect(self, other):
for own_coord, other_coord in zip(self.coordinates, other.coordinates):
if abs(own_coord - other_coord) > self.radar_range:
return False
return True
def radar(self):
for other in Mobilesuits.instances:
if other is not self and self.can_detect(other):
print "%s detected at %s" % (other.description, other.coordinates)
Games typically have a "master loop" of some kind; yours does here:
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
The simplest thing to do is to count in the loop:
#Main execution
turn_count = 0
while True:
commands(raw_input(),currentmobilesuit)
turn_count += 1
If you wanted the real time taken to have some impact on the counter, or be the counter, you can get the current time from the time module calling time.time().
#Main execution
import time
time_start = time.time()
time_elapsed = 0
while True:
commands(raw_input(),currentmobilesuit)
time_elapsed = time.time() - time_start
A couple other thoughts:
Make a Game class, and put the turn counter and game loop in that.
Have the commands function return a number that is the number of time units that took place during the command; for example, entering an invalid command might take 0 turns, while repairing a robot might take 5.
#Main execution
turn_count = 0
while True:
turns_taken = commands(raw_input(),currentmobilesuit)
turn_count += turns_taken
You can use non-blocking I/O. This will help you avoid the complications of threading. Here's your sample code implemented with a non-blocking read of stdin:
#!/usr/bin/python
import sys
import select
call_count = 0
#Main Function declarations
def commands(user_input):
global call_count
if len(user_input) > 0:
print('call count: ' + str(call_count) + ' user entered: ' + user_input)
def raw_input_no_block():
global call_count
call_count = call_count + 1
input_avail = select.select([sys.stdin], [], [], 0.1)[0] #wait for 0.1 seconds
if input_avail:
return sys.stdin.readline()
else:
return ''
#Main execution
while True:
commands(raw_input_no_block())

Categories

Resources