Search code examples
pythonwindowsinputstdin

Clear input buffer before input() on Windows?


I'm creating a game in which you have to guess the result of an operation in a certain time; to do this i created a thread to have a timed input and then I close the thread after the time is up.

Issue

My problem is that when the user doesn't enter any number, before the time is up, in the next cycle the input waits for two inputs instead of one.

So, what I need is to clear the stdin before getting a new input. I find some solutions for Unix but nothing for Windows.

Code

import os
import random 
from time import sleep
import threading
import concurrent.futures

random.seed()

def get_input(a):
    a[0]=input()

def do_operation(time, n):
    number_1 = random.randint(0,n)
    number_2 = random.randint(0,n)
    operations = ['+', '-', '/', '*']
    operation = random.choices(operations)
    operation = "".join(operation)
    if operation == '/':
        while(number_1 % number_2 != 0):
            number_1 = random.randint(0,n)
            number_2 = random.randint(0,n)
    #Trovo i risultati delle operazioni
    if operation == '+':
        result = number_1 + number_2
    elif operation == '-':
        result = number_1 - number_2
    elif operation == '*':
        result = number_1 * number_2
    elif operation == '/':
        result = number_1 / number_2

    print(number_1,operation,number_2, '=', end = " ")
    count = [None, result]
    x = threading.Thread(target=get_input, args = (count,), daemon=True)
    x.start()
    x.join(time)
    return count


def stampastats(lives, points):
    print('\n\t\t\t\tlives:', end = " ")

    for live in range(lives):
        print('*', end = " ")    

    print('\n\t\t\t\tPoints:', points)

#main
lives = 3
points = 0
while(lives > 0):
    stampastats(lives, points)
    result = do_operation(10, 200)
    if result[0] != result[1]:
        print('\nWrong')
        print('\nThe result was: ' + str(result[1]))
        lives -= 1
    else:
        print('\nBravo')
        points += 1000
    if lives == 0:
        print('\nGAME OVER')
    else:
        sleep(1)
        os.system('cls')

Solution

  • There is a pending input() if a timeout happened. You can send an Enter in this case; I'm applying the pyautogui module to do that. (Call is_alive() after join() to decide whether a timeout happened.).

    Some runtime errors fixed (and some debugging outputs kept) in the following script:

    import os
    import random 
    from time import sleep
    import threading
    import concurrent.futures
    import pyautogui
    
    random.seed()
    
    def get_input(a):
        a[0]=input()
    
    def do_operation(time, n):
        number_1 = random.randint(0,n)
        number_2 = random.randint(0,n)
        operations = ['+', '-', '/', '*']
        operation = random.choices(operations)
        operation = "".join(operation)
        #Trovo i risultati delle operazioni
        if operation == '+':
            resulta = number_1 + number_2
        elif operation == '-':
            resulta = number_1 - number_2
        elif operation == '*':
            resulta = number_1 * number_2
        else: # operation == '/':
            while(number_2 == 0 or number_1 % number_2 != 0):
                    number_1 = random.randint(0,n)
                    number_2 = random.randint(0,n)
            resulta = number_1 / number_2
        
        print(number_1,operation,number_2, '=', end = " ")
        count = [None, resulta]
        x = threading.Thread(target=get_input, args = (count,), daemon=True)
        x.start()
        x.join(time)
        #print( x.native_id, x.is_alive(), x.isDaemon()) # debugging info 
        if x.is_alive():
            pyautogui.press("enter")               # answer to pending input()
        return count
    
    
    def stampastats(lives, points):
        print('\n\t\t\t\tlives:', end = " ")
        for live in range(lives):
            print('*', end = " ")    
        print('\n\t\t\t\tPoints:', points)
    
    #main
    lives = 3
    points = 0
    while(lives > 0):
        stampastats(lives, points)
        result = do_operation(10, 200)
        #print(result)
        if((result[0] == None) or (result[0] == '') or (float(result[0]) != float(result[1]))):
            print('\nWrong', result)
            print('The result was: ' + str(result[1]))
            lives -= 1
        else:
            print('\nBravo', result)
            points += 1000
        if(lives == 0):
            print('\nGAME OVER')
        else:
            sleep(1)
            # os.system('cls')