Multiplication Quiz in Python
Beginner · Games · about 40 minutes to build · 132 lines
Pick the times tables to practise and answer timed questions, then see your score, your time and the facts you missed.
The program
Press Run and answer its questions in the box that appears under the code.
Open it in the full editor to save it, share it and keep building.
Sample run
What the program printed, and what was typed (in yellow).
Multiplication quiz Answer within 10 seconds to score a point. Which tables? (like 3 7, 2-5 or all): 3 to 7 Type numbers from 1 to 12, a range like 2-5 or all. Which tables? (like 3 7, 2-5 or all): 3 7 How many questions? (5-20): 6 Q1: 7 x 3 = 21 Correct. Q2: 7 x 11 = 77 Correct. Q3: 3 x 2 = 6 Correct. Q4: 3 x 6 = eighteen Type the answer as a number. Q4: 3 x 6 = 18 Correct. Q5: 3 x 9 = 28 Not quite: 3 x 9 = 27. Q6: 3 x 1 = 3 Correct. Score: 5 / 6 (83%) Time: 7.5 s, about 1.2 s a question Good work. Practise these: 3 x 9 = 27 Play another round? (y/n) n Goodbye.
How it is built
1. Reading the tables
partition("-") splits a piece like 2-5 into a low and a high number. A single number like 7 has no high part, so high or low uses the same number twice. Text that is not a number, or is out of range, returns None.
def parse_tables(text): """Turn "3 7", "2-5" or "all" into a sorted list of tables, or None.""" if text.strip().lower() == "all": return list(range(2, MAX_FACTOR + 1)) tables = set() for piece in text.replace(",", " ").split(): low, _, high = piece.partition("-") try: low, high = int(low), int(high or low) except ValueError: return None if not 1 <= low <= high <= MAX_FACTOR: return None tables.update(range(low, high + 1)) return sorted(tables) or None
2. Timing one question
The clock starts before the question is asked and stops when a number comes back. A typo like eighteen asks again without stopping the clock.
def ask_question(number, a, b): """Ask one question and return (answer, seconds taken).""" start = time.perf_counter() while True: try: answer = int(input(f"Q{number}: {a} x {b} = ")) return answer, time.perf_counter() - start except ValueError: print(" Type the answer as a number.")
3. Picking questions
random.choice() picks one of the chosen tables and random.randint() the other factor. The loop draws again if the question is the same as the one before.
def new_question(tables, previous): """Pick a random question that is not the same as the previous one.""" while True: question = (random.choice(tables), random.randint(1, MAX_FACTOR)) if question != previous: return question
4. Playing a round
A right answer within TIME_LIMIT seconds scores a point; a right answer that was too slow does not. Wrong answers go into missed so they can be shown at the end.
def play_round(tables, count): """Ask count questions and return (score, total seconds, missed facts).""" score, total, missed = 0, 0.0, [] a, b = None, None for number in range(1, count + 1): a, b = new_question(tables, (a, b)) answer, seconds = ask_question(number, a, b) total += seconds right = answer == a * b if right and seconds <= TIME_LIMIT: score += 1 print(" Correct.") elif right: print(f" Correct, but it took over {TIME_LIMIT} s: no point.") else: print(f" Not quite: {a} x {b} = {a * b}.") missed.append(f"{a} x {b} = {a * b}") return score, total, missed
5. The result
The score becomes a percentage, which picks the message, and the total time divided by the number of questions gives the time per question.
def show_result(score, count, total, missed): """Print the score, the time and the facts to practise.""" percent = round(100 * score / count) print(f"\nScore: {score} / {count} ({percent}%)") if total < 1: print("Time: under 1 second") else: print(f"Time: {total:.1f} s, about {total / count:.1f} s a question") if percent == 100: print("A perfect round.") elif percent >= 70: print("Good work.") else: print("Keep practising: you are getting there.") if missed: print("Practise these:", "; ".join(missed))
Make it bigger
- Ask the missed facts again at the end of the round until the player gets them all right.
- Add a division mode that turns each fact around, like 56 / 8.
- Save the best score for each table in a file.
- Take one second off the time limit after every perfect round.