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

如何为Python游戏设置用户输入最长时限?

单词复述游戏:输入限时5秒的实现问题与解决

需求说明

要做一个简单的单词复述游戏:

  • 系统依次给出单词,用户需在5秒内输入完全相同的单词
  • 输入正确则进入下一轮,超时或输入错误则游戏结束
  • 用户可以提前输入(比如2秒内完成),无需等待满5秒

初始无时限代码

for word in ["banana","earth","turtle","manchester","coctail","chicken"]:
    # 用户最多5秒输入单词,提前完成可直接进入下一轮,超时则游戏结束
    user_input = input(f"Type word '{word}': ")

    # 输入正确则进入下一轮
    if(user_input==word):
        continue
    # 输入错误则结束游戏
    else:
        print("You lost")
        break

尝试的threading.Timer实现(存在问题)

import threading

class NoTime(Exception):
    pass

def count_time():
    raise NoTime

for word in ["banana","earth","turtle","manchester","coctail","chicken"]:
    try:
        # 创建5秒后抛出异常的计时器
        timer = threading.Timer(5,count_time)
        timer.start()

        user_input = input(f"Type word '{word}': ")
        # 若提前输入,取消计时器避免不必要的异常
        timer.cancel()

        if user_input==word:
            print("Correct")
        else:
            print("Incorrect, you LOSE!")
            break

    except NoTime:
        print("You run out of time, you lose")
        break

出现的错误信息

回溯(最近的调用最后):
  文件 "C:\Users\papit\AppData\Local\Programs\Python\Python311\Lib\threading.py", 第1038行, 在 _bootstrap_inner中
    self.run()
  文件 "C:\Users\papit\AppData\Local\Programs\Python\Python311\Lib\threading.py", 第1394行, 在 run中
    self.function(*self.args, **self.kwargs)
  文件 "C:\Users\papit\OneDrive\Pulpit\Programming\Python Bro Course\Math\second\threading_training.py", 第7行, 在 count_time中
    raise NoTime
NoTime

问题原因

子线程中抛出的异常无法被主线程的try-except捕获。threading.Timer启动的是独立子线程,count_time函数里的NoTime异常是在子线程上下文触发的,主线程的异常处理机制无法感知到这个异常,所以会直接打印堆栈信息,而不是进入except NoTime分支执行游戏结束逻辑。

解决方案:跨平台实现方式

用threading.Thread读取输入,配合threading.Event标记输入完成状态,主线程通过wait()设置超时时间,完美解决跨平台的输入限时问题:

import threading

words = ["banana", "earth", "turtle", "manchester", "coctail", "chicken"]

for word in words:
    input_received = threading.Event()
    user_input = None

    # 定义读取输入的线程函数
    def get_user_input():
        nonlocal user_input
        user_input = input(f"输入单词 '{word}': ").strip()
        input_received.set()  # 标记输入已完成

    # 启动输入线程
    input_thread = threading.Thread(target=get_user_input)
    input_thread.start()

    # 主线程等待最多5秒:要么输入完成,要么超时
    if not input_received.wait(timeout=5):
        # 超时逻辑
        print("\n你超时了,游戏结束!")
        break
    else:
        # 输入完成,判断对错
        if user_input == word:
            print("正确!进入下一轮")
        else:
            print(f"错误!你输入的是'{user_input}',游戏结束")
            break
else:
    # 所有单词都正确完成
    print("恭喜你,所有单词都答对了!游戏通关!")

代码说明

  1. input_received是线程安全的事件对象,用来标记用户是否完成输入
  2. 单独启动一个线程执行get_user_input,避免input()阻塞主线程的超时判断
  3. 主线程通过input_received.wait(5)等待最多5秒:
    • 如果5秒内用户完成输入,input_received会被设置,wait()返回True,进入输入校验逻辑
    • 如果5秒超时,wait()返回False,触发超时结束游戏的逻辑
  4. 最后添加for-else分支,处理所有单词都答对的通关场景

另一种Unix/Linux专属方案:用select实现

如果你的程序只在Unix/Linux环境运行,可以用select模块直接监听标准输入,无需额外线程:

import sys
import select

words = ["banana", "earth", "turtle", "manchester", "coctail", "chicken"]

for word in words:
    print(f"输入单词 '{word}': ", end='', flush=True)
    # 监听stdin,超时5秒
    ready, _, _ = select.select([sys.stdin], [], [], 5)

    if ready:
        # 有输入,读取并处理
        user_input = sys.stdin.readline().strip()
        if user_input == word:
            print("正确!进入下一轮")
        else:
            print(f"\n错误!你输入的是'{user_input}',游戏结束")
            break
    else:
        # 超时
        print("\n你超时了,游戏结束!")
        break
else:
    print("恭喜你,所有单词都答对了!游戏通关!")

内容的提问来源于stack exchange,提问作者Paweł Michoń

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:31:41