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
# ....
#
####
Пожалуйста, продолжайте программировать! Иногда это сложно, но и полезно!