Projet composition d'objets : dés

Dans le premier projets dés, vous avez codé des classes toutes seules. Dans cette parties on va coder plusieurs classes enchevêtrées.

Pour les besoins de ce projet, nous allons présupposer que vous avez une classe qui fonctionne. La version minimale que nous allons utiliser ici est disponible ci-après. Mais ne vous sentez pas obliger de l'utiliser.

une implémentation de la classe

fichier dé.py :

import random

MIN_VALEUR = 1
MAX_VALEUR = 6


class Dé:
    def __init__(self, position=1):
        self._position = 1  # init
        self.position = position  # utilisation du mutateur

    def lancer(self):
        self.position = random.randrange(MIN_VALEUR, MAX_VALEUR + 1)

        return self

fichier test_dé.py :

fromimport, MIN_VALEUR, MAX_VALEUR

def test_init():
    assert type(()) ==def test_position():
    assert().position == 1
    assert(position=3).position == 3

def test_lancer():
    assert MIN_VALEUR <=().lancer().position <= MAX_VALEUR

Il va nous falloir manipuler 5 dés ensemble pour réaliser le but de notre projet :

But du projet

Jouer au poker d'as.

Nous n'atteindrons pas ce but à la fin du projet, mais libre à vous de le continuer et de le finir.

5 dés

Méthode naïve pour manipuler 5 dés : la liste de dés.

Pour illustrer cette étape et progresser dans notre projet de jeu, faisons une petite user story :

User Story

  • Nom : "jets de dés"
  • Utilisateur : un joueur compulsif
  • Story : On veut pouvoir lancer des dés et voir le résultat
  • Actions :
    1. créer une liste
    2. créer 5 dés que l'on ajoute un à un à la liste
    3. lancer les 5 dés
    4. afficher les valeurs des dés de la liste

Créez la user story dans le fichier story_jets.py

Composition

L'utilisation d'une liste permet de groper les 5 dés, mais il faut toujours les lancer individuellement. Cela pourrait être pratique de lancer automatiquement tous les dés.

Classe TapisVert

On aimerait avoir une structure, nommée TapisVert, qui :

  1. Proposez une modélisation UML de cette classe, montrez la relation qu'elle entretien avec la classe .
  2. modifier la user story "jets de dés" pour qu'elle utilise cette classe

corrigé

tapis vert

story_jets.py :

fromimport TapisVert

tapis_vert = TapisVert()

tapis_vert.lancer()

forin tapis_vert.dés:
    print(.position)

Avant de commencer à coder, comprenez comment il est possible que la méthode TapisVert.lancer() peut utiliser la méthode Dé.lancer() alors que les deux méthodes ont le même nom.

Maintenant que vous voyez comment faire codez là :

Ajoutez le code de la classe TapisVert dans le fichier dé.py.

Ajoutez les test de cette nouvelle classe au fichier test_dé.py. Vous pourrez par exemple tester :

  • qu'après la création d'un objet TapisVert on dispose bien de 5 dés positionnés sur 1.
  • qu'après avoir lancé les dés, leurs positions sont toujours cohérentes avec le nombre de faces.
  • que TapisVert donne bien ses dés et non une copie de ceux-ci. Pour réaliser ceci vous pourrez implémenter le test suivant :
    1. demander les dés d'un objet de type TapisVert
    2. modifier la position d'un dé
    3. redemander les dés de l'objet de type TapisVert et vérifier que la position du dé est bien celle modifiée

Affichage

Afin de pouvoir coder plus rapidement nos story, il faut une méthode de représentation de nos objets.

Commençons par le :

Créez une méthode Dé.__str__ qui permettent d'écrire :

>>> fromimport>>> d =()
>>> d.position = 4
>>> print(d)>>> 

Vous pourrez utilisez les caractères : "⚀", "⚁", "⚂", "⚃", "⚄" et "⚅" pour vos représentations.

On peut maintenant utiliser Dé.__str__ pour que TapisVert.__str__ soit facile à coder :

Créez une méthode TapisVert.__str__ qui permettent d'écrire :

>>> fromimport TapisVert
>>> tapis_vert = TapisVert()
>>> print(tapis_vert)---->>> tapis_vert.lancer()
>>> print(tapis_vert)---->>> 

corrigé

On peut utiliser deux trucs. Le premier est de construire une liste avec les représentations sous la forme d'une chaîne de caractères des dés. Par exemple :

>>> fromimport TapisVert
>>> tapis_vert = TapisVert()
>>>[str(x) for x in tapis_vert.dés]
['⚀', '⚀', '⚀', '⚀', '⚀']

Puis utiliser la méthode str.join de python qui est super utile pour concaténer des listes de chaînes de caractères :

>>> l = ["coucou", "les", "amis"]
>>> "*".join(l)
'coucou*les*amis'

Ces deux astuces nous permettent d'écrire le code :

class TapisVert:
    # ...

    def __str__(self):
        return " - ".join([str(x) for x in self.dés])

    # ...

Reconnaissance

Pour jouer au poker d'as, il nous faudra reconnaître des formes de jets de dés (comme les paires, ou encore les full). Créons une user story pour coder cette fonctionnalité :

User Story

  • Nom : "formes de jets"
  • Utilisateur : un joueur compulsif
  • Story : On veut pouvoir savoir quelles formes de dés sont présentes
  • Actions :
    1. jeter 5 dés
    2. vérifier s'il y a une paire, un brelan ou un carré
    3. recommencer en 1

Créez la story dans le fichier story-formes-dés.py.

Pour cela, l'utilisateur pourra appuyer sur la entrée pour lancer les dés d'un objet de type TapisVert, afficher les 5 dés et indiquer s'il y a une paire, un brelan ou un carré avec des méthodes TapisVert.possède_paire(), TapisVert.possède_brelan(), et TapisVert.possède_carré() qui rendent des booléens.

Et maintenant le code des différentes méthodes à implémenter :

Ajoutez dans TapisVert les méthodes nécessaires et testez-les en simulant des lancez ayant une forme particulière.

Pour coder cela de façon simple, vous pourrez coder deux méthodes supports :

  • une méthode qui rend une liste $L$ de taille 7 telle que $L[i]$ donne le nombre de dés ayant la position $i$ ($1 \leq i \leq 6$)
  • une méthode qui prend en paramètre un nombre $n$ et qui rend True s'il existe au moins $n$ dés ayant la même position. Ceci permettra de coder de la même manières les différentes fonctions demandées.