pyTkMasterMind

Analyse fonctionnelle

Objectif principal

  • Le programme implémente un Mastermind à 2 joueurs (codeur et décodeur) avec plusieurs parties.
  • Le codeur choisit une combinaison secrète. Le décodeur essaie de la deviner en proposant des combinaisons.
  • Le système indique à chaque proposition combien de pions sont bien placés et combien sont présents mais mal placés.

Structure de données utilisées

  • matjeu : matrice 2D où chaque ligne représente un essai, et la dernière ligne la combinaison secrète.
  • matreponse : matrice 2D stockant les résultats (pions noirs et blancs) pour chaque essai.
  • Des variables globales pour suivre le nombre de colonnes (pions), lignes (essais), joueurs, scores, rôle codeur/décodeur, etc.
Exemple des matrices en cours de partie
                            

matjeu (11 × 4)

0521
1052
2105
3405
2134
201-1
-1-1-1-1
-1-1-1-1
-1-1-1-1
-1-1-1-1
-1-1-1-1
2315

matreponse (10 × 4)

111-1
111-1
001-1
01-1-1
011-1
-1-1-1-1
-1-1-1-1
-1-1-1-1
-1-1-1-1
-1-1-1-1
-1-1-1-1
Image 1

Aspects techniques et conception

  • L'interface graphique Tkinter est indépendante de la logique fonctionnelle.
  • Tkinter ne permet pas de passer des arguments directement aux fonctions de rappel des boutons.
  • L’usage des variables globales est donc fréquent pour contourner le problème et éviter l'usage multiple de fonctions lambda.

Fonctions importantes

feedback(matJ, matR)

Afficher le code de la fonction feedback()

def feedback(matJ, matR):
    """
    Fonction permettant de compter les pions bien placé, de compter les pions dont la couleur est bonne mais mal placés, puis d'afficher les pions (respectivement noirs et blancs)
    Parameters
    ----------
    matJ : int[nblignes+1][nbcolonnes]
    matR : int[nblignes][nbcolonnes]
    ----------
   Returns bool : permet de savoir si la manche est terminée (True) ou non (False)
    """
    global nbcolonnes
    global nblignes
    global ligne
    global pas
    global rmarqueur
    global dictcouleursreponse
    global canvasreponses
    
    tupSecret=matJ[nblignes]  # tupSecret est la dernière ligne de la matrice de jeu
    ListeReponse=matJ[ligne]  # ListeReponse est la ligne en cours

    black = sum(s==g for s,g in zip(tupSecret,ListeReponse)) # Nombre de pions bien placés
    white = sum(min(tupSecret.count(c), ListeReponse.count(c)) for c in set(ListeReponse)) - black # Nombre de pions corrects mais mal placés
    
    # On remplit la matrice réponse avec les blacks et les white
    for i in range(black):
        matR[ligne][i]=0   
    for j in range(white):
        matR[ligne][black+j]=1
        
    # On dessine les pions
    for i in range(nbcolonnes):
        if matR[ligne][i]!=-1:
            xcercle=pas+rmarqueur+i%(nbcolonnes//2++nbcolonnes%2)*(pas+2*rmarqueur)
            ycercle=pas+rmarqueur+i//(nbcolonnes//2+nbcolonnes%2)*(pas+2*rmarqueur)
            cercle(canvasreponses[ligne],xcercle,ycercle,rmarqueur,dictcouleursreponse[matR[ligne][i]])
    
    if black==nbcolonnes :
        return True
    return False
                                
  • Cœur du jeu : compare la proposition du joueur matjeu[ligne] avec la combinaison secrète matjeu[nblignes].
  • Cette fonction :
    • calcule le nombre de pions bien placés (noirs),
    • calcule le nombre de pions présents mais mal placés (blancs),
    • met à jour la matrice réponse matR pour stocker les résultats,
    • Indique si la combinaison est correcte (victoire).

choisircouleur(matJ, numerocouleur, canvasL, bouton_validerligne)

  • Permet au joueur de choisir une couleur,
  • Met à jour la matrice et l'affichage,
  • Gère le bouton valider.

bouton_valider()

  • Gère la validation d'une proposition,
  • Gère la logique de victoire/défaite et le score,
  • Gère le changement de rôle avant la nouvelle partie.

initialiser_fenetre_principale(canvasL, canvasR)

  • Réinitialise le plateau et prépare la nouvelle partie, inverse les rôles.

Décomposition de l'interface graphique

Nous avons décidé d'utiliser tkinter pour créer l'interface de jeu.

import tkinter as tk

Le jeu apparaît dans une fenêtre qui s'appelle par défaut root, et qu'on affiche avec la commande root.mainloop()

import tkinter as tk
root = tk.Tk()
root.mainloop()

Voici un aperçu de la fenêtre

fenêtre

L'espace jeu et l'espace réponse sont deux frames distinctes.

espacecommande = tk.LabelFrame(root,text="Espace commande",relief='groove')
espaceaffichage=tk.Frame(root, bd=4, relief="raised", padx=pas, pady=pas)

Chacun de ces espaces contient un nombre de canvas égal au nombre de tentatives que le décodeur a pour trouver le code secret, plus une ligne pour que le codeur rentre son code, qui sera caché par la suite pour le décodeur.

for i in range(nblignes+1):
  canvasL[i] = tk.Canvas(espacejeu, width=pas+(2*rpion+pas)*nbcolonnes, height=hligne,bg=dictcouleurs[-1])

Les espaces jeu et réponses sont d'abord remplis de petit cercles grisés modélisant les trous vides.
Lorsqu'un joueur place une bille, elle est modélisée par nouveau cercle de couleur, plus gros.
C'est pareil pour l'espace réponse, dont les objets dessinés sont juste plus petits.

espaces jeu et réponses

L'espace affichage est une frame.

espaceaffichage=tk.Frame(root, bd=4, relief="raised", padx=5, pady=5)
espaceaffichage.pack(side="left",padx=0, pady=10, fill="y", expand=0.5)

Cet espace contient diverses informations sur la partie en cours : scores, identité du codeur et du décoeur, etc.


numpartie=1
nbparties=2
sv_nbparties = tk.StringVar()
sv_nbparties.set(f"Partie {numpartie} sur {nbparties}")
labelnbparties = tk.Label(espaceaffichage, textvariable=sv_nbparties)
labelnbparties.pack(side="top")
espace affichage

L'espace commande est une frame.

espacecommande = tk.LabelFrame(root,text="Espace commande",relief='groove')
espacecommande.pack(side="bottom",padx=10,pady=10,fill="x")

Cet espace contient les boutons permettant aux joueurs de modifier l'espace jeu

bouton_validerligne = tk.Button(espacecommande,text="Valider ligne", command=bouton_valider)
bouton_validerligne.pack(side="left")
bouton_validerligne.config(state="disabled")
espace commande