# Ten questions maths game

Like my previous question about my Mental Maths game , I have written a script for a ten questions Maths game and again it seems like there is a more simple method, can anyone take me out of the dark on this one?

def tenquestions():
mode=input("(E)asy, (M)edium, (H)ard")
questions=0
rightqs=0
while questions != 10:
if operations == "A":
if mode == "E":
num1 = randint(5,1000)
num2 = randint(5,1000)
useranswer=int(input(str(num1) + "+"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "M":
num1 = randint(1000,10000)
num2 = randint(1000,10000)
useranswer=int(input(str(num1) + "+"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "H":
num1 = randint(10000,1000000)
num2 = randint(10000,1000000)
useranswer=int(input(str(num1) + "+"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
else:
print("Invalid Input")
elif operations == "S":
if mode == "E":
num1 = randint(50,100)
num2 = randint(5,49)
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "M":
num1 = randint(5000,10000)
num2 = randint(100,5000)
useranswer=int(input(str(num1) + "-"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "H":
num1 = randint(50000,1000000)
num2 = randint(10000,50000)
useranswer=int(input(str(num1) + "-"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
else:
print("Invalid Input")
elif operations == "M":
if mode == "E":
num1 = randint(5,25)
num2 = randint(1,10)
useranswer=int(input(str(num1)+ "×"+ str(num2) +"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "M":
num1 = randint(25,100)
num2 = randint(10,100)
useranswer=int(input(str(num1) + "×"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "H":
num1 = randint(100,2500)
num2 = randint(100,1000)
useranswer=int(input(str(num1) + "×"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
else:
print("Invalid Input")
elif operations == "D":
if mode == "E":
possnums1 = [30,40,60,70,80,90,100]
possnums2 = [5,10,2]
num1 = possnums1[randint(0,6)]
num2 = possnums2[randint(0,2)]
useranswer=int(input(str(num1) + "÷"+ str(num2) +"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "M":
possnums1 = [100,120,240,330,540,390,510]
possnums2 = [5,10,2,6]
num1 = possnums1[randint(0,6)]
num2 = possnums2[randint(0,3)]
useranswer=int(input(str(num1) + "÷"+ str(num2) +"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
elif mode == "H":
possnums1 = [280,3080,1680,308,196,5628,12588]
possnums2 = [28,14,7]
num1 = possnums1[randint(0,6)]
num2 = possnums2[randint(0,2)]
useranswer=int(input(str(num1) + "÷"+ str(num2) +"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1
else:
print("Invalid Input")
else:
print("Invalid Input")
print(str(rightqs) + " out of " +str(questions) + " correct")
again=input("Again? Type 'Y' for yes and 'N' for no")
from random import randint
print("TEN QUICK QUESTIONS")
again = "Y"
while again=="Y":
operations = input("(A)ddition, (S)ubtraction, (M)ultiplication, (D)ivision")
tenquestions()

• I'm not the downvoter, but you were likely downvoted because of the two questions in a row with the same problems. If you had just posted the first one, you could have improved this one before you posted it. – Hosch250 Dec 12 '15 at 16:23
• I don't see a sign of learning from the answer of Hosch250 on the previous question. This question was posted too soon after the first, while I was also writing an answer, from which you could have learned enough to make this question substantially better. A large portion of my answer on the previous question could be copy-pasted here. It's not ideal for the site to have such content. So I suggest to 1. try to learn from the answers you receive, and 2. leave enough time to receive answers before posting a follow-up – janos Dec 12 '15 at 17:02
• will do in future, sorry guys – Joe Dec 12 '15 at 17:26
• In the answer by Janos, he is mentioning the use of operator.add & co, does that sound familiar somehow? This is one of the lesson we hope for you to have picked up from earlier answers, and implement if possible in new code. – holroy Dec 12 '15 at 21:25

As mentioned in my previous answer, you can use a function to remove this duplication:

num1 = randint(5,1000)
num2 = randint(5,1000)
useranswer=int(input(str(num1) + "+"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1


Becomes:

def addition(min, max):
num1 = randint(min, max)
num2 = randint(min, max)
useranswer=int(input(str(num1) + "+"+ str(num2)+"="))
print("Correct!")
rightqs=rightqs+1
else:
questions=questions+1


Again, this will result in heavy duplication between the addition/subtraction, etc. methods than can be removed in a similar manner. You will also be left with a messy chain of if/elifs that can likely be cleaned up as well.

You can simplify the statement questions=questions+1 into questions += 1

This is an unnecessary cast:

num1 = randint(min, max)
num2 = randint(min, max)


Last, but not least, you should put your starting code in an if __name__ == "__main__": function. This will prevent problems when you start working with code in multiple files.

The tenquestions function is 170 lines long. Try to aim for the smallest possible functions that do one thing and do it well.

When you have similar code with segments of code implementing identical logic but with different values in certain positions, that's a prime candidate for method extraction: the logic should be moved to its own function, and the changing values should be replaced with function parameters.

@Hosch250 started to explain that same point, let's take that a step further and transform your code. Following the first tip, and a few other tips in my previous answer to your previous question, your code becomes:

def play_add(minvalue, maxvalue):
num1 = randint(minvalue, maxvalue)
num2 = randint(minvalue, maxvalue)
answer = num1 + num2
prompt = '{} + {} = '.format(num1, num2)
print("Correct!")
return True
return False

def play_sub(num1min, num1max, num2min, num2max):
num1 = randint(num1min, num1max)
num2 = randint(num2min, num2max)
answer = num1 - num2
prompt = '{} - {} = '.format(num1, num2)
print("Correct!")
return True
return False

def tenquestions():
mode = input("(E)asy, (M)edium, (H)ard")
questions = 0
rightqs = 0
while questions != 10:
if operations == "A":
if mode == "E":
rightqs += 1
questions += 1
elif mode == "M":
rightqs += 1
questions += 1
elif mode == "H":
rightqs += 1
questions += 1
else:
print("Invalid Input")
elif operations == "S":
if mode == "E":
if play_sub(50, 100, 5, 49):
rightqs += 1
questions += 1
elif mode == "M":
if play_sub(5000, 10000, 100, 5000):
rightqs += 1
questions += 1
elif mode == "H":
if play_sub(50000, 1000000, 10000, 50000):
rightqs += 1
questions += 1
else:
print("Invalid Input")
elif operations == "M":
# ... and so on ...


And so on. You can do similar for multiplication and division too.

Ok so this eliminated a lot of duplication from tenquestions, but there is still a lot of duplication in play_add and play_sub. So follow the same logic, extract the common part to a new function, let's call it play_operation, and let's implement play_add and play_sub in terms of that:

def play_operation(op, symbol, num1min, num1max, num2min, num2max):
num1 = randint(num1min, num1max)
num2 = randint(num2min, num2max)
answer = op(num1, num2)
prompt = '{} {} {} = '.format(num1, symbol, num2)
print("Correct!")
return True
return False


Note that division is a tad more complicated than the others. That's fine, in fact it's important to know where to stop with generalization. In case of division, you should extract the common logic to a play_div function, and you can stop there, no need to bend over backwards to alter play_operation to work in this case too.