【问题标题】:How to have input while a while loop ( or similar) is executed如何在执行 while 循环(或类似循环)时进行输入
【发布时间】:2014-08-23 10:12:07
【问题描述】:

虽然我不确定,但我确实相信线程可以实现这一点。大多数解决这个问题的线程都没有解决它来匹配我的问题。我创建了一个简单的类似泥浆的战斗系统,当你“战斗”一个 NPC 时会执行该系统。我有在 while 循环下运行的代码,它检查你和 NPC 之间的健康状况,如果你们中的一个人死了,那么循环就会结束。

然而

在循环过程中,我希望用户可以在其中输入命令,而不是被困在观看循环代码块而您无能为力的情况下。从我在线阅读的内容来看,线程模块可能对我有帮助?另外,如果有人有 PyGame 经验,也许研究一下这将是一个解决方案?请让我知道你的想法。

下面是我想要完成的一个非常简单的示例。

import time

fighting = True
while fighting:
    # do the magic here
    time.sleep(4)       # to give it a nice even pace between loop intervals

尽管在任何时候我都希望能够输入诸如技能或咒语之类的命令。 有什么想法或建议吗?

【问题讨论】:

  • 命令是否需要在键入后立即执行,还是可以等待循环的新迭代?
  • @Dannnno 他们可以等到循环的新迭代很好,我可以使用任何可行的方法。
  • 不是完美的复制品,但应该足以为您指明正确的方向
  • 我已经看过那个论坛@Dannnno ,它不是我的问题,也不是重复的。它提出了同样的问题,但在两个不同的方面。

标签: python multithreading while-loop


【解决方案1】:

您可以将人机界面和格斗游戏分成单独的线程。格斗游戏使用队列进行输入,该队列使用超时继续。这是一个非常简单的队列结构,它应该能够满足您的最低要求。

import time
import threading
import Queue


def fighter(input_queue):
    while True:
        start = time.time()
        # do stuff
        wait = time.time() - start()
        if wait <= 0.0:
            wait = 0
        try:
            msg = input_queue.get(wait, wait)
            if msg == 'done':
                return
            # do something else with message
        except Queue.Empty:
            pass

def main():
    input_queue = Queue.Queue()
    fight_thread = threading.Thread(target=fighter, args=(input_queue,))
    fight_thread.start()
    while True:
        msg = raw_input('hello ')  # py 2.x
        input_queue.put(msg)
        if msg == 'done':
            break
    fight_thread.join()

【讨论】:

  • done_event 是干什么用的?您既没有发出信号也没有在任何地方等待它(队列已经在内部同步,所以我认为您不需要其他任何东西)。
  • @abarnet - 这是反馈机制的一部分,但它只是让示例变得复杂。它应该已从示例中删除。
【解决方案2】:

如果您只希望它在 Windows 上运行,并且希望保持简单的事件循环:

fighting = True
inputbuf = ''
while fighting:
    # do the magic here
    while msvcrt.khbit():
        newkey = msvcrt.getwche()
        inputbuf += newkey
        if newkey == '\r':
            process_command(inputbuf)
            inputbuf = ''
    time.sleep(4)       # to give it a nice even pace between loop intervals

另一方面,如果你想使用后台线程,那就简单多了:

def background():
    for line in sys.stdin:
        process_command(line)
bt = threading.Thread(target=background)
bt.start

fighting = True
while fighting:
    # do the magic here
    time.sleep(4)       # to give it a nice even pace between loop intervals

这适用于跨平台,它提供正常的行缓冲输入(包括完整的readline 支持),人们可能会喜欢。

但是,我假设您希望 process_command# do the magic here 代码共享信息,甚至可能设置 fighting = False。如果你在没有任何线程同步的情况下这样做,它将不再跨平台工作。 (它可能适用于 Windows CPython 和 Unix CPython,但可能适用于 IronPython 或 Jython——或者更糟糕的是,它在大部分时间都能工作,但随机失败只是经常需要你修复它,但不够频繁,你可以调试它......)

【讨论】:

    【解决方案3】:

    您可能正在寻找的是非阻塞 raw_input 实现。这将允许循环继续进行,同时允许用户输入命令。

    有一个实现此herehere 的示例。也许您可以调整其中一个以适合您的目的。

    编辑:

    或者,如果您正在处理 Windows...

    【讨论】:

    • 遗憾的是,这两个示例都需要 Unix 操作系统或类似操作系统才能工作。我在 Windows 平台上工作。
    • 刚刚编辑了我的回复以包含指向 Windows 示例的链接。希望这对你有用。
    • 使用该示例不起作用的 IDE。除非你在 Windows 控制台上这样做
    猜你喜欢
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    相关资源
    最近更新 更多