Chifoumi
Chifoumi est un jeu de hasard pour deux joueurs et qui se joue avec les mains. Les 2 joueurs présentent en même temps leur main formant un signe particulier, parmi 3 éléments (pierre – feuille – ciseaux). Chaque coup bat un autre coup, fait match nul contre le deuxième (son homologue) et est battu par le troisième.
Par exemple : la pierre émousse les ciseaux, les ciseaux coupent la feuille, la feuille enveloppe la pierre …
Nous allons réaliser un programme à partir d’une variante récente de ce jeu :
. Les règles classiques s’appliquent, mais il faut ajouter que le lézard mange le papier, empoisonne Spock, est écrasé par la pierre et est décapité par les ciseaux. Spock vaporise la pierre, casse les ciseaux, et est discrédité par le papier.Cette variante augmente le nombre de combinaisons de 3 à 10, et est censée réduire le nombre d’égalités entre deux joueurs qui se connaissent.
Structure des données
Les relations entre les différents symboles peuvent être modélisées par le diagramme de résolution ci-contre.
En algorithmique, il s’agit d’un graphe orienté, noté par le couple \(G=(V,E)\) comprenant :
- \(V\) un ensemble de sommets (aussi appelés nœuds ou points) ;
- \(E\) un ensemble d’arêtes orientées (aussi appelées flèches), qui sont des paires de sommets (c.-à-d. qu’une arête est associée à deux sommets distincts).
On dit que deux sommets sont adjacents s’ils sont reliés par une arête.
En informatique on peut représenter ce type de graphe par un tableau (appelé matrice d’adjacence) où les sommets sont représentés en tête des lignes et des colonnes, et les arêtes sont placées à l’intersection des sommets adjacents :
Par exemple, la matrice d’adjacence du graphe (non orienté) ci-contre est un tableau où chaque arête entre 2 sommets est indiquée par un « 1 », les autres cases étant à « 0 » :
1 2 3 4 5 6 1 0 1 0 0 1 0 2 1 0 1 0 1 0 3 0 1 0 1 0 0 4 0 0 1 0 1 1 5 1 1 0 1 0 0 6 0 0 0 1 0 0
Dans l’exemple précédent, la matrice est symétrique (axe de symétrie diagonal), mais dans le cas du chifoumi, les arêtes sont orientées, ce qui signifie que les « 1 » de la matrice n’auront pas de symétrique.
Pour simplifier la notation, on attribut à chaque symbole une lettre :
- A : pierre
- B : papier
- C : ciseaux
- D : lézard
- E : Spock
On décide de représenter la supériorité des symboles du haut vers le bas du tableau : orientation de lecture de la colonne vers la ligne.
Par exemple « la pierre émousse les ciseaux » sera représenté par un « 1 » au croisement de la colonne « A » et de la ligne « C ».
F
).A | B | C | D | E | |
A | |||||
B | |||||
C | 1 | ||||
D | |||||
E |
Afin de pouvoir lors du jeu afficher des phrases telles que « Spock vaporise la pierre« , il convient de structurer les constantes de la manière suivante :
- les noms des différents éléments seront stockés dans une liste
S
.
exemple : « la pierre » - les verbes exprimant la supériorité des uns sur les autres seront quant à eux stockés dans une liste
V
.
exemple : « discrédite » - Les « 1 » de la matrice d’adjacence seront remplacés par les indices de ces verbes dans la liste qui les contient
(il faudra songer à gérer les « 0 » qui ne sont pas sensés représenter un indice)
Programme
Écrire une fonction plusFortQue(s1, s2)
qui demande deux paramètres de type entier représentant les indices des éléments dans la liste S
, et qui renvoie :
True
sis1
est strictement supérieur às2
False
sis2
est strictement supérieur às1
None
s’ils sont égaux
resultat(s1, s2)
qui renvoie le résultat d’un « coup » sous la forme d’une phrase telle que "
Spock vaporise la pierre
"
(on part du principe que s1
est plus fort que s2
).
Pour mémoriser le joueur en cours ainsi que les scores, nous utiliserons deux variables globales :
j = 0 # ou 1 score = [0, 0]
afficherScore()
qui affiche le score sous la forme "Joueur 1 : 5 - Joueur 2 : 2"
.
analyse(s1, s2)
qui analyse le « coup » qui vient d’être joué, s1
étant l’élément choisi par le joueur 1 et s2
celui choisi par le joueur 2. analyse()
affiche le résultat du « coup » et se charge également de modifier les scores (s’il y a lieu) puis de les afficher.
changerJoueur()
qui permet de modifier la variable globale j
.
convertir(key)
qui convertit un caractère ('A', 'B', 'C', 'D', 'E')
en nombre (0, 1, 2, 3, 4)
.
acquerir()
qui interroge un joueur et renvoie le nombre correspondant à l’élément qu’il a choisi. acquerir()
doit afficher l’invite à taper une lettre pour le joueur en cours. Seules les touches ('A', 'B', 'C', 'D', 'E')
sont autorisées, la fonction ne se termine pas tant que le joueur n’a pas tapé une de ces touches !
Pour acquérir les consignes des joueurs, nous allons utiliser la bibliothèque keyboard. Elle ne fait pas partie de la distribution Python, il faut donc l’installer. L’opération est très simple :
Depuis le sous dossier /Script du dossier contenant Python, ou bien depuis pyzo (et certains autres IDE) :
pip install keyboard
La documentation complète est ici : https://github.com/boppreh/keyboard#api et des exemples se trouvent là.
Mais nous n’utiliserons que la fonction keyboard.read_key()
de la manière suivante :
keyboard.read_key(suppress=True) time.sleep(0.2) # permet d'éviter de détecter plusieurs appuis sur la touche
Grâce à cette fonction, le programme s’interrompt jusqu’à ce que l’utilisateur appuie sur une touche, puis la valeur de la touche est renvoyée.
Nous adopterons le code suivant :
- Touches A à E : les éléments du jeu
- Touche Echap : termine le jeu et annonce le score final.
Version avec interface graphique