Projet : objets cartes
Encore un projet d'initiation dans le codage des objets. On s'intéresse ici aux méthodes spéciales qui permettent d'utiliser les objets comme des nombres.
Vous allez coder une classe Carte
, ce qui permettra par la suite de jouer à la bataille. La classe carte en elle-même ne fera pas grand chose, mais elle illustrera la notion de value object :
Définition
Un value object est un objet ne pouvant pas être modifié une fois créé : il ne possède aucune méthode lui permettant de changer ses attributs qu'il faut renseigner à sa création.
Ce projet va vous faire utiliser des méthodes d'améliorations d'objets comme :
- l'utilisation de la fonction spéciale d'affichage
__str__
- l'utilisation de fonctions spéciale de comparaisons
Remémorez vous ces parties avant de commencer le projet.
Projet
Vscode
Créez un dossier projet-cartes
sur votre ordinateur et ouvrez leu avec visual studio code pour un faire votre projet.
Programme principal & User stories
Le but du projet est de pouvoir jouer à une variante de la bataille :
But
On veut pouvoir mélanger un jeu de 32 cartes (sans joker) puis le séparer en 2 pioches de 16 cartes, un tas par joueur.
A chaque tour les deux joueurs prennent la première carte de leur pioche et la révèle. Le joueur ayant la plus grande carte (7 < 8 < 9 < 10 < V < D < R < 1 et si égalité de rang alors : ♠ > ♥ > ♦ > ♣︎) prend les deux cartes et les place dans sa pile de défausse (initialement vide).
Lorsqu'un joueur doit prendre une carte alors que sa pioche est vide, il mélange les cartes de sa défausse qui forment une nouvelle pioche. Si la pioche et la défausse sont vides, le joueur perd la partie.
Carte UML
La pioche et la défausse pouvant être facilement modélisées par des listes, il nous reste à créer une classe Carte pour avoir tous les éléments de base de notre projet.
Proposez une modélisation UML d'une classe Carte pour notre projet
solution
solution
Un constructeur, un formatage en chaîne de caractères pour affichage à l'écran et des opérateurs de comparaison :
User stories
Le projet nécessite de faire plein de choses. Pour vous aider à réaliser ce but, on va se placer des objectifs intermédiaires, sous la forme de user stories.
Je vous en propose une ci-après qui exhibe la capacité à créer un jeu de 32 cartes et à afficher les cartes à l'écran :
User Story
- Nom : "Voyance"
- Utilisateur : un voyant extralucide.
- Story : On veut pouvoir tirer les cartes
- Actions :
- créer un paquet de 32 cartes (sans joker)
- prendre au hasard 3 cartes du paquet
- afficher à l'écran les trois cartes, dans l'ordre où elles ont été tirées
Par rapport au jeu, il manque essentiellement la fonctionnalité permettant d'ordonner les cartes :
Créez une user story qui exhibe la fonctionnalité de pouvoir ordonner les cartes.
En affichant 10 cartes tirées avec remise dans l'ordre où elles ont été tirées, puis dans l'ordre croisant.
corrigé
corrigé
- Nom : "Ordonnancement"
- Utilisateur : un adepte de réussite
- Story : On veut pouvoir ranger les cartes par ordre croissant
- Actions :
- choisir 10 cartes au hasard (on peut avoir les mêmes cartes)
- afficher à l'écran les 10 cartes, dans l'ordre où elles ont été tirées
- afficher à l'écran les 10 cartes, dans l'ordre croissant
Créons les fichiers pour nos users stories, même si le code n'est pas encore clair. Par exemple pour la user story "voyance", on crée un fichier story_voyance.py
contenant :
# création d'un paquet de 32 cartes
# prendre au hasard 3 cartes du paquet
# afficher à l'écran les trois cartes, dans l'ordre où elles ont été tirées
On ajoutera petit à petit le code permettant d'implémenter la story, au fur et à mesure de l'avancement du projet.
Créez les deux fichiers de story.
Code
Créez les fichiers qui nous permettront de coder la carte :
carte.py
test_carte.py
Constructeur
Le constructeur d'une carte nécessite 2 paramètres : la valeur et la couleur.
En considérant que les deux paramètres couleur et valeur sont des chaînes de caractères, quelles sont les possibilités admissibles pour construire une carte ?
corrigé
corrigé
Par exemple, pour les valeurs :
"sept"
"huit"
"neuf"
"dix"
"valet"
"dame"
"roi"
"as"
Pour les couleurs :
"pique"
"cœur"
"carreau"
"trèfle"
Implémentez le constructeur de la classe Carte
et ses tests en supposant que l'utilisateur entre les bonnes valeurs de paramètres.
Affichage à l'écran
Pour permettre un affichage à l'écran plus convivial :
Codez la méthode __str__
d'une carte. Le code suivant doit pouvoir fonctionner :
>>> from carte import Carte
>>> ace_pique = Carte("as", "pique")
>>> print(ace_pique)
as de pique
Faites un test de cette méthode en testant la représentation sous la forme d'une chaîne de caractères d'une Carte
.
La représentation sous la forme d'une chaîne de caractères un objet x
est le résultat de str(x)
.
Lorsque l'on écrit print(ace_pique)
, python transforme l'objet en chaîne de caractères avec la commande str
qui elle-même cherche la méthode __str__
. Les trois instructions suivantes sont donc équivalentes :
print(ace_pique)
print(str(ace_pique))
print(ace_pique.__str__())
Représentation de l'objet
Vous verrez parfois une autre méthode de représentation d'un objet utilisant la commande repr()
. Cette fonction doit permettre de reconstruire l'objet si nécessaire.
Par exemple :
>>> from carte import Carte
>>> ace_pique = Carte("as", "pique")
>>> print(repr(ace_pique))
Carte('as', 'pique')
On utilise souvent repr()
pour du débogage (donc de l'affichage développeur), alors que str()
est utilisé pour de l'affichage utilisateur.
- on utilise
str(objet)
(crée avec la méthode__str__
) pour un affichage à l'écran. On transforme l'objet en un texte. - on utilise
repr(objet)
(crée avec la méthode__repr__
) pour représenter l'objet sous la forme d'une chaîne de caractères. On doit pouvoir reconstruire un objet identique avec la commandeeval
(eval(repr(objet))
doit rendre un objet similaire àobjet
.
Un petit tuto français pour expliciter les différences entre les deux représentations : https://www.youtube.com/watch?v=ejGYAnf_X24
Créez et testez la méthode __repr__
corrigé
corrigé
class Carte:
# ...
def __repr__(self):
return "Carte(" + repr(self.valeur) + ", " + repr(self.couleur) + ")"
# ...
Constantes de classes
Avant de pouvoir finir la partie de création d'une carte, il nous reste un problème à résoudre. Comment indiquer à l'utilisateur les possibilités de valeur et de couleurs ?
La solution communément utilisée pour cela est de créer des constantes :
Créez les constantes :
SEPT
,HUIT
,NEUF
,DIX
,VALET
,DAME
,ROI
,AS
PIQUE
,COEUR
,CARREAU
,TREFLE
En leur associant les chaînes de caractères adéquates.
Il ne faudra qu'utiliser ces constantes pour créer les cartes et ne plus directement utiliser des chaînes de caractères comme "sept"
qui sont des MAGIC NUMBERS.
Par exemple, on écrira Carte(AS, TREFLE)
plutôt que Carte("as", "trèfle)
Utilisez dans le code et les tests les constantes à la place des chaînes de caractères.
Vous n'êtes pas obligé d'importer toutes les constantes, une à une. En utilisant juste import carte
, vous pourrez utiliser carte.PIQUE
(constante PIQUE
dans l'espace de nom de carte
) directement par exemple.
Enfin, pour grouper ces constantes, vous pourrez :
Créer deux autres constantes, qui rassemblent les couleurs et les valeurs entre elles :
VALEURS = [SEPT, HUIT, NEUF, DIX, VALET, DAME, ROI, AS]
COULEURS = [TREFLE, CARREAU, COEUR, PIQUE]
Remarquez que l'on a rangé les différentes valeurs par ordre croissant de valeur et de couleur.
User story voyance
Vous avez tous les outils nécessaires pour créer la user story "voyance" :
Codez la user story "voyance".
Vous pourrez utiliser la fonction random.sample
pour tirer des cartes sans remise d'un paquet.
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__
Il suffit de coder ==
et <
pour obtenir toutes les comparaison.
Ceci devrait être suffisant pour la deuxième user story :
Codez la seconde user story.
Vous pourrez utiliser la fonction random.choices
pour tirer des cartes avec remise d'un paquet.
Jeu
Vous pouvez maintenant finir le projet en codant le jeu !
La règle du jeu est :
- mélangez un jeu de 32 cartes en deux pioches de 16 cartes, une pour chaque joueur
- chaque joueur dispose également d'une défausse, initialement vide
- N = 1
- chaque joueur dévoile la carte du dessus de leur pioche
- le joueur ayant la carte la plus élevée remporte la carte de l'adversaire et pose les deux cartes (la sienne et celle de son adversaire) dans sa défausse
- si un joueur n'a plus de cartes dans sa pioche, il mélange les cartes de sa défausse pour en faire un nouvelle pioche
- si un joueur n'a plus de carte dans sa pioche, il perd la partie
- N = N + 1
- si N est inférieur ou au nombre maximum de tour, retour en 4, sinon le jeu s'arrête.
Codez le jeu dans un fichier main.py