Projet : Amélioration des objets cartes

Prérequis :

Nous allons améliorer la classé que nous avions crée lors du projet précédent (en prérequis).

Un code possible d'une carte

Fichier carte.py :

SEPT = 7
HUIT = 8
NEUF = 9
DIX = 10
VALET = 11
DAME = 12
ROI = 13
AS = 14

PIQUE = 4
COEUR = 3
CARREAU = 2
TREFLE = 1


VALEURS = (SEPT, HUIT, NEUF, DIX, VALET, DAME, ROI, AS)
COULEURS = (TREFLE, CARREAU, COEUR, PIQUE)


class Carte:
    def __init__(self, valeur, couleur):
        self.couleur = couleur
        self.valeur = valeur

    def texte(self):
        valeur = ["7", "8", "9", "10", "V", "D", "R", "1"]
        couleur = ["♣︎", "♦", "♥", "♠"]
        return valeur[self.valeur - 7] + couleur[self.couleur - 1]

    def plus_grande_ou_égale_que(self, other):
        return (self.valeur > other.valeur) or (
            (self.valeur == other.valeur) and (self.couleur >= other.couleur)
        )

Fichier test_carte.py :

import carte
from carte import Carte


def test_constructeur():
    assert isinstance(Carte(carte.SEPT, carte.TREFLE), Carte)


def test_texte():
    assert Carte(carte.SEPT, carte.TREFLE).texte() == "7♣︎"


def test_plus_grande_ou_égale_que():
    assert Carte(carte.AS, carte.TREFLE).plus_grande_ou_égale_que(Carte(carte.VALET, carte.PIQUE))
    assert Carte(carte.AS, carte.TREFLE).plus_grande_ou_égale_que(Carte(carte.AS, carte.TREFLE))
    assert Carte(carte.AS, carte.PIQUE).plus_grande_ou_égale_que(Carte(carte.AS, carte.TREFLE))
    assert not Carte(carte.VALET, carte.PIQUE).plus_grande_ou_égale_que(Carte(carte.AS, carte.TREFLE))

Affichage d'une carte

Remplacez la méthode Carte.texte() par la méthode Carte.__str__().

Modifiez les tests pour prendre en compte de cette nouvelle méthode.

Attribut de classes

Pour créer les cartes on utilise des constantes définies dans le fichier carte.py. Commençons par mettre ces constantes directement dans la classe pour ne pas avoir à tout importer :

Placez les différentes constantes relatives aux valeurs et aux couleur des cartes en attributs de classe et modifiez les tests en conséquence.

Cependant, pour spécifier à l'utilisateur les valeurs et couleurs possibles, utilisez des constantes et des tuples n'est cependant pas optimal. Pour gérer les énumérations, python met à disposition les Enum.

On pourrait ainsi gérer les couleurs ainsi :

>>> from enum import Enum
>>> couleur = Enum("Couleur", [("Pique", 4), ("Cœur", 3), ("Carreau", 2), ("Trèfle", 1)])
>>> print(couleur.pique.name)
pique
>>> print(couleur.pique.value)
4
>>> c = couleur.pique
>>> c
<Couleur.pique: 4>
>>> for c in couleur:
...     print(c)
...
Couleur.pique
Couleur.cœur
Couleur.carreau
Couleur.trèfle

Utilisez des Enum pour gérer les constantes VALEURS et COULEURS,puis supprimez les constantes relatives aux différentes valeurs et couleurs individuelles (on n'utilisera que les enum).

Modifiez les tests en conséquence.

Cette technique est redoutable : elle est à la fois lisible, sans magic number et portable ! Utilisez-la dès que vous voulez gérer des énumérations.

Comparaisons

Une fois la carte créée, il ne faudrait plus pouvoir la modifier. Or pour l'instant on a directement accès aux attributs, donc rien n'interdit de le faire, rendons nos attributs privés :

Rendez les attributs valeurs et couleurs de chaque carte privé.

Méthode de conception

Lorsque l'on crée un objet, si on a pas de raison particulière de le rendre modifiable on crée un value object. Cela évite les effets de bords (et rend la programmation concurrente et parallèle bien plus simple).

Comparaisons de cartes

Ajoutez à votre classe carte les opérateurs de comparaisons :

Codez et testez les opérateurs de comparaisons :

  • == qui correspond a à la méthode __eq__
  • != qui correspond a à la méthode __ne__
  • < qui correspond a à la méthode __lt__
  • > qui correspond a à la méthode __gt__
  • <= qui correspond a à la méthode __le__
  • >= qui correspond a à la méthode __ge__

N'hésitez pas à utiliser des opérateurs déjà codé. Vous pouvez par exemple utiliser les fonctions == et <= pour coder les autres les comparaisons.