首页 > 解决方案 > 记忆游戏计时器实现和错误处理

问题描述

我已经实现了一个记忆游戏,用户必须在 5 秒的计时器运行时在脑海中对数字进行排序。

请看下面的代码:

    from random import randint
    from threading import Timer

    def timeout():
        print("Time over\n#####################\n")

    while True:
        list = []
        for i in range(5):
            list.append(randint(1000, 10000))

        t = Timer(5, timeout)
        t.start()

        print(list)
        print('[ 1  ,  2  ,  3  ,  4  ,  5  ]')

        solution = sorted(list)[2]
        print('please select the 3rd largest number in this row (1-5):')
        input_string = input()
        selection = int(input_string)

        if solution == list[selection - 1]:
            print("Your guess is correct\n")
        else:
            print("Your guess is wrong\n")

        t.join()

这是游戏交互本身(请忽略语法高亮):

USER@HOST:~/$ python3 memory_game.py
[8902, 8655, 1680, 6763, 4489]
[ 1  ,  2  ,  3  ,  4  ,  5  ]
please select the 3rd largest number in this row (1-5):
4
Your guess is correct

Time over
#####################

[5635, 3810, 1114, 5042, 1481]
[ 1  ,  2  ,  3  ,  4  ,  5  ]
please select the 3rd largest number in this row (1-5):
4
Your guess is wrong

Time over
#####################

[6111, 1430, 7999, 3352, 2742]
[ 1  ,  2  ,  3  ,  4  ,  5  ]
please select the 3rd largest number in this row (1-5):
23
Traceback (most recent call last):
  File "memory_game.py", line 24, in <module>
    if solution == list[selection - 1]:
IndexError: list index out of range
Time over
#####################

任何人都可以帮我解决这些问题:
1. 只有当玩家需要超过 5 秒的时间来回答时,才应该写“时间结束”。如果玩家及时解决了它,下一个挑战应该会静默出现。
2. 如果玩家没有写任何猜测并按下“Enter”,程序将终止并显示错误消息: Traceback (last recent call last): File "memory_game.py", line 22, in selection = int(input_string) ValueError: invalid以 10 为基数的 int 的文字:''
3. 如果玩家输入任何随机数,程序将退出并出现“索引超出范围错误” - 我找不到在哪里放置 try: except: 任何帮助将不胜感激 -谢谢!

标签: python-3.xerror-handlingtimer

解决方案


至于你的问题:

  1. 您可以使用t.cancel()(停止计时器并且不调用该函数)而不是t.join()(等到线程完成;这总是会导致超时,当然)
  2. (和 3。)这些基本上是相同的——将查询消息和所有输入处理放入一个while循环中,一旦你知道输入是有效的,就跳出它

...

  1. 另外,“超时”消息实际上并没有做任何有用的事情(例如,在超时发生后您仍然可以输入有效答案。我通过在超时时使程序退出以蛮力的方式“修复”该问题除了这样做,您还可以使用全局变量来存储超时是否被命中,并在您的输入中相应地处理它(确保使用例如互斥锁使其成为线程安全的)。

一般来说,把程序的结构转一下可能会更容易——让主线程处理输入的超时和验证,让线程只处理输入(这样很容易杀死线程停止被处理的输入)。

当然,使用该select模块,可以在没有线程的情况下更好地实现这一点(有一个由线程/计时器写入的管道和标准输入,然后选择两者进行读取,它将阻塞直到用户输入或超时发生)。

也许有人会发布一个不错asyncio的基于解决方案?;)

这是修改后的解决方案(尽可能少地修改以使其工作,可以重构其他部分以使其总体上更好):

import random                                                                                                            
import threading                                                                                                         
import os                                                                                                                

def timeout():                                                                                                           
    print("Time over\n#####################\n")                                                                          
    # You can't use sys.exit() here, as this code is running in a thread                                                 
    # See also: https://stackoverflow.com/a/905224/1047040                                                               
    os._exit(0)                                                                                                          

while True:                                                                                                              
    list = []                                                                                                            
    for i in range(5):                                                                                                   
        list.append(random.randint(1000, 10000))                                                                         

    t = threading.Timer(5, timeout)                                                                                      
    t.start()                                                                                                            

    print(list)                                                                                                          
    print('[ 1  ,  2  ,  3  ,  4  ,  5  ]')                                                                              

    solution = sorted(list)[2]                                                                                           
    while True:                                                                                                          
        try:                                                                                                             
            print('please select the 3rd largest number in this row (1-5):')                                             
            input_string = input()                                                                                       
            selection = int(input_string)                                                                                
            chosen = list[selection - 1]                                                                                 
            # If we arrive here, the input was valid, break out of the loop                                              
            break                                                                                                        
        except Exception as e:                                                                                           
            # Tell the user that the input is wrong; feel free to remove "e"                                             
            # from the print output                                                                                      
            print('Invalid input:', e)                                                                                   

    if solution == chosen:                                                                                               
        print("Your guess is correct\n")                                                                                 
    else:                                                                                                                
        print("Your guess is wrong\n")                                                                                   

    # Make sure to cancel the thread, otherwise guessing correct or wrong                                                
    # will block the CLI interface and still write "time out" at the end                                                 
    t.cancel()                                                                                                           

推荐阅读