Python, функция в цикле while разрушает его для меня

Я программирую игру в кости. Этот сегмент кода предназначен для ввода, чтобы убедиться, что у меня есть правильный ввод (например, 5+4*3/2-1), а не для сбоя программы позже.

Я использую easygui для графического интерфейса. Сначала код был таким:

#possible_inputs = a list of operators (+-*/) and the values from the dices (1-6) as well as "OK, "Del" and "Reroll"
#raw_user_input = empty list
#br_value - the target value
#dice_value_list - the values from the dices
var = 0

    while(var != possible_inputs.index("OK")):
        var = eg.indexbox(raw_user_input, "Targetvalue: " + br_value_str, possible_inputs)
        if(var != possible_inputs.index("OK")):
          raw_user_input.append(possible_inputs[var])  
        if(var == possible_inputs.index("Del")):
            raw_user_input[:] = []
        if(var == possible_inputs.index("Reroll")):
            #reroll dices

    if(len(raw_user_input) == 0):
        eg.msgbox("No input given", "ERROR")
        return gui_input(dice_value_list, br_value)

    for r in range(len(raw_user_input)):
        if(r%2 == 0):
            if(raw_user_input[r] not in dice_value_list):
                eg.msgbox("Incorrect expression", "ERROR")
                return gui_input(dice_value_list, br_value)            
        else:
            if(raw_user_input[r] not in allowed_operators):
                eg.msgbox("Incorrect expression", "ERROR")
                return gui_input(dice_value_list, br_value)     

Это работало нормально, и моя программа не зависала, потому что ввод не был бы неправильным.

Однако я должен поместить функцию, которая вычисляет входные данные внутри цикла while, чтобы иметь возможность предоставлять пользователю их вычисленное выражение в окне сообщений в режиме реального времени. Поэтому я изменил программу на это:

    input_value_calc = 0
    while(var != possible_inputs.index("OK")):
        var = eg.indexbox(raw_user_input, "Target value: " + br_value_str + ", current target value " + str(input_value_calc), possible_inputs)
        if(var != possible_inputs.index("OK")):
          raw_user_input.append(possible_inputs[var])  
        if(var == possible_inputs.index("Del")):
            raw_user_input[:] = []
        if(var == possible_inputs.index("Reroll")):
            #reroll dices

        br_check, values_input, input_value_calc = user_input_value_check(raw_user_input,br_value):

def user_input_value_check(raw_user_input,br_value):

    if(len(raw_user_input) == 0):
        eg.msgbox("No input given", "ERROR")
        gui_input(dice_value_list, br_value)

    for r in range(len(raw_user_input)):
        if(r%2 == 0):
            if(raw_user_input[r] not in dice_value_list):
                eg.msgbox("Incorrect expression", "ERROR")
                gui_input(dice_value_list, br_value)            
        else:
            if(raw_user_input[r] not in allowed_operators):
                eg.msgbox("Incorrect expression", "ERROR")
                gui_input(dice_value_list, br_value)
#rest of the program calculates the score, which works fine
#the function returns True/False (if the input evaluates to the correct br_value), values_input (again for other functions in the program), input_value_calc (the evaluated input value)

Если я даю правильный ввод в первый раз, когда все в порядке, но моя проблема сейчас в том, что каждый раз, когда я даю неправильный ввод (2 оператора или 2 значения рядом друг с другом, начинаются с оператора и т. Д.), Он говорит, что я ошибаюсь, и позволяет мне дать другой вход. На этот раз, однако, кнопки не работают должным образом (например, я нажимаю del, и это добавляет "del" к моему вводу)

Я был бы очень признателен за помощь! Спасибо!

1 ответ

@cataclysmic,

Возможно, есть другой способ достичь того, что вы пытаетесь. Например, у вас есть проверка данных после того, как пользователь полностью вводит информацию. вместо этого, почему бы не заставить пользователя делать правильные вещи. Таким образом, пользователю не следует разрешать сначала нажимать "*". Сначала они должны нажать на штамп. Затем они должны быть вынуждены выбрать только оператор (например, ' * '), а затем переключаться между выбором кубика и операциями выбора (как в тактах: тик... ток... тик... ток).

Кроме того, как только пользователь выбирает кубик, он не может выбрать его снова (я полагаю). Итак, удалите его из списка после выбранного.

Рассмотрим следующий код. Это не идеально, но я пытался сделать это похожим на то, что вы пытались сделать. Я проверил это на более новой версии easygui, чем у вас, поэтому я не могу обещать, что это работает:

import easygui as eg

def get_user_input(target_value, dice_rolls):

    operator_choices = ['+', '-', '*', '/']
    operator_choices.extend(['OK', 'Del', 'Reroll'])
    dice_choices = [str(r) for r in dice_rolls]
    dice_choices.extend(['Del', 'Reroll'])

    raw_user_input = list()
    mode = 'tick'
    while True:
        if mode == 'tick':
            choices = dice_choices
        else:
            choices = operator_choices
        var = eg.indexbox(''.join(raw_user_input), "Target value: {}".format(target_value), choices)
        if var is None:
            raise ValueError("Dialog closed with invalid entry")
        choice = choices[var]
        if choice == 'OK':
            return ''.join(raw_user_input)
        if choice == 'Del':
            raw_user_input = list()
            dice_choices = [str(r) for r in dice_rolls]
            dice_choices.extend(['Del', 'Reroll'])
            mode = 'tick'
            continue
        if choice == 'Reroll':
            return None
        raw_user_input.append(choice)
        if mode == 'tick': # Remove the dice from the list of dice
            del dice_choices[dice_choices.index(choices[var])]
        if mode == 'tick':
            mode = 'tock'
        else:
            mode = 'tick'


br_value = 12 # Sample value
dice_value_list = [4, 2, 1, 1, 5] # Sample rolls

try:
    user_input = get_user_input(br_value, dice_value_list)
except:
    print("Your data entry was cancelled by the user")
    exit()

if user_input is None:
    print("Rerolling the dice")
    #.... do that now!

print("User entered: {}".format(user_input))
####
# Now, put code here to process your user_input
# ....
#
####

Пожалуйста, продолжайте программировать! Иногда это сложно, но и полезно!

Другие вопросы по тегам