3
\$\begingroup\$

I've very recently started using OOP paradigms for the code in my work (academic research). As an exercise I tried coding this quick scoreboard.

I'm not interested in improving the 'display' part, I know there would be a lot to do there, but does my use of classes make any sense?

import os
from numpy import nan, nansum
from matplotlib import interactive
import matplotlib.pyplot as plt


class Player:
    def __init__(self, name):
        self.name = name
        self.score = []
        self.cumulative_score = []
        self.total_score = 0

    def add_score(self, score):
        self.score[-1] = score
        self.cumulative_score[-1] = self.total_score + score
        self.total_score = nansum(self.score)


class ScoreBoard:
    def __init__(self):
        plt.style.use('ggplot')
        interactive(True)
        player_name = True
        self.players = []
        while player_name:
            player_name = input('Player name ? ')
            if player_name:
                self.players += [Player(player_name)]
        self.round = 0
        self.figure = plt.figure()
        self.ax = self.figure.add_subplot(111)
        self.plots = {}
        for player in self.players:
            self.plots[player.name], = plt.plot(range(1, self.round + 1),
                                                player.cumulative_score,
                                                label=player.name, marker='*')
        plt.legend()

    def new_round(self):
        self.round += 1
        for player in self.players:
            player.score += [nan]
            player.cumulative_score += [nan]
        for i, player in enumerate(self.players):
            self.display()
            new_score = input('Score pour {}: '.format(player.name))
            if new_score:
                player.add_score(int(new_score))

    def display(self):
        self.ax.clear()
        for player in self.players:
            self.plots[player.name], = plt.plot(range(1, self.round + 1),
                                                player.cumulative_score,
                                                label=player.name, marker='*')
        plt.legend()
        os.system('cls' if os.name == 'nt' else 'clear')
        print(' \t| '.join(player.name for player in self.players))
        print(''.join(['-'] * 80))
        for round in range(self.round):
            print(' \t| '.join(str(player.score[round]) for player in
                               self.players))
        print(''.join(['-'] * 80))
        print(' \t| '.join(str(player.total_score)
                           for player in self.players))


score_board = ScoreBoard()

while True:
    score_board.new_round()
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I think your use of classes mostly makes sense.

The key to object oriented programming, in my humble opinion, is relating how we think about objects in the real world to the way our code is structured. If you were playing a game, would you, as the player, add a score to the score board? Well, it might depend on the game. Sometimes, the game might determine your score and add it to the scoreboard (I'm thinking battleship). In that game, the player doesn't add their score to the scoreboard, it is behind the scenes in a way.

I like that you created a class player, most games revolve around players and encapsulating that information in a class makes sense.

When you play a game, does the scoreboard determine when a new round occurs? Not really, that is sort of inherent to the game. The scoreboard, which in the real world encapsulates information needed just for displaying information related to a game, doesn't actually make decisions about a game. It merely receives information and then displays it. Therefore, it might make sense to separate your scoreboard's display functionality from the functionality of actually playing the game.

This could happen by creating another class called game that would have as members of the class player's and a scoreboard. The game class could be responsible for starting a new round and be responsible for making sure the scoreboard is updated and the player's own score is updated.

Often in OOP, methods are like actions and take on verb-like names. I like that you called your method add_score inside player.

I hope this is constructive feedback and you find it helpful. If you have any questions, let me know.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.