Des dés !

L’objectif de cette activité est de réaliser, par toutes petites étapes un programme de jeu de dés …

Vous y apprendrez :

  • à définir des classe à partir de diagrammes UML,
  • définir des constructeurs avec différents usages des arguments,
  • employer des mutateurs, des accesseurs et des attributs privés,
  • utiliser des arguments de tailles variables,

 

Simples classes

Implémenter en Python les deux classes décrites par le diagramme ci-dessous.
Les dés (classe De) du jeu (classe Jeu) doivent être instanciés lors la construction du jeu.

Exemple : Jeu(5, 6) doit instancier (et mémoriser dans un attribut des) 5 dés de 6 faces

Remarque : la relation entre les classes Jeu et De peut se lire : « Chaque objet de type Jeu contient au moins 1 objet de type De »

Cela implique qu’il faudra définir dans la définition de la classe Jeu un attribut des, de type liste d’objets de type De.

Cette définition apparaît pas dans le cadre de la classe, mais c’est redondant …

 

Ajouter une méthode lancer à la classe De. Cette méthode doit retourner une valeur aléatoire comprise entre 1 et le nombre de faces du dé.
Il est conseillé d’utiliser la fonction randint du module random.

 

Ajouter à présent une méthode lancer à la classe Jeu. Cette méthode doit lancer tous les dés et retourner la liste des valeurs de chaque dé.

 

Instancier un jeu de 3 dés et afficher le résultat d’un lancer !

 

Mémorisation des valeurs

On souhaite à présent que les valeurs des dés du jeu restent mémorisées au sein même des objets, un peu comme si les dés du jeu étaient posés sur le plateau de jeu.

Les méthodes lancer() deviennent de type « procédure » (elles ne renvoient rien !) mais la valeur de chaque dé est mémorisé au sein de chacun des objets dé, dans un nouvel attribut valeur (un entier valant de 1 à nbr_faces).

Implémenter cette nouvelle structure en Python.
 

 

Dans certaines règles de jeu de dés, il est possible de faire plusieurs lancers, et parfois même de ne pas lancer tous les dés.

Modifier la méthode Jeu.lancer en ajoutant un argument à mot clé exclure de type liste contenant les indices (dans la liste des dés du jeu) des dés à ne pas lancer.

 

 

Affichage

Ajouter la méthode spéciale __repr__ à la classes De, afin d’afficher la valeur donnée par un lancer.
Utiliser le caractère unicode 0x2680 et les suivants, en passant par la fonction chr.

Par exemple pour afficher la valeur 5 d’un dé de_1, l’instruction print(de_1) doit afficher .

 

Faire de même pour la classe Jeu.

 

 

Le dé dans tous ses états

Lors du déroulement d’une partie (selon les règles du jeu), un dé peut prendre plusieurs états :

  • pas encore lancé (dans la main d’un joueur)
  • posé sur le plateau (avec une de ses faces visible)
  • bloqué sur le plateau (avec une de ses faces visible) : il ne peut pas être relancé

 

Il faut convenir d’un « code » pour qualifier ces différents états. On peut, par exemple utiliser un seul attribut valeur de la manière suivante :

  • pas encore lancé : valeur = 0
  • posé sur le plateau : valeur = 1 à nbr_faces
  • bloqué sur le plateau : valeur = -1 à -nbr_faces(nombres négatifs)

Afin de pouvoir facilement changer cette manière de coder l’état d’un dé, et pour éviter d’avoir à modifier de nombreuses lignes de code, il est préférable de rendre l’attribut valeur « privé » et de passer par des méthodes « publiques » pour obtenir l’état du dé :

Il faut bien entendu :

  • interdire de lancer un dé bloqué (et donc interdire de modifier sa valeur avec .set_valeur())
  • ne pas pouvoir bloquer un dé non encore posé

Afin de permettre aux objets qui utilisent des dés de savoir si une action a eu un effet (blocage, lancer, …) on décide de renvoyer un indicateur de « réussite » sous la forme d’un booléen :

  • True : l’action a produit un effet
  • False : l’action n’a pas eu d’effet

 

Implémenter cette nouvelle structure de la classe De.

 

Le jeu de dés

A présent, il faut permettre au programme de manipuler les dés au sein du jeu qui les contient. On enrichi donc la structure de la classe Jeu :

Attention, les méthodes d’action (lancer, bloquer, …) doivent, à l’instar de celles des objets De, renvoyer un indicateur de réussite (voir plus haut).

Remarque : le symbole * devant les paramètres des méthodes permet de pouvoir passer les arguments comme plusieurs valeurs et récupérer un tuple dans la méthode.

exemple si on appelle lancer(1,2), à l’intérieur de la méthode, num_des sera le tuple (1,2).

 

Implémenter (et tester !) cette nouvelle classe Jeu.

 

 

 

Analyse des résultats

On désire maintenant afficher le résultat d’une combinaison obtenue, après un ou plusieurs lancer, en accord avec les règles d’un jeu, par exemple celui du 421.

On décide de donner le résultat d’un jeu de dés grâce à deux valeurs, l’objectif étant de pouvoir classer toutes les combinaisons de manière absolue (pas de combinaisons ex-aequo) :

  • le nombre de points : de 1 à 8 dans le jeu de 421

exemple : 114 = (4 points) > 333 (3points)

  • la valeur de la combinaison :

exemple : 641 (1 point) > 533 (1 point)

 

Ajouter à la classe Jeu une méthode evaluer renvoyant le nombre de points et la valeur de la combinaison du jeu.

 

Comparaison des combinaisons

En Python certains noms de méthode sont réservés à des usages particulier (nous avons vu le cas de la méthode __repr__), mais il en existe de nombreuses autres :

  • objet1.__lt__(objet2) renvoie True si objet1 est strictement inférieur (lt = less than) à objet2
  • objet1.__eq__(objet2) renvoie True si objet1 est égal (eq = equal) à objet2

Ces méthodes doivent impérativement renvoyer un booléen. Charge au programmeur de définir ce qui fait qu’un objet est plus petit, plus grand ou égal à un autre …

Une fois définis, il est possible de comparer deux objets en utilisant les opérateurs habituels :

par exemple : objet1.__lt__(objet2) est équivalent à objet1 < objet2  !

 

Rajouter les deux méthodes __lt__ et __eq__ à la classe Jeu.
Tester le fonctionnement en rajoutant le code suivant au script :
j1 = Jeu()
j2 = Jeu()
    
print(j1.lancer(0,1,2))
print(j2.lancer(0,1,2))
    
if j1 < j2:
    print(j1, "<", j2)
elif j1 == j2:
    print(j2, "=", j1)
else:
    print(j2, "<", j1)

 

 

 

Les joueurs

Maintenant que l’on sait classer les combinaisons obtenues, on peut envisager d’organiser une partie avec plusieurs joueurs.

Pour cela, définir une nouvelle classe Joueur, qui pourra, en plus de caractéristiques générales (nom, …), posséder un attribut score.

 

Et la partie de dés !

Il faut à présent définir la classe qui gérera la partie de dés.

Cette classe devra donc posséder:

  • un jeu de dés
  • des joueurs (2 ou plus)

C’est cette classe qui définira les règles du jeu (il faudra donc s’occuper de la méthode Jeu.evaluer qui n’est pas à la bonne place.

Implémenter cette nouvelle structure.

 

 

 

Déroulement de la partie

 

 

Vous aimerez aussi...

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *