You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python打字游戏开发:实现超时自动退出的倒计时功能

无线程实现打字游戏超时终止方案

问题描述

我正在为学校项目开发一款简易打字游戏,尝试用threading实现倒计时与输入同步运行,希望时间结束时自动终止游戏,但当前只能在按下回车时停止输入,超时终止功能未生效。现寻求无需threading的替代方案。

原代码

import time
import datetime
import random
import threading
library = ["Hello","World"] 
#There will be some text here

alphabet = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,":":0}
alphabet2 = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,"!":0,":":0}
def countdown1(h, m, s):

  total_seconds = h * 3600 + m * 60 + s

  while total_seconds > 0:

      # Timer represents time left on countdown
      timer = datetime.timedelta(seconds = total_seconds)

      print(timer, end="\r")
      # Delays the program one second
      time.sleep(1)

      # Reduces total time by one second
      total_seconds -= 1
  print("Start now!")

done = False
def countdown2():
  c = 0
  if done:
    print("You used "+str(c)+" seconds to type!! Good Job!!")
  while not done:
    time.sleep(1)
    c += 1
  
  
count = 0
print('You have 1 minute to type the following text')
c = random.randint(0,len(library)-1)
print(library[c])
print('Type after countdown, hit return after finishing or when the time is up')
countdown1(0,0,3)
threading.Thread(target=countdown2,daemon = True).start()
word = input().replace(" ", "")
done = True
passage = library[c].replace(" ", "")
total = len(passage)
for i in passage:
  if i in alphabet2:
    alphabet2[i] += 1
letter1 = []
letter2 = []
for i in word:
  if i in alphabet:
    alphabet[i] += 1
for key in alphabet.values():
  letter1.append(int(key))
for key in alphabet2.values():
  letter2.append(int(key))
for j in range(57):
  count += min(letter1[j],letter2[j])
print('Congrats! You got '+str(count)+'/'+str(total)+' right!')

替代方案(无线程)

可以通过第三方库或平台原生模块实现带超时的输入,无需线程即可在超时后自动终止输入。

跨平台兼容方案(推荐)

使用inputimeout库(需先安装:pip install inputimeout),该库封装了不同平台的实现,调用简单:

import time
import datetime
import random
from inputimeout import inputimeout, TimeoutOccurred

library = ["Hello","World"] 
# 可在此添加更多文本

alphabet = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,":":0}
alphabet2 = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,"!":0,":":0}

def countdown1(h, m, s):
    total_seconds = h * 3600 + m * 60 + s
    while total_seconds > 0:
        timer = datetime.timedelta(seconds=total_seconds)
        print(timer, end="\r")
        time.sleep(1)
        total_seconds -= 1
    print("Start now!")

count = 0
print('你有1分钟时间输入下面的文本')
c = random.randint(0, len(library)-1)
print(library[c])
print('倒计时结束后开始输入,完成后按回车,超时会自动结束')
countdown1(0, 0, 3)

# 设置超时时间为60秒(1分钟)
try:
    word = inputimeout(prompt='', timeout=60).replace(" ", "")
except TimeoutOccurred:
    print('\n时间到!')
    word = ''

passage = library[c].replace(" ", "")
total = len(passage)
for i in passage:
    if i in alphabet2:
        alphabet2[i] += 1
letter1 = []
letter2 = []
for i in word:
    if i in alphabet:
        alphabet[i] += 1
for key in alphabet.values():
    letter1.append(int(key))
for key in alphabet2.values():
    letter2.append(int(key))
for j in range(57):
    count += min(letter1[j], letter2[j])
print(f'恭喜!你答对了 {count}/{total} 个字符!')

原生实现(无需额外库)

若不想安装第三方库,可根据平台分别处理:

Windows平台(使用msvcrt)

import time
import datetime
import random
import msvcrt

library = ["Hello","World"] 
alphabet = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,":":0}
alphabet2 = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,"!":0,":":0}

def countdown1(h, m, s):
    total_seconds = h * 3600 + m * 60 + s
    while total_seconds > 0:
        timer = datetime.timedelta(seconds=total_seconds)
        print(timer, end="\r")
        time.sleep(1)
        total_seconds -= 1
    print("Start now!")

count = 0
print('你有1分钟时间输入下面的文本')
c = random.randint(0, len(library)-1)
print(library[c])
print('倒计时结束后开始输入,完成后按回车,超时会自动结束')
countdown1(0, 0, 3)

start_time = time.time()
word = ''
timeout = 60  # 1分钟超时

while time.time() - start_time < timeout:
    if msvcrt.kbhit():
        char = msvcrt.getche().decode('utf-8')
        if char == '\r':  # 回车键
            break
        word += char
else:
    print('\n时间到!')

word = word.replace(" ", "")
passage = library[c].replace(" ", "")
total = len(passage)
for i in passage:
    if i in alphabet2:
        alphabet2[i] += 1
letter1 = []
letter2 = []
for i in word:
    if i in alphabet:
        alphabet[i] += 1
for key in alphabet.values():
    letter1.append(int(key))
for key in alphabet2.values():
    letter2.append(int(key))
for j in range(57):
    count += min(letter1[j], letter2[j])
print(f'恭喜!你答对了 {count}/{total} 个字符!')

Unix/Linux平台(使用select)

import time
import datetime
import random
import sys
import select

library = ["Hello","World"] 
alphabet = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,":":0}
alphabet2 = {'a':0,'A':0,'b':0,'B':0,'c':0,'C':0,'d':0,'D':0,'e':0,'E':0,'f':0,'F':0,'g':0,'G':0,'h':0,'H':0,'i':0,'I':0,'J':0,'j':0,'k':0,'K':0,'l':0,'L':0,'m':0,'M':0,'n':0,'N':0,'o':0,'O':0,'p':0,'P':0,'q':0,'Q':0,'r':0,'R':0,'s':0,'S':0,'t':0,'T':0,'u':0,'U':0,'v':0,'V':0,'w':0,'W':0,'x':0,'X':0,'y':0,'Y':0,'z':0,'Z':0,',':0,'.':0,'-':0,"'":0,"!":0,":":0}

def countdown1(h, m, s):
    total_seconds = h * 3600 + m * 60 + s
    while total_seconds > 0:
        timer = datetime.timedelta(seconds=total_seconds)
        print(timer, end="\r")
        time.sleep(1)
        total_seconds -= 1
    print("Start now!")

count = 0
print('你有1分钟时间输入下面的文本')
c = random.randint(0, len(library)-1)
print(library[c])
print('倒计时结束后开始输入,完成后按回车,超时会自动结束')
countdown1(0, 0, 3)

timeout = 60  # 1分钟超时
print('开始输入:', end='', flush=True)
ready, _, _ = select.select([sys.stdin], [], [], timeout)
if ready:
    word = sys.stdin.readline().strip().replace(" ", "")
else:
    print('\n时间到!')
    word = ''

passage = library[c].replace(" ", "")
total = len(passage)
for i in passage:
    if i in alphabet2:
        alphabet2[i] += 1
letter1 = []
letter2 = []
for i in word:
    if i in alphabet:
        alphabet[i] += 1
for key in alphabet.values():
    letter1.append(int(key))
for key in alphabet2.values():
    letter2.append(int(key))
for j in range(57):
    count += min(letter1[j], letter2[j])
print(f'恭喜!你答对了 {count}/{total} 个字符!')

方案说明

  • 跨平台方案使用inputimeout,无需关心平台差异,代码简洁,适合快速开发。
  • 原生方案调用系统模块,无额外依赖,适合环境受限的场景。
  • 两种方案均能在超时后自动终止输入,替代原线程实现的功能,同时避免线程同步问题。

内容的提问来源于stack exchange,提问作者Shujin Liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:14:53