3
\$\begingroup\$

I'm new to programming in Python, and I am trying to create a multiplication exercise generator. I've got the following code for the solution, but I'm wondering if there is any more elegant solutions than this one. Note: I have not covered lists, tuples, or dictionaries as of yet so I'm using the absolute basics to create this program.

#solution.py
#A script that allows a student to learn multiplication using the random
#module. Answers will be made and the script must display to try again
#or to present the next questions.

from random import randrange
answer = 0

def generate_question() :
    global answer

    #Random numbers
    number_one = randrange(1, 13)
    number_two = randrange(1, 13)

    #Correct answer
    answer = number_one * number_two

    #Display question
    print "What is %d times %d?" % (number_one, number_two)

def check_answer(user_input) :
    global answer

    #Answer check
    if user_input == answer :
        print "Very good!"
        generate_question()
    else :
        print "Try again!"

#Script Section
generate_question()

while True :
    #Answer to question
    user_input = int(raw_input("Answer: "))
    check_answer(user_input)
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

You're using functions, that's good. But, your program would be easier to understand, and better, if it didn't.

As a rule of thumb; don't put things in global scope. Whether it be via global or by not putting your code in a function. This is the global scope becomes un-reliable and you proceed to not know what your code is doing.

I would say that you should move check_answer into your while loop. This is as rather than using generate_question you should use break. This at the moment would end the program, but if you add another while True loop you can get the same functionality. This is better as then you are starting to separate generating a question and checking if it's correct. As we now only rely on the outer while to correctly setup the inner while, rather than changing globals to get things to work.

And so I'd use:

from random import randrange

def generate_number():
    return randrange(1, 13)

def main():
    while True:
        num1, num2 = generate_number(), generate_number()
        answer = num1 * num2
        print "What is %d times %d?" % (num1, num2)
        while True:
            user_input = int(raw_input("Answer: "))
            if user_input == answer:
                print "Very good!"
                break
            else:
                print "Try again!"

You should notice that this is your code. With a second while loop and a break. But you should notice it's easier to understand what it's doing, when coming as a third party.

As at first, I didn't notice your code asks more than one question.


Just so you know you're already using a tuple! In print "What is %d times %d?" % (num1, num2). The (num1, num2) is creating a tuple. If you decided to use this rather than num1 and num2 then you would change num1 to num[0] and num2 to num[1]. This is as in most programming languages they start lists with zero rather than one. Lists actually work the same way as tuples, but are created using [] rather than (). The only difference is you can change num[0] when using a list, but you can't with a tuple.

You should also learn what try-except are. If I enter abc rather than 123 into your program it would exit abruptly. What these do is try to run the code, if an error occurs run the except code. But I'll warn you now, never use a 'bare except'. Which is an except that doesn't say what it's protecting against. This is as if the code raises a different error than you'll run code as if it were another, which can hide bugs. And makes finding those bugs really hard to find.

And so I'd further change the code to use:

from random import randrange

def generate_number():
    return randrange(1, 13)

def main():
    while True:
        num1, num2 = generate_number(), generate_number()
        answer = num1 * num2
        print "What is %d times %d?" % (num1, num2)
        while True:
            try:
                user_input = int(raw_input("Answer: "))
            except ValueError:
                print('That is not a valid number.')
                continue
            if user_input == answer:
                print "Very good!"
                break
            else:
                print "Try again!"
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.