18 - Projet Mastermind

Présentation du jeu

Un plateau de Mastermind

Le Mastermind est un jeu de société pour deux joueurs dont le but est de trouver un code (couleur et position de 4 ou 5 pions) en 10 ou 12 coups. Dans la version originale, les 6 couleurs sont : jaune, bleu, rouge, vert, blanc, noir.

Il existe de nombreuses variantes suivant le nombre de couleurs, de rangées ou de trous et les couleurs utilisées pour les pions. Le jeu peut par exemple contenir 8 couleurs (rouge, jaune, bleu, orange, vert, blanc, violet, rose). Il y a aussi une version qui propose de découvrir un code de 5 couleurs en 12 rangées : le « Super » Mastermind. (Source : Wikipédia.)

Règles du jeu

Le jeu se joue à deux : un codificateur et un décodeur.

Le codificateur choisit une combinaison de 4 ou 5 pions à faire deviner et la pose bien cachée. Rien ne l’empêche d’en choisir plusieurs d’une même couleur.

Son adversaire, le décodeur, est chargé de déchiffrer ce code secret. Il doit le faire en 10 ou 12 coups au plus. Il place 4 ou 5 pions dans les trous de la première rangée immédiatement près de lui.

  • Si l’un des pions a la bonne couleur dans la bonne position, le codificateur l’indique en plaçant une fiche noire dans l’un des trous de marque, sur le côté droit correspondant du plateau.
  • Si l’un des pions correspond uniquement par sa couleur, mais n’est pas bien placé, le codificateur l’indique par une fiche blanche dans l’un des trous de marque.
  • S’il n’y a aucune correspondance, il ne marque rien.

Il y a plusieurs variantes : le codificateur peut indiquer globalement le nombre de bien placés et le nombre de mal placés, sans indiquer lesquels sont bien ou mal placés. Ou il peut indiquer pion par pion s’il est bien ou mal placé (le jeu est alors plus facile, évidemment).

La manche se termine lorsque le décodeur a trouvé et placé la bonne combinaison, ou lorsqu’il n’y a plus de lignes libres (le joueur a atteint le nombre maximum de propositions).

Organisation du travail

  1. Le devoir maison de préparation (manipulation de listes, copie de liste, génération aléatoire sans répétition) entraîne les briques dont le projet a besoin.
  2. Télécharger le fichier de départ mastermind_a_faire.py : il contient les constantes, les prototypes des fonctions à écrire et les tests qui permettent de vérifier chaque fonction au fur et à mesure.
  3. Écrire les fonctions dans l’ordre demandé ci-dessous, en décommentant les tests correspondants après chaque fonction.
  4. En cas de blocage, consulter les indications , puis, si cela ne suffit pas, la fiche d’aide .

Le programme demandé

Constantes globales

Nous allons rendre le jeu du Mastermind plus général avec un nombre de couleurs, une longueur de la combinaison secrète et un nombre maximal de combinaisons à proposer paramétrables. Nous utiliserons pour cela les constantes suivantes.

  • Une liste nommée COULEURS contenant les couleurs possibles des pions. Exemple : COULEURS = ["J", "B", "R", "V", "O", "N"] correspond à la version du jeu avec 6 couleurs (jaune, bleu, rouge, vert, orange, noir).
  • Un entier nommé NB_PIONS qui donne le nombre de pions d’une combinaison. Dans la version normale du Mastermind NB_PIONS = 4 et dans le super Mastermind NB_PIONS = 5.
  • Un entier nommé NB_MAX_ESSAIS pour le nombre maximal de combinaisons à proposer. Dans la version normale du Mastermind NB_MAX_ESSAIS = 10 et dans le super Mastermind NB_MAX_ESSAIS = 12.
  • Trois constantes pour représenter les marques de pion bien placé, mal placé ou absent : SYMBOLE_BIEN_PLACE = "#", SYMBOLE_MAL_PLACE = "X", SYMBOLE_ABSENT = "0".

Fonction qui génère aléatoirement une combinaison secrète

Écrire une fonction Python nommée genere_combinaison_secrete() qui va générer aléatoirement une combinaison secrète de longueur NB_PIONS en prenant les couleurs des pions dans la liste COULEURS sans répétitions. La fonction renverra la combinaison sous la forme d’une liste.

Exemple : après combinaison_secrete = genere_combinaison_secrete(), la variable combinaison_secrete peut contenir ["J", "R", "V", "O"].

Fonction qui permet au joueur de saisir une proposition

Écrire une fonction Python nommée saisir_combinaison() qui permet au joueur de saisir une proposition de longueur NB_PIONS en prenant les couleurs des pions dans la liste COULEURS. La fonction renverra la proposition sous la forme d’une liste. Vous pourrez faire saisir les couleurs une par une, ou tout d’un coup. Vous rédigerez la documentation de cette fonction.

Fonction qui transforme une proposition (liste) en chaîne de caractères

Écrire une fonction Python nommée combi_to_str(combinaison) qui permet de convertir la proposition (liste) en une chaîne de caractères. Nous pourrons l’utiliser pour faire afficher la proposition ou la combinaison secrète.

Exemple : combi_to_str(["J", "R", "B", "N"]) doit renvoyer "JRBN".

Fonction qui compte le nombre d’occurrences d’un élément dans une liste

C’est un petit utilitaire qui peut toujours servir : écrire une fonction Python nommée nb_occurrences(element, combinaison) qui compte le nombre de fois où element apparaît dans la combinaison.

Exemples : nb_occurrences("J", ["J", "R", "J", "N"]) doit renvoyer 2 ; nb_occurrences("V", ["J", "R", "J", "N"]) doit renvoyer 0.

Fonction qui trouve l’indice d’un élément dans une liste

Encore un petit utilitaire qui peut toujours servir : écrire une fonction Python nommée trouve(element, combinaison) qui renvoie l’indice (le premier) de l’élément element dans la liste combinaison s’il est présent, et -1 sinon. Vous rédigerez la documentation de cette fonction.

Exemples : trouve("J", ["J", "R", "J", "N"]) doit renvoyer 0 ; trouve("V", ["J", "R", "J", "N"]) doit renvoyer -1.

Fonction qui analyse la proposition et la compare à la combinaison secrète

Écrire une fonction Python nommée evalue_proposition(proposition, secret) qui a pour paramètres une liste proposition qui contient la proposition d’un joueur et une liste secret qui contient la combinaison secrète. Cette fonction renverra une liste liste_reponse construite de manière à marquer les pions bien placés, mal placés et absents.

Exemples :

  • evalue_proposition(["J", "R", "B", "N"], ["J", "R", "V", "O"]) renverra la liste ["#", "#", "0", "0"] car « J » et « R » sont bien placés ;
  • evalue_proposition(["J", "O", "R", "N"], ["J", "R", "V", "O"]) renverra la liste ["#", "X", "X", "0"] car « J » est bien placé, et « O » et « R » sont mal placés.

Remarque. Pour éviter de recompter deux fois les mêmes pions (par exemple en bien placé puis en mal placé, ou lorsqu’il y a des répétitions, dans la proposition ou dans la combinaison), on pourra faire une copie de la proposition et une copie de la combinaison secrète et modifier ces copies au fur et à mesure du comptage pour éliminer les pions déjà comptés.

Fonction qui permet de jouer une manche entière de Mastermind

Écrire une fonction Python nommée manche_de_mastermind() qui permet de jouer une manche de Mastermind. L’ordinateur génère une combinaison secrète, puis, à chaque tour, demande à l’utilisateur de saisir une proposition, l’analyse et répond, jusqu’à ce que la manche soit terminée pour l’une des deux raisons possibles : le joueur a trouvé la combinaison, ou il a perdu car il a atteint son nombre maximum d’essais.

La fonction renverra le nombre d’essais tentés, cela pourra être utilisé en cas de comptabilisation des scores.

Approfondissements possibles

  • Sécuriser la fonction saisir_combinaison() : s’assurer qu’il y a le bon nombre de couleurs, que chaque élément est bien une couleur possible, etc.
  • Autoriser les répétitions dans la combinaison secrète. Pour pouvoir choisir l’une ou l’autre option, on peut définir une variable globale AVEC_REPETITION = True et la modifier au besoin. Modifier la fonction genere_combinaison_secrete() pour qu’elle prenne en compte cette variable globale, et s’assurer que evalue_proposition() supporte la possibilité d’une répétition dans la combinaison secrète.
  • Offrir deux modes pour le résultat de l’évaluation d’une proposition : un mode où l’on annonce globalement le nombre de bien placés et de mal placés sans préciser lesquels, et un mode où l’on précise pour chaque pion comme on vient de le faire. On peut définir une variable globale COMPTAGE_GLOBAL ; la fonction evalue_proposition() peut rester inchangée, mais il faudra modifier manche_de_mastermind() pour qu’elle affiche la réponse en fonction du mode de jeu.
  • Prévoir la possibilité d’enchaîner plusieurs manches et de comptabiliser les scores.
  • Écrire une fonction de menu qui permet de choisir le niveau de difficulté, et ainsi modifier les valeurs des constantes globales (COULEURS, NB_PIONS, NB_MAX_ESSAIS, et éventuellement COMPTAGE_GLOBAL et AVEC_REPETITION).
  • Si vraiment vous avez tout fait, envisager une aide au jeu par l’ordinateur. Il s’agit alors de déterminer toutes les combinaisons possibles, puis à chaque tour de jeu, de ne garder que celles qui donneraient bien la réponse obtenue pour la dernière proposition. On peut alors aider le joueur en lui affichant toutes les possibilités, ou en lui en conseillant une (au hasard) parmi les possibles.