2

I'm programming a dice game. This segment of code is for the input, to make sure I have a correct input (example, 5+4*3/2-1) and not crash the program later.

I'm using easygui for GUI. At first the code was like this:

#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)     

It worked fine, and my program wouldn't crash because the input wouldn't be wrong.

However I'm supposed to put the function that calculates the input inside the while-loop to be able to give the user their calculated expression in the messagebox in real time. So I changed the program to this:

    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)

If I give a correct input the first time everything is fine but my problem now is that everytime I give the wrong input (2 operators or 2 values next to eachother, start with an operator etc) it says I'm wrong and lets me give another input. This time however the buttons isnt working properly (for example I press del and it adds "del" to my input)

I would really appreciate someone giving me help on this one! Thanks!

smci
  • 32,567
  • 20
  • 113
  • 146
  • 2
    Is this an easygui problem, or a code problem? None of us have easygui, and we aren't going to install it just to debug this for you, either. So please use print statements (or pdb debugger) to **narrow down what is going wrong**, then **cut your question down to the absolute minimum to reproduce your symptom** e.g. `gui_input(example-bad-expression, ...)` – smci Apr 11 '14 at 09:41
  • 1
    Also, your **title** is awful. It's really unclear, and it also sounds like you haven't spent any time trying to narrow down your bug (*'This program is wrong'*). So please improve it too. (Ordinarily, such a question would get downvoted/closed like crazy. I'm amazed this still has +2 upvotes). Show us that you're prepared to do a little work, before asking us to do some for you. – smci Apr 11 '14 at 09:42
  • 1
    @smci You're right, this problem lacks the required information to diagnose the problem. – TooTone Apr 11 '14 at 10:22

1 Answers1

0

@cataclysmic,

Perhaps there is another way to achieve what you are attempting. For instance, you have data validation after the user completely enters the information. instead, why not force the user to do the right thing. So, the user should not be allowed to press ' * ' first. They should first be required to press a die. Then they should be forced to select only an operator (like ' * '), and then alternate between selecting die and selecting operations (as in a clock tick...tock...tick...tock).

Also, once the user selects a die once they should not be able to select it again (I assume). So, delete it from the list after selected.

Consider the following code. It isn't perfect, but I tried to make it similar to what you were trying to do. I have tested this on a newer version of easygui than you have, so I can't promise it works:

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
# ....
#
####

Please keep programming! It is sometimes difficult, but rewarding too!

Robert Lugg
  • 1,090
  • 2
  • 12
  • 40