5
\$\begingroup\$

This time I made a quiz game, in which the player is asked questions and receives points for each question answered correctly. Some people told me I should learn about classes, so this is what I came up with.

import random
from Quiz_Questions import game_questions
questions = [*game_questions]
def game():
 print('-' * 20)
 player_score = 0
 right_answers = 0
 wrong_answers = 0
 while len(questions) > 0:
 question = random.choice(questions)
 questions.remove(question)
 print(question.text)
 user_answer = input('Insert answer (Yes or No): ')
 while user_answer not in ['yes', 'y', 'f', 'true', 'no', 'n', 'f', 'false']:
 print('Sorry, that is an invalid answer')
 user_answer = input('Please insert another answer (Yes or No): ')
 if user_answer.lower() in question.correct_answer:
 player_score += question.question_reward
 right_answers += 1
 print('You got it right! (+{} points)'.format(question.question_reward))
 print('You have {} points'.format(player_score))
 else:
 wrong_answers += 1
 print('You got it wrong, good luck next time!')
 print('-' * 20)
 print('Congratulations! You have answered all the questions!')
 print('Your final score is {} points'.format(player_score))
 print('You answered {} questions right'.format(right_answers))
 print('And {} questions wrong.'.format(wrong_answers))
game()

Quiz_Question.py

class Question():
 def __init__(self, text, correct_answer, question_reward):
 self.text = text
 if correct_answer == 'True':
 self.correct_answer = ['yes', 'y', 'f', 'true']
 elif correct_answer == 'False':
 self.correct_answer = ['no', 'n', 'f', 'false']
 self.question_reward = question_reward
game_questions = [Question('Russia has a larger surface area than Pluto.', 'True', 7),
 Question('There are as many stars in space than there are grains of sand on every beach in the world.', 'False', 5),
 Question('For every human on Earth there are 1.6 million ants.', 'True', 8),
 Question('On Jupiter and Saturn it rains diamonds.', 'True', 9),
 Question('Scotland’s national animal is the phoenix.', 'False', 4),
 Question('A banana is a berry.', 'True', 8),
 Question('An octopus has three hearts.', 'True', 4),
 Question('There are 10 times more bacteria in your body than actual body cells.', 'True', 9),
 Question('Rhode Island is the closest US state to Africa.', 'False', 3),
 Question('Shakespeare made up the name "Sarah" for his play Merchant of Venice.', 'False', 3)]
Peilonrayz
44.4k7 gold badges80 silver badges157 bronze badges
asked Jan 11, 2020 at 19:01
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

I would turn around the logic. The design you have has a lot of the general logic in the main program, and a lot of game-specific logic in the questions module. A better design for reusability would be to put the logic in a module, and the game-specific stuff (basically just the questions and perhaps some very superficial user interface) in the main program.

I would also define a separate class for the collection of questions; so maybe the main game might look like

from Quiz_Questions import QuestionsCollection, Question, PlayerState, QuestionsExhausted
collection = QuestionsCollection()
collection.add('Russia has a larger surface area than Pluto.', 'True', 7)
collection.add('There are as many stars in space than there are grains of sand on every beach in the world.', 'False', 5)
collection.add('For every human on Earth there are 1.6 million ants.', 'True', 8)
collection.add('On Jupiter and Saturn it rains diamonds.', 'True', 9)
collection.add('Scotland’s national animal is the phoenix.', 'False', 4)
collection.add('A banana is a berry.', 'True', 8),
collection.add('An octopus has three hearts.', 'True', 4)
collection.add('There are 10 times more bacteria in your body than actual body cells.', 'True', 9)
collection.add('Rhode Island is the closest US state to Africa.', 'False', 3)
collection.add('Shakespeare made up the name "Sarah" for his play Merchant of Venice.', 'False', 3)
def game():
 print('-' * 20)
 player = PlayerState()
 questions = collection.game()
 while True:
 try:
 question = questions.next()
 except QuestionsExhausted:
 break
 print(question.challenge())
 user_answer = input('Insert answer (Yes or No): ')
 response = player.assess(question, user_answer)
 print(response)
 print('-' * 20)
 print('Congratulations! You have answered all the questions!')
 print('Your final score is {} points'.format(player.score()))
 print('You answered {} questions right'.format(player.right_answers()))
 print('And {} questions wrong.'.format(player.wrong_answers()))
game()

This is just a rough sketch, but hopefully hints at a different design where the classes encapsulate the behavior specific to each, with enough freedom to reassemble things in a different arrangement (multi-player game? Add timeouts?) and also with the user-facing I/O and message strings (mostly) separate from the library module.

This doesn't handle invalid input very elegantly but I'm thinking the way I started this, the Player class would be responsible for some I/O as well, so maybe actually refactor to

...
while True:
 try:
 question = questions.next()
 except QuestionsExhausted:
 break
 player.handle(question)
print('Congratulations! You have answered all the questions!')
...
Ben A
10.7k5 gold badges37 silver badges101 bronze badges
answered Jan 11, 2020 at 20:24
\$\endgroup\$
1
  • \$\begingroup\$ Hey, sorry, I didn't understand much of what you did, but I'll keep that thing you said about separating the general logic and game-specific logic in mind. Thanks for your suggestions! \$\endgroup\$ Commented Jan 11, 2020 at 20:46
2
\$\begingroup\$
if correct_answer == 'True':
 self.correct_answer = ['yes', 'y', 'f', 'true']
elif correct_answer == 'False':
 self.correct_answer = ['no', 'n', 'f', 'false']

f is recognized as a correct answer for both True and False answers, so I can collect all the points without knowing the correct answer to any of the questions by consistently answering f.

This behavior is a bit counter-intuitive, so it makes sense to explicitly document it in the code

answered Jan 26, 2020 at 7:04
\$\endgroup\$
1
  • \$\begingroup\$ Yeah, you are right, for True answers it should have been 't' instead of 'f', my mistake haha. \$\endgroup\$ Commented Jan 26, 2020 at 19:56

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.