0

I try to make a simple game, give a sum random number and input to answer it, I try to limit the time for input, but I can stop the input processing when timeout.

score=0
from threading import Timer
while score<=3:
    import random
    a=random.randint(0,100)
    b=random.randint(0,100)
    sum=a+b
    d=str(sum)
    while True:
        print(a,"+",b,"=")
        timeout = 3
        t = Timer(timeout, print, ['Sorry, times up'])
        t.start()
        prompt = "you have %d s to input your answer\n" % timeout
        c = input(prompt)
        t.cancel()

          #i want to stop input c and make other code like 'do you want to play again'
        if c.isdigit():
            break
        else:
            print('invalid input')
        continue
    result=c
    if result==d:
        score=score+1
        print('your score',score)
    else:
        score=score-1
        print('your score',score)
else:
    print('you win')
kgf3JfUtW
  • 13,702
  • 10
  • 57
  • 80
  • Indentation is vital in Python. You need to properly format your code. The last two lines (the `else` statement) makes no sense. – kgf3JfUtW Oct 28 '17 at 06:55
  • 1
    @sam You can have an `else` clause at the end of a `while` or `for` loop. But I agree that the one at the end of this code doesn't make a lot of sense. – PM 2Ring Oct 28 '17 at 07:16
  • 1
    You're doing pretty well for someone who's totally new to programming. But maybe you should stick with simpler things until you've got more knowledge and experience. Using threads correctly is not really a beginner's topic. – PM 2Ring Oct 28 '17 at 07:19
  • @PM 2ring.Thank you, i've just found out that my problem need to use threads from my friend, and i have no idea this is such that big problem. I just want finish my very first simple project to have inspiration in keep learning coding. By the way can you explain to me why my last else is making no sense. I'm really appreciate your help – ikaruss Oct 28 '17 at 08:06
  • Getting input with a timeout is actually a tricky problem, and the solution depends on what OS you're running. The way to do it on Windows is quite different to how it can be done on Linux (and other Unix-like systems). – PM 2Ring Oct 28 '17 at 08:53
  • There's nothing technically wrong with that final `else`, but it's not necessary: you can just make the `print('you win')` independent of the `while` loop. An `else` clause at the end of a `while` or `for` loop is used when you have a `break` inside the loop but you need to do certain stuff if the loop completes without exiting via the `break`. You can put that stuff into the `else` at the end of the loop. There are several SO pages discussing this construct, [this answer](https://stackoverflow.com/a/37643358/4014959) is brief but clear. – PM 2Ring Oct 28 '17 at 09:05
  • oh! i got it. Thank you very much – ikaruss Oct 28 '17 at 10:08
  • @PM2Ring Wow, thank you so much for pointing this out. After using Python for 5 years, I haven't even learned the `else` statement! It's great to learn something new every day. – kgf3JfUtW Oct 28 '17 at 12:50
  • @ikaruss OP: apologies for the bluntness due to my lack of my knowledge of the `else` statement, and am happy PM2Ring was able to help! – kgf3JfUtW Oct 28 '17 at 12:53
  • @sam it's ok man. Thank you for your help though. Im totally noob at this field so any comment is my gain – ikaruss Oct 28 '17 at 14:07

2 Answers2

0

Similar question has been answered before here.

I have tested it before and the following codes work in my Ubuntu. I'm not sure if this works in Windows too.

import sys
from select import select

timeout = 5
print "What is your name?"

# Assignment to three different variables based on select() paramenters
#    rlist: wait until ready for reading
#    wlist: wait until ready for writing
#    xlist: wait for an "exceptional condition"
rlist, _, _ = select([sys.stdin], [], [], timeout)
if rlist:
    s = sys.stdin.readline()
    print "Your name is: %s" %(s)
else:
    print "Timeout!! Try again."

Hope this helps.

ajenie
  • 21
  • 3
  • Thank you. This works on my case too. Sorry i dont have reputation to up vote for you. – ikaruss Oct 28 '17 at 10:06
  • Glad to hear that it works for you. Don't worry about the upvote :-) – ajenie Oct 29 '17 at 08:45
  • #ajenie. Sorry but i have to bother you again. I use s.isdigit to test valid input. It seem work for normal input but with this code it dose not work. I have no idea why :(( – ikaruss Oct 30 '17 at 01:56
  • I tried `s.isdigit()` and it doesn't work either. If you check `type(s).__name__`, the result is always _str_. Maybe this is due to the nature of reading from keyboard. So, i would suggest to use regular expression to test it. For example, `if re.match("^\d+$", s)`. – ajenie Oct 30 '17 at 10:51
  • thank you ajenie, i solve it with try int(s). and it work. I think it not the best way but seen work at my very first program. – ikaruss Nov 01 '17 at 14:27
0

This works also for me (Debian)

import sys, termios, signal
from _thread import interrupt_main

while True:
   timeout = 3
   signal.signal(signal.SIGALRM, lambda x,y: interrupt_main())
   signal.alarm(3)
   try:
       c = input("Number? ")
   except:
       termios.tcflush(sys.stdin, termios.TCIOFLUSH)
       answer = input('\nContinue? ')
       if (len(answer) == 0) or (answer.lower()[0] != 'y'):
           break
signal.alarm(0)

If you are using Windows you could try using interrupt_main as handler for Timer

t = Timer(timeout, interrupt_main)

This approach does not fully work for me. In my linux box the signal handler is able to interrupt the input() call but the timer handler, however, not. Only if you press Enter, the program flow follows to the "Continue" question

J.M. Robles
  • 614
  • 5
  • 9