import random # generates the two terms to use in questions def int_generator(): # Generates a random number between 2 and 12 term_1 = random.randint(2,12) term_2 = random.randint(2,12) return term_1, term_2 # generates a random operation for the quiz to use def ops_generator(): # The list of operators there is to choose from operators = ["+", "-", "*", "/"] # Randomizes the operator for the quiz op = random.choice(operators) return op # generates the question using the specific operator that is chosen from the # ops_gen function def question_generator(term_1, term_2, op): if op == "+": question = f"{term_1} + {term_2}" elif op == "-": question = f"{term_1} - {term_2}" elif op == "*": question = f"{term_1} * {term_2}" else: question = f"{term_1} / {term_2}" return question # Check that users have entered a valid # option based on a list def string_checker(question, valid_ans=("yes", "no")): error = f"Please enter a valid option from the following list: {valid_ans}" while True: # Get user response and make sure it's lowercase user_response = input(question).lower() for item in valid_ans: # check if the user response is a word in the list if item == user_response: return item # check if the user response is a word in the list # the first letter of an item in the list elif user_response == item[0]: return item # print error if user does not enter something that is valid print(error) print() # Displays instructions def instructions(): print(""" *** Instructions *** This is a math quiz that contains basic arithmetic questions. Although you may choose to include area questions if you wish to. You also may choose to include perimeter questions if you wish to. Each arithmetic question will use two random numbers and a random operator (+, -, * or /). For area and perimeter questions it will either be for a square or rectangle. The lengths and width will be displayed for rectangles, squares will display one side with a number Your goal is to answer each question correctly. How it works: • Choose how many questions you want to answer • You may choose if you want to include area questions or not. • For each round, a new maths question will appear. • Type your answer and press . • The quiz will tell you if you are correct or incorrect. • If you entered an incorrect answer, the correct answer will be displayed. • Your total score will be displayed at the end if you wish to see them. Rules: • Arithmetic numbers are between 2 and 12. • Area numbers are between 2 and 24. • Perimeter numbers are between 2 and 36. • If area questions are included there will be a 50% chance for an area question to appear each round. • If Perimeter questions are included there will be a 50% chance for a perimeter question to appear each round. • If both Perimeter and Area questions are included there will be a 33.3% chance for an each question to appear each round. • For area and perimeter questions you do not need to include units. • Division questions may produce decimal answers. • If an answer contains decimals it will be rounded to 1 dp. • You can exit the quiz at any time by typing 'xxx'. Good luck! """) # checks for an integer between 5 and 15 for round count def int_check(): while True: error = "Please enter an integer from 5 - 15: " try: response = int(input("How many rounds (5 - 15) would you like to play?\nYour answer: ")) # checks that the number is from the range of 5 - 15 if 5 <= response <= 15: return response else: print(error) except ValueError: print(error) # generates the area question def area_question_generator(): shapes = ["rectangle", "square"] shape = random.choice(shapes) if shape == "rectangle": width = random.randint(2, 24) length = random.randint(2, 24) unit = random.choice(["cm", "m", "km"]) area_question = f"Area of a rectangle with width of {width}{unit} and a length of {length}{unit}" area_answer = width * length else: # square side = random.randint(2, 24) unit = random.choice(["cm", "m", "km"]) area_question = f"Area of a square with a {side}{unit} side" area_answer = side * side return area_question, area_answer # generates the area question def perimeter_gen(): shapes = ["rectangle", "square"] shape = random.choice(shapes) if shape == "rectangle": width = random.randint(2, 36) height = random.randint(2, 36) unit = random.choice(["cm", "m"]) perimeter_question = f"The Perimeter of a rectangle with width of {width}{unit} and a length of {height}{unit}" perimeter_answer = 2 * (width + height) else: # square side = random.randint(2, 36) unit = random.choice(["cm", "m"]) perimeter_question = f"The Perimeter of a square with a {side}{unit} side" perimeter_answer = 4 * side return perimeter_question, perimeter_answer # Main routine # Starts game variables rounds_played = 0 correct_answers = 0 incorrect_answers = 0 arithemetic_questions = 0 perimeter_questions = 0 area_questions = 0 # Asks if user wants instructions print("Welcome to the maths quiz!") want_instructions = string_checker("Would you like to see the instructions on how to play?\nYour answer: ") print() # Displays instructions if user requests them if want_instructions == "yes": instructions() # Asks if user wants to include area questions want_area_question = string_checker("Would you like to include area questions?\nYour answer: ") if want_area_question == "yes": print("You have chosen to include area questions.") else: print("You have chosen to not include area questions.") print() # Asks if user wants to include perimeter questions want_perimeter_question = string_checker("Would you like to include perimeter questions?\nYour answer: ") if want_perimeter_question == "yes": print("You have chosen to include perimeter questions.") else: print("You have chosen to not include perimeter questions.") print() # Asks user how many rounds they want # And prints the chosen amount of rounds num_rounds = int_check() print(f"The chosen amount of rounds is {num_rounds}") # Game loop starts here while rounds_played < num_rounds: # Perimeter question question, answer = perimeter_gen() perimeter_questions += 1 # Adds the round played to the total round number rounds = rounds_played + 1 # Rounds heading print(f"\n___ Round {rounds} out of {num_rounds} ___") # Gets user input user_input = (input(f"What is {question}?:\nYour answer: ")).lower() # If user sends xxx ends the game if user_input == "xxx": break # Turns user input into a float and checks if it is a number # If it isn't a number then add an incorrect answer and continue to # Next round try: user_answer = round(float(user_input), 1) except ValueError: print("You entered an invalid answer. This will be marked incorrect." f"\nThe correct answer was {answer}.") incorrect_answers += 1 rounds_played += 1 continue # Checks if answer is correct if user_answer == answer: correct_answers += 1 print("Correct!") else: incorrect_answers += 1 print(f"Incorrect! The correct answer is {answer}.") # Adds the current round played to the total rounds_played += 1 # End of game loop print("You have finished the quiz!") print() # game score calculations total = correct_answers + incorrect_answers correct_percent = (correct_answers / total) * 100 incorrect_percent = (incorrect_answers / total) * 100 arithmetic_percent = (arithemetic_questions / total) * 100 area_percent = (area_questions / total) * 100 perimeter_percent = (perimeter_questions / total) * 100 # Asks if user wants to see their score see_score = string_checker("Would you like to see your score?\nYour answer: ") # If the user wants to see their score then display their score if see_score == "yes": print() print(f"You played {rounds_played} rounds!" f"\nWith {correct_answers} ({correct_percent:.1f}%) correct answers!" f"\nand {incorrect_answers} ({incorrect_percent:.1f}%) incorrect answers.") # if user chose to include area and perimeter, show break down of area and arithemetic questions answered if want_perimeter_question == "yes" and want_area_question == "yes": print(f"You answered {arithemetic_questions} ({arithmetic_percent:.1f}%) arithmetic questions!") print(f"You answered {perimeter_questions} ({perimeter_percent:.1f}%) perimeter questions!") print(f"You answered {area_questions} ({area_percent:.1f}%) area questions!") # If user chose to include area questions, show break down of area and arithemetic questions answered elif want_area_question == "yes": print(f"You answered {arithemetic_questions} ({arithmetic_percent:.1f}%) arithmetic questions!") print(f"You answered {area_questions} ({area_percent:.1f}%) area questions!") # If user chose to include perimeter questions, show break down of area and arithemetic questions answered elif want_perimeter_question == "yes": print(f"You answered {arithemetic_questions} ({arithmetic_percent:.1f}%) arithmetic questions!") print(f"You answered {perimeter_questions} ({perimeter_percent:.1f}%) perimeter questions!") # If user chose to not include area or perimeter questions, only display the total questions answered else: print(f"You answered {total} total questions!")