Odd behavior when counting down the second time - python

The first time playing the game, the timer works, the second time playing the game, the timer counts by two?
def main():
win1 = Tk()
win1x = 750
win1y = 720
gui1 = MakeGUI(win1,win1x,win1y,"light blue")
def countdown1(remaining,win):
if gui1.gameTimer > 0:
gui1.gameTimer-= 1
win1.after(1000,countdown1,remaining,win1)
else:
pass
while (gui1.quitGame == False):
while gui1.startGame == True:
# start the timer
countdown1(gui1.gameTimer,win1)
# start a loop until time up
while(gui1.gameTimer > 0):
gui1.drawGUI()
gui1.cleanupGUI()
gui1.initializeGUI()
main()

Found the issue in one of the class files. Good to go.

Related

Threads not being accessed by pylance, and any way to stop a thread? Python

My code
import time
answer = None
def check():
#Global Variable Definitions
global outOfTime
global answer
#Variable Fixup
outOfTime = 2
timevalue = 0
#Set Time Dependant On Level
if difficulty == "EASY":
timevalue = 300 / level
elif difficulty == "MEDIUM":
timevalue = 150 / level
elif difficulty == "HARD":
timevalue = 5 / level
else:
print("ERROR!")
time.sleep(2) #Incase Of No Difficulty
quizStartup()
print("You Have", round(timevalue), "Seconds")
time.sleep(timevalue) #Timer
if answer == None:
outOfTime = 1
from threading import Thread
t = Thread(target = check).start
answer = input("Answer: ")
When I run this code, its being working forever but now the thread is not accessed by pylance. Any ideas on how to fix this?
Also is there anyway to stop this thread later on?
.start is not a property, you need to call it like a function, t = Thread(target=).start()
to stop a thread, the proper way is with flags

I am trying to execute an alarm function in tkinter but it is not working properly

I am trying to Execute the function in tkinter as I want function to run in background I have done following code. Also I am trying to execute it inside a while loop but its not looping through.
t1 = dt.time(hour = 13, minute= 24)
t2 = dt.time(hour= 13, minute= 4)
timetable = [t1, t2]
root = Tk()
def Alarm():
current_time = now_time.strftime("%H:%M:%S")
print(current_time)
print(timetable[0])
while True:
if timetable[0] <= dt.datetime.now().time():
print("Its time")
break
Alarm()
root.mainloop()
print statements are only for testing. The logic I am using in alarm clock is also not executing properly as it tells ""Its time" even after time has passed. I have tried following methods before.
method 1:
for i in reversed(timetable):
i_time = i
#print (i_time)
#print(now_time.strftime("%H:%M"))
while True:
if dt.datetime.now().time() < i_time:
#if i_time <= dt.datetime.now().time():
print("Its Time")
break
method 2:
for i in timetable:
current_time = dt.datetime.now().time()
alarm_time = i
while True:
if current_time < alarm_time:
if current_time <= alarm_time:
print("its time", alarm_time)
Using for loop was my first goal but for loop isn't executing properly. It only gets 1st element and doesn't go to 2nd element even if first element has passed so I have decided to go with if,elif,else statement
You can use the after method to run a function after a certain amount of time has elapsed. You should use it rather than creating a loop.
You simply need to convert the alarm time to a number of milliseconds, then use that to ring the alarm at the given time. For example, to ring an alarm in one hour you would do this:
def ring_alarm():
print("Its time")
delay = 60 * 60 * 1000 # 60 min/hour, 60 secs/min, 1000ms/sec
root.after(delay, ring_alarm)
I am going with if..else response for executing alarm as
current_time = dt.datetime.now().time()
if timetable[0] == current_time:
print("Its time")
break
I was breaking While loop in wrong place as well an typo from my end.

How to implement a timed background function?

A straightforward application of:
Prompt for user input.
Start countdown (or count up) timer.
Wait on user input (as timer counts down/up).
If user inputs a correct response, conditional statement 1
Else, conditional statement 2
If user exceeds a preset time, timer expires and user is directed accordingly.
I've tried some of the solutions offered on this web site. However, in all cases, the count up/down timer seems to stop once the user input prompt is generated. In other words, the timer does not seem to run as a separate (background) thread.
import threading
import time
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
self.count = 10
def run(self):
while self.count > 0 and not self.event.is_set():
print (self.count)
int_answer = (int(input('Enter your age: '), base = 10)
str_answer = str(int_answer)
while str_answer == '':
self.count -= 1
self.event.wait(10)
if (int_answer > 50) :
<do something>
else:
<do somethingelse>
def stop(self):
self.event.set()
tmr = TimerClass()
tmr.start()
time.sleep(1)
tmr.stop()
The program should go to condition 1 if a response of > 50 is provided; else, go to condition 2 if a response of <= 50 is entered. The timer should expire after a period of 10 secs. if the user has not provided a response (with user notification).
I've adapted the code from this answer to your needs:
import threading
import queue
import time
def read_kbd_input(inputQueue):
print('Ready for keyboard input:')
while (True):
input_str = input()
inputQueue.put(input_str)
def main():
inputQueue = queue.Queue()
inputThread = threading.Thread(target=read_kbd_input, args=(inputQueue,), daemon=True)
inputThread.start()
start_time = time.time()
while True:
if (inputQueue.qsize() > 0):
input_str = inputQueue.get()
# Insert your code here to do whatever you want with the input_str.
print("input_str = {}".format(input_str))
break
time.sleep(0.1) # poll each 100ms
if time.time() - start_time > 2: # timeout after 2 sec
break
print("End.")
if (__name__ == '__main__'):
main()

math quiz with a time limit (simultaneous functions) - advanced python

So I would like to run two programs, a timer and a math question. But always the input seems to be stopping the timer funtion or not even run at all. Is there any ways for it to get around that?
I'll keep the example simple.
import time
start_time = time.time()
timer=0
correct = answer
answer = input("9 + 9 = ")
#technically a math question here
#so here until i enter the input prevents computer reading the code
while True:
timer = time.time() - start_time
if timer > 3:
#3 seconds is the limit
print('Wrong!')
quit()
So recap i would like the player to answer the question in less than 3 seconds.
after the 3 seconds the game will print wrong and exit
if the player answer within three seconds the timer would be 'terminated' or stopped before it triggers 'wrong' and quit
hope you understand, and really appreciate your help
On Windows you can use the msvcrt module's kbhit and getch functions (I modernized this code example a little bit):
import sys
import time
import msvcrt
def read_input(caption, timeout=5):
start_time = time.time()
print(caption)
inpt = ''
while True:
if msvcrt.kbhit(): # Check if a key press is waiting.
# Check which key was pressed and turn it into a unicode string.
char = msvcrt.getche().decode(encoding='utf-8')
# If enter was pressed, return the inpt.
if char in ('\n', '\r'): # enter key
return inpt
# If another key was pressed, concatenate with previous chars.
elif char >= ' ': # Keys greater or equal to space key.
inpt += char
# If time is up, return the inpt.
if time.time()-start_time > timeout:
print('\nTime is up.')
return inpt
# and some examples of usage
ans = read_input('Please type a name', timeout=4)
print('The name is {}'.format(ans))
ans = read_input('Please enter a number', timeout=3)
print('The number is {}'.format(ans))
I'm not sure what exactly you have to do on other operating systems (research termios, tty, select).
Another possibility would be the curses module which has a getch function as well and you can set it to nodelay(1) (non-blocking), but for Windows you first have to download curses from Christopher Gohlke's website.
import time
import curses
def main(stdscr):
curses.noecho() # Now curses doesn't display the pressed key anymore.
stdscr.nodelay(1) # Makes the `getch` method non-blocking.
stdscr.scrollok(True) # When bottom of screen is reached scroll the window.
# We use `addstr` instead of `print`.
stdscr.addstr('Press "q" to exit...\n')
# Tuples of question and answer.
question_list = [('4 + 5 = ', '9'), ('7 - 4 = ', '3')]
question_index = 0
# Unpack the first question-answer tuple.
question, correct_answer = question_list[question_index]
stdscr.addstr(question) # Display the question.
answer = '' # Here we store the current answer of the user.
# A set of numbers to check if the user has entered a number.
# We have to convert the number strings to ordinals, because
# that's what `getch` returns.
numbers = {ord(str(n)) for n in range(10)}
start_time = time.time() # Start the timer.
while True:
timer = time.time() - start_time
inpt = stdscr.getch() # Here we get the pressed key.
if inpt == ord('q'): # 'q' quits the game.
break
if inpt in numbers:
answer += chr(inpt)
stdscr.addstr(chr(inpt), curses.A_BOLD)
if inpt in (ord('\n'), ord('\r')): # Enter pressed.
if answer == correct_answer:
stdscr.addstr('\nCorrect\n', curses.A_BOLD)
else:
stdscr.addstr('\nWrong\n', curses.A_BOLD)
if timer > 3:
stdscr.addstr('\nToo late. Next question.\n')
if timer > 3 or inpt in (ord('\n'), ord('\r')):
# Time is up or enter was pressed; reset and show next question.
answer = ''
start_time = time.time() # Reset the timer.
question_index += 1
# Keep question index in the correct range.
question_index %= len(question_list)
question, correct_answer = question_list[question_index]
stdscr.addstr(question)
# We use wrapper to start the program.
# It handles exceptions and resets the terminal after the game.
curses.wrapper(main)
Use time.time(), it returns the epoch time (that is, the number of seconds since January 1, 1970 UNIX Time). You can compare it to a start time to get the number of seconds:
start = time.time()
while time.time() - start < 60:
# stuff
You can have a timer pull you out of your code at any point (even if the user is inputting info) with signals but it is a little more complicated. One way is to use the signal library:
import signal
def timeout_handler(signal, frame):
raise Exception('Time is up!')
signal.signal(signal.SIGALRM, timeout_handler)
This defines a function that raises an exception and is called when the timeout occurs. Now you can put your while loop in a try catch block and set the timer:
signal.alarm.timeout(60)
try:
while lives > 0
# stuff
except:
# print score

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