3
\$\begingroup\$

I have the following program for a multiple choice quiz game. Before I get stuck in some habits, can anyone please review and propose suggestions for improvements?

import random
import time

YES = ['y', 'Y', 'yes', 'Yes', 'YES']
NO = ['n', 'N', 'no', 'No', 'NO']
CLEAR = ['c', 'C', 'clear', 'Clear', 'CLEAR']
QUIT = ['q', 'Q', 'quit', 'Quit', 'QUIT']
MULTIPLECHOICE = ['a', 'b', 'c', 'd']


class QuizGame:
    '''  repository of methods to do with QuizGame
         -  get_username
         -  play_loop
         -  ask_play_again
         -  escape_quiz
         -  play_quiz
         -  read_highscores
         -  write_highscores
         -  clear_highscores
         -  display_highscores
    '''
    questions = \
        {1: ('What was the first video game ever made?',
             'a)  God of War 9\nb)  Pacman \nc)  Pong \nd)  Tennis for Two',
             'd'),

         2: ('What was the most expensive video game to ever be developed?',
             'a)  Destiny\nb)  Call of Duty: Modern Warfare 2  \n'
             'c)  Grand Theft Auto: V  \nd)  Disney Infinity',
             'b'),

         3: ('What amount of time a day does the average gamer (In the US, '
             'age 13 or older) spend gaming?',
             'a)  54 minutes\nb)  25 hours\nc)  2 hours\nd)  30 minutes',
             'a'),

         4: ('Who is the founder of Nintendo?',
             'a)  Fusajiro Yamauchi\nb)  Bob Dylan\nc)  Steve Bovaird\n'
             'd)  Nihonjin no Shimei',
             'a'),

         5: ('What was the most purchased game of 2017?',
             'a)  Jesus sim\nb)  Farming Simulator 2017\n'
             'c)  Call of Duty: WWII\nd)  Destiny 2',
             'c'),

         6: ('When was E3 [Electronic Entertainment Expo] 2017?',
             'a)  13 Jun 2017 - 15 Jun 2017\nb)  13 Jun 2017 - 14 Jun 2017\n'
             'c)  15 July 2017 - 13 July 2017\nd)  10 Jun 2017 - 18 Jun 2017',
             'a'),

         7: ('What was the most popular console of 2010?',
             'a)  Xbox 360\nb)  PlayStation 3\nc)  Xbox 1\nd)  PlayStation 4',
             'a'),

         8: ('Who was the most subscribed gaming youtuber of 2012?',
             'a)  PrettyL8r\nb)  Pewdiepie\nc)  Greg\nd)  NotGreg',
             'b'),

         9: ('Who won the Game of The Year award 2016?',
             'a)  Overwatch\nb)  Treyarch\nc)  Blizzard\n'
             'd)  Rainbow Six Siege',
             'c'),

         10: ('When did DOOM release?',
              'a)  December 10, 1993\nb)  February 23, 1995\n'
              'c)  January 32, 20019\nd)  Yesterday',
              'a'), }

    welcometext =\
        '\nHello {}, welcome to The Videogame Quiz'\
        '\nIn this quiz, you will be asked 10 questions about videogames.'\
        '\nTry your best to answer all 10 correctly. Enter a, b, c or d '\
        '\ndepending on which answer you think is right\n'

    users = {}
    score = 0
    highscore_file = 'highscore.log'

    @classmethod
    def get_username(cls):
        '''  method to ask user for user_name, if user name is Quit then leave.
             Dictionary of cls.users is checked on existing users. If user
             does not exist he/ she is added.
        '''
        user_name = ''
        quit = False
        while len(user_name) < 4 and not quit:
            user_name = input('Hello! What is your name [enter Q(uit) '
                              'to leave]?: ').strip().capitalize()
            if user_name in QUIT:
                quit = True

        if not quit:
            if user_name not in cls.users:
                cls.users.update({user_name: 0})
                cls.highscore = 0

            print(cls.welcometext.format(user_name))

        return user_name, quit

    @classmethod
    def play_loop(cls, user_name):
        '''  method to control loop of the quiz, update highscore, and ask
             to play again or not
        '''
        playagain = True
        while playagain:
            print(f'\n{user_name}, your current highscore is '
                  f'{cls.users[user_name]}.\n')

            if cls.escape_quiz():
                break

            score = cls.play_quiz()

            if score > cls.users[user_name]:
                cls.users.update({user_name: score})

            playagain = cls.play_again()

    @staticmethod
    def play_again():
        '''   ask player if he/ she wants to play quiz again
        '''
        answered = False
        while not answered:
            answer = input('Do you want to take the quiz again? Y or N: ')
            answered = True

            if answer in YES:
                playagain = True

            elif answer in NO:
                playagain = False

            else:
                answered = False

        return playagain

    @staticmethod
    def escape_quiz():
        '''  ask player twice if he/ she is ready to continue
        '''
        answered = 0
        question = '\nAre you ready to continue? Y or N? '
        while answered < 2:
            answer = input(question)
            print('---------------------------------------')
            answered += 1

            if answer in YES:
                escape_the_quiz = False
                break

            elif answer in NO:
                escape_the_quiz = True
                for i in range(3):
                    print('Oh... ok')
                    time.sleep(0.5)
                question = '\nNow are you ready to continue? Y or N '

            else:
                print('Yes or no only please!')

        return escape_the_quiz

    @classmethod
    def play_quiz(cls):
        '''  core of quiz asking multiple choice questions. Player can leave
             by entering quit
        '''
        questions = cls.questions.copy()
        question_choice = {i for i in range(1, len(questions)+1)}
        score = 0
        question_nr = 1

        while questions:
            question = random.sample(question_choice, 1)[0]
            answered = False

            print(f'Question: {question_nr} of {len(cls.questions)}')
            print(questions[question][0])
            print(questions[question][1])
            question_nr += 1

            answered = False
            while not answered:
                answer = input('What is your answer?: ').lower()

                if answer in (MULTIPLECHOICE + QUIT):
                    answered = True

                else:
                    print('ERROR, please input a, b, c or d only please!')

            if answer in QUIT:
                break

            elif answer == questions[question][2]:
                print('Good job! You are correct.\n')
                score += 1

            else:
                print('Unfortunately that is not correct! '
                      'Better luck next time.\n')

            questions.pop(question)
            question_choice.remove(question)

        print(f'Your score is >>> {score}\n')

        return score

    @classmethod
    def read_highscores(cls):
        '''  read highscores from cls.highscore_file
        '''
        try:
            with open(cls.highscore_file, 'r') as highscores:
                for line in highscores:
                    user_name, score = line.split(':')
                    cls.users[user_name.strip()] = int(score)

        except Exception as e:
            print('Error in log file, must be format <name: score>')

    @classmethod
    def write_highscores(cls):
        '''  write highscores to cls.highscore_file
        '''
        try:
            with open(cls.highscore_file, 'w') as highscores:
                for name in cls.users:
                    highscores.write('{}: {}\n'.
                                     format(name, str(cls.users[name])))

        except Exception as e:
            print('Error in log file, must be format <name: score>')

    @classmethod
    def clear_highscores(cls):
        '''  clears the highscore file if confirmed by typing 'CLEAR'
        '''
        answer = input('\nDo you want to clear the scores log, '
                       'type \'CLEAR\' ')

        if answer == 'CLEAR':
            with open(cls.highscore_file, 'w') as highscores:
                highscores.write('')

    @classmethod
    def display_highscores(cls):
        '''  displays highscores in order from high to low
        '''
        print('\nHighscores')
        print('-'*40)
        print('{:20}{}'.format('Name', 'Score'))
        print('-'*40)

        sorted_output = sorted(QuizGame.users.items(), key=lambda v: v[1],
                               reverse=True)
        for line in sorted_output:
            print(f'{line[0]:20}{line[1]}')


def main():
    '''  starts the program
    '''
    QuizGame.read_highscores()
    QuizGame.display_highscores()
    quit = False

    while not quit:
        user_name, quit = QuizGame.get_username()
        if not quit:
            QuizGame.play_loop(user_name)

    QuizGame.display_highscores()
    QuizGame.write_highscores()
    QuizGame.clear_highscores()


if __name__ == '__main__':
    main()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.