I have posted my first [version](http://codereview.stackexchange.com/questions/109813/rock-paper-scissors-with-scores-and-save-file) of RockPaperScissors a while back. It was on an old version of python with improper use of some functions. This version was updated to a more recent version of python and has a little extra for users who run on terminal. Is there anything I should add or change? Are my classes used correctly? Are there any bugs? Any overall improvements?

    # Programmer: DeliriousSyntax
    # Date: October 30, 2015
    # File: RockPaperScissorsV2-py3.py
    
    # This is a classic game of rock paper scissors.
    
    import random
    import shelve
    import time
    import colorama
    import sys


    
    
    class Scorecard(dict):
        """Stores all items related to "Score\""""
    
        def __init__(self, **kwargs):
            """Makes all values set to 0"""
            super().__init__(**kwargs)
            for key in ('rounds', 'losses', 'wins', 'draws', 'games_won',
                        'games_lost', 'games_played', "total_rounds",
                        'rounds_won', 'rounds_lost', 'rounds_tied', 'game_draws'):
                self[key] = 0
    
        def reset(self):
            """Resets the scores for next game"""
            for key in ('rounds', 'losses', 'wins', 'draws'):
                self[key] = 0
    
        def round_update(self, result):
            """Updates the info for each round
            :param result:
            """
            self['rounds'] += 1
            if result == 'win':
                self['wins'] += 1
            elif result == 'loss':
                self['losses'] += 1
            else:
                self['draws'] += 1
    
        def add2score(self):
            """Adds the scores from the game to total scores"""
            self['games_played'] += 1
            self['rounds_lost'] += self['losses']
            self['rounds_won'] += self['wins']
            self['rounds_tied'] += self['draws']
            self['total_rounds'] += self['rounds']
            if self['losses'] > self['wins']:
                self['games_lost'] += 1
            elif self['losses'] < self['wins']:
                self['games_won'] += 1
            else:
                self['game_draws'] += 1
    
        def stats_board(self):
            """Returns the stat board"""
            return ('\n\n++++++++++++++++++++-=Stats=-++++++++++++++++++++++\n'
                    '===================================================\n'
                    '|--{:^11}--|--{:^12}--|--{:^12}--|\n'.format("X   ", "Rounds", "Games") +
                    '|--{:^11}--|--{:^12}--|--{:^12}--|\n'.format("Wins  ", self['rounds_won'], self['games_won']) +
                    '|--{:^11}--|--{:^12}--|--{:^12}--|\n'.format("Losses", self['rounds_lost'], self['games_lost']) +
                    '|--{:^11}--|--{:^12}--|--{:^12}--|\n'.format("Draws ", self['rounds_tied'], self['game_draws']) +
                    '|--{:^11}--|--{:^12}--|--{:^12}--|\n'.format("Played", self['total_rounds'], self['games_played']) +
                    '\n')
    
        def final_score(self):
            """Returns the games final board"""
            return ('\n\n+++++++++++Final Score++++++++++++\n'
                    '==================================\n'
                    '|--{:^11}--|--{:^12}--|\n'.format('Wins  ', self['wins']) +
                    '|--{:^11}--|--{:^12}--|\n'.format('Losses', self['losses']) +
                    '|--{:^11}--|--{:^12}--|\n'.format('Draws  ', self['draws']) +
                    '|--{:^11}--|--{:^12}--|\n'.format('Rounds', self['rounds']) +
                    '\n')
    
    
    class Game:
        """Main Game Class"""
        MOVES = ('rock', 'paper', 'scissors')
        ROUND_OPTIONS = ('1', '3', '5', '7')
        MENU = ('stats', 'play', 'quit')
        WIN_CONDITIONS = {
            "rock": "scissors",
            "scissors": "paper",
            "paper": "rock",
        }
        green = colorama.Fore.GREEN
        yellow = colorama.Fore.YELLOW
        cyan = colorama.Fore.CYAN
        blue = colorama.Fore.BLUE
        magenta = colorama.Fore.MAGENTA
        COLORS = (green, yellow, cyan, blue, magenta)
    
        def delirioussyntax(self):
            """Creator"""
            colorama.init()
            idle = "idlelib" in sys.modules
            time.sleep(.3)
            if idle is False:
                print(colorama.Back.BLACK + colorama.Style.BRIGHT, end='')
            for letter in "Delirious":
                if idle is False:
                    print(random.choice(Game.COLORS), end='')
                print(letter, end='')
                sys.stdout.flush()
                time.sleep(random.uniform(.1, .4))
            if idle is False:
                print(colorama.Fore.RED, end='')
            for letter in "Syntax":
                print(letter, end='')
                sys.stdout.flush()
                time.sleep(random.uniform(.1, .4))
            print(colorama.Style.RESET_ALL, "\n\n")
    
        def intro(self):
            """Intro statements"""
            self.Score = Scorecard()
            try:
                with shelve.open("RPSv2.dat") as f:
                    self.Score = f["statistics"]
            except KeyError:
                with shelve.open("RPSv2.dat") as f:
                    f["statistics"] = self.Score
    
            print("Brought to you by: ", end='')
            sys.stdout.flush()
            self.delirioussyntax()
            time.sleep(1)
            print("Welcome to the greatest, mind blowing challenge of all time.")
            print("     - Rock, Paper, Scissors!\n")
            print("Many have tried and many have FAILED...")
            print("This will be a test between the human mind and my AI.")
            input("Press \"enter\" when you believe your ready for this challenge.\n")
            print("\nGood Luck... Human.\n\n")
    
        def custom_input(self, question, choices):
            """A custom loop that checks to see if choices are valid
            :param choices:
            :param question:
            """
            response = None
            while True:
                while response not in choices:
                    response = input(question).lower()
                    if response in choices:
                        return response
                    print("Correct inputs:\n  >", end='')
                    print("\n  >".join(choices), "\n")
    
        def start_game(self):
            """Main menu of game basically"""
            self.intro()
            while True:
                choice = self.custom_input("Would you like to play, look at stats, or quit?:\n   ->", self.MENU)
                if choice == 'play':
                    self.play_game()
                elif choice == 'stats':
                    stats = self.Score.stats_board()
                    print(stats)
                else:
                    break
    
        def computer_choice_gen(self):
            """Generates computer choice"""
            return random.choice(Game.MOVES)
    
        def play_game(self):
            """Player vs Computer game"""
            rounds = int(self.custom_input("\nHow many rounds would you like to play?\n   ->", self.ROUND_OPTIONS))
            while self.Score['rounds'] != rounds:
                self.user_choice = self.custom_input("\nWhat is your choice, human?\n   ->", self.MOVES)
                self.computer_choice = self.computer_choice_gen()
                print("\nComputer choice is {}".format(self.computer_choice))
                result = self.evaluate()
                self.Score.round_update(result)
                if result == "win":
                    print("{} beats {}! The human wins this round.\n\n".format(self.user_choice, self.computer_choice))
                elif result == "loss":
                    print("{} beats {}! Hahaha! You lost this round!\n\n".format(self.computer_choice, self.user_choice))
                else:
                    print("I knew you were going to pick {}!\n\n".format(self.user_choice))
            print(self.Score.final_score())
            self.Score.add2score()
            self.Score.reset()
            with shelve.open("RPSv2.dat") as f:
                f["statistics"] = self.Score
    
        def evaluate(self):
            """returns if outcome of round"""
            if Game.WIN_CONDITIONS[self.user_choice] == self.computer_choice:
                return "win"
            elif self.user_choice == self.computer_choice:
                return "draw"
            else:
                return "loss"
    
    
    if __name__ == "__main__":
        Game = Game()
        Game.start_game()