Des dés !
L’objectif de cette activité est de réaliser, par toutes petites étapes un programme de jeu de dés …
Simples classes
Remarque : la relation entre les classes
Jeu
etDe
peut se lire : « Chaque objet de typeJeu
contient au moins 1 objet de typeDe
»Cela implique qu’il faudra définir dans la définition de la classe
Jeu
un attributdes
, de type liste d’objets de typeDe
.Cette définition n’apparait pas dans le cadre de la classe !
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
.
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.
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
__repr__
aux deux classes De
et Jeu
, afin d’afficher la valeur donnée par un lancer grâce aux caractères unicode 0x267F
et suivants :Par exemple pour afficher la valeur 5 d’un dé de_1
, l’instruction print(de_1)
doit afficher ⚄ .
Le dé dans tous ses états
Lors du déroulement d’une partie, 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
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 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
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
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).
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)
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éfinies, il est possible de comparer deux objets en utilisant les opérateurs habituels :
par exemple : objet1.__lt__(objet2) est équivalent à objet1 < objet2 !
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.
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.
Déroulement de la partie