Author: Aël D.

Tutoriels

Utiliser Tkinter pour donner des interfaces à vos scripts…

Dans ce tutoriel, vous allez apprendre pas à pas les bases de tkinter en Python : créer une fenêtre, y ajouter du texte, des boutons, et autres, mais aussi l’organiser à l’aide de boites et de grilles.

Qu’est ce que Tkinter ?

Tkinter (ou ToolKit Interface) est une library Python permettant de donner une interface graphique à vos scripts Python et ainsi les rendre plus agréables à utiliser, qu’ils s’agisse de simulateurs, de programmes de calcul ou de mini jeux textuels par exemple.

Il est important de noter que Tkinter n’est pas disponible sur la Numworks ou autre calculatrice utilisant Python, mais est par contre utilisable sous Windows, Linux macOS et même sur Android en utilisant Pydroid

Installer Tkinter

Tkinter est inclus avec Python 3 sous Windows, Linux ou macOS, vous n’aurez donc normalement pas à vous soucier de devoir l’installer en plus.

Au début de votre script, vous aurez simplement à taper les lignes suivantes afin d’importer la bibliothèque tkinter :

from tkinter import *
import tkinter as tk

Maintenant que l’on a spécifié que l’on allait utiliser cette bibliothèque, on peut commencer à mettre en place notre fenêtre.

Création de la fenêtre

C’est dans cette fenêtre que tous les éléments vont apparaître.

Pour commencer, nous allons créer une fenêtre. Pour cela une ligne suffit:

fenetre = Tk()

Lorsque l’on exécute le script rien ne se passe: il faut spécifier au script que l’on veut faire apparaître la fenêtre. Pour cela, entrer la ligne suivante à la fin de votre script.

fenetre.mainloop()

Il est important que cette ligne reste la dernière de votre programme, car tout ce qui sera écrit après cette ligne n’apparaîtra pas dans la fenêtre

On obtient alors normalement le résultat suivant :

Maintenant que l’on a créé cette fenêtre, on peut la personnaliser: lui donner un nom, des dimensions, une couleur de fond etc…

fenetre.title("Ma permière fenêtre Tkinter!")
fenetre.geometry("1080x720")
fenetre.config(bg="#d1fdff")

Les dimensions seront écrites sous la forme "largeurxhauteur"

La couleur peut être spécifiée de deux manières différentes:

  • Avec le nom de la couleur en anglais (ex. bg="grey")
  • En utilisant sa notation en héxadécimal, comme dans l’exemple donné ci-dessus. Il est possible de trouver des couleurs en héxadécimal à l’aide de cet outil

On obtient alors ceci :

Il est également possible de personnaliser l’icône de la fenêtre.

Pour cela, il vous faudra une image au format .ico . On peut convertir des images au format .png en .ico à l’aide d’un convertisseur en ligne

Une fois que vous avez votre icône, placez la dans le même dossier que votre script, et entrez la ligne suivante (en remplaçant "logo.ico" par "lenomdevotreicone.ico")

fenetre.iconbitmap("logo.ico")

Il est aussi possible de définir la taille minimale de la fenêtre:

fenetre.minsize(500,500)

On a donc appris à personnaliser notre fenêtre tkinter… mais elle reste tout de même bien vide. Nous allons donc voir comment ajouter des éléments à cette fenêtre.

Ajouter du texte

Pour ajouter du texte sur notre interface, on va utiliser une instance nommée Label

titre = Label(fenetre, text="Voici un exemple de Label en police consolas et en taille 20", font=("Consolas",20), bg="#d1fdff", fg="black")
soustitre = Label(fenetre, text="Voici un exemple de Label en police Helvetica et en taille 15", font=("Helvetica",15), bg="#d1fdff", fg="black")

On remarque que l’on peut personnaliser différents aspects du Label:

  • La boîte dans laquelle il se trouve (cette notion sera abordée un peu plus loin)
  • Le texte qu’il renferme ( text )
  • Sa police et taille d’écriture ( font )
  • Son arrière plan ( bg pour background )
  • Sa couleur de police ( fg pour foreground )

Si l’on exécute le script, on s’aperçoit que le texte ne s’affiche pas: là aussi, il faut spécifier qu’il faut l’afficher à l’aide de l’instruction .pack(). Il sera nécessaire d’appeler tout nouvel élément que l’on créé de cette manière.

titre.pack()
soustitre.pack()

Les différents éléments que vous allez incorporer à votre fenêtre apparaîtront dans l’ordre dans lequel vous allez les appeler à l’aide de .pack() , ici, titre sera donc au dessus de soustitre.

Il est possible de donner une marge à notre texte en utilisant pady et padx. Par exemple, l’instruction suivante donne une marge de 45 des deux côtés en hauteur

titre.pack(pady=45)

On peut aussi spécifier au texte de prendre toute la place possible en utilisant expand comme ceci:

titre.pack(expand=YES)

Ajouter des boutons

Maintenant que l’on sait faire apparaître du texte sur notre fenêtre, on va s’intéresser aux boutons. Leur mise en place est très similaire à celle des Labels. Cependant, on peut leur ajouter d’autres arguments

  • command qui spécifiera la fonction à éxécuter en cas de clic sur le bouton
  • width et height qui permettent de modifier respectivement sa largeur et sa longueur. Si ils ne sont pas spécifiés, la taille du bouton sera celle nécessaire pour que son texte s’affiche
nb_clicks=0
def compteur():
    global nb_clicks
    nb_clicks += 1
    print(nb_clicks)

bouton1 = Button(fenetre, text="Je suis un bouton", font=("Consolas",15), bg="white", fg="black", command=compteur, width=10, height=3)

Ici, on a donc créé un Bouton d’une largeur de 10 et d’un hauteur de 3 qui incrémente un compteur à chaque clic et qui donne la valeur du compteur dans la console

Mais ce que l’on chercherait à faire, ce serait de faire apparaître le texte directement dans la fenêtre.

On créé alors un nouveau Label qui va afficher la valeur de nb_clicks.

nb_clicks=0

textecompteur = Label(fenetre, text="nombre de clicks : %s" %(nb_clicks), font=("Helvetica",15), bg="#d1fdff", fg="black")
#ici, dans la chaîne de caractères, le "%s" sera remplacé par la valeur de la variable placée dans le tuple situé après le % soit nb_clicks

def compteur():
    global nb_clicks
    nb_clicks += 1
    print(nb_clicks)

bouton1 = Button(fenetre, text="Je suis un bouton", font=("Consolas",15), bg="white", fg="black", command=compteur, width=50, height=3)

On se rend alors compte que même si la valeur est incrémentée, le label ne s’actualise pas dans la fenêtre. On va alors ajouter une ligne dans la fonction compteur qui va mettre à jour ce Label à chaque clic du bouton à l’aide de l’instruction .config()

def compteur():
    global nb_clicks
    nb_clicks += 1
    textecompteur.config(text="nombre de clicks : %s" %(nb_clicks))

Voici ce que ça donne:

Cependant, si la fonction à exécuter nécessite des arguments, les choses vont se passer un peu différemment.

Dans cet exemple, on va créer deux boutons, qui vont exécuter la même fonction en cas de clic, mais avec des arguments différents.

Il est nécessaire pour cela d’importer la fonction partial de la library functools.

from functools import partial

On créé d’abord notre fonction. Ici, elle prend en argument une couleur et applique cette couleur au Label titre en cas d’appel de la fonction:

def changer_couleur_titre(couleur):
    titre.config(fg=couleur)

Ensuite, on créé les boutons avec pour commande partial( nomdelafonction, argument )

bouton2 = Button(fenetre, text="titre rouge", font=("Consolas",15), bg="white", fg="black", command=partial(changer_couleur_titre,"red"))
bouton3 = Button(fenetre, text="titre bleu", font=("Consolas",15), bg="white", fg="black", command=partial(changer_couleur_titre,"blue"))

Lorsque l’on va cliquer sur bouton2 le titre va devenir rouge, et sur le bouton3 il deviendra bleu

Ajouter un champ pour entrer du texte

Pour certains programmes, et en particulier les simulateurs, il est nécessaire d’entrer des données manuellement, et c’est là que les Entry entrent en jeu.

Là aussi, le processus est assez similaire aux Labels, la seule différence est que text est remplacé par textvariable qui sera donc la variable que l’on va modifier lorsque l’on écrira dans ce champ.

A l’instar des boutons, il est aussi possible de modifier leur taille à l’aide de width et height

Ici, la création de la variable est un peu différente car il doit s’agir d’une variable tkinter. On procède alors de la manière suivante:

#création de la variable
variable = tk.StringVar()
variable.set("Vous pouvez me modifier")

#création du champ
entree = Entry(fenetre, textvariable=variable, font=("Helvetica",15), bg="#d1fdff", fg="black", width=30)

Il faudra utiliser la même méthode à chaque fois que l’on voudra créer des variables pour des chaînes de caractères que l’on voudra afficher dans une interface tkinter

Il est possible aussi possible d’appeler cette variable (en utilisant .get() car il s’agit d’une variable tkinter) pour modifier du texte par exemple:

def changer_titre():
    titre.config(text=variable.get())

bouton4 = Button(fenetre, text="Cliquez pour actualiser", font=("Helvetica",15), bg="#d1fdff", fg="black", command = changer_titre)

Ici, à chaque clic du bouton, le texte du titre sera actualisé pour devenir celui du champ:

Maintenant que l’on sait incorporer différents éléments à notre fenêtre, on va s’intéresser à comment les organiser

Utiliser les boites

Les boites, ou Frames, sont très utiles lorsque l’on utilise tkinter puisqu’elles permettent de regrouper des éléments entre eux et ainsi créer différents menus entre lesquels on peut naviguer.

Il est nécessaire de les définir avant les éléments qui vont en faire partie, c’est pourquoi il est conseillé de les définir juste en dessous de la configuration de la fenêtre.

On créé une boite de la manière suivante, en spécifiant la boite dans laquelle elle est placée, et la couleur de son arrière plan

boitelabels = Frame(fenetre, bg="#d1fdff")

Ici, on a spécifié que la boite apparaîtrait dans la fenêtre principale, mais il est aussi possible de faire apparaître des boites dans des boites.

Comme tout autre élément, si l’on veut qu’une boite apparaisse, il ne faudra pas oublier de l’appeler avec un .pack(). Si un élément est appelé ainsi mais pas sa boîte, il n’apparaîtra pas, et si jamais il n’est pas appelé et que sa boite si, il n’apparaîtra pas non plus

Pour qu’un élément apparaisse dans une boîte, il suffit de remplacer le fenetre que l’on utilisait jusqu’à présent par le nom de la boite:

titre = Label(boitelabels, text="Voici un exemple de Label en police consolas et en taille 20", font=("Consolas",20), bg="#d1fdff", fg="black")
soustitre = Label(boitelabels, text="Voici un exemple de Label en police Helvetica et en taille 15", font=("Helvetica",15), bg="#d1fdff", fg="black")

Nous allons maintenant essayer de créer un menu nous permettant de naviguer entre tout ce que l’on a créé jusqu’à présent.

On créé alors différentes boites pour nos différents éléments. Dans cet exemple

  • boitelabels contiendra les éléments servi à la démonstration de ce que sont les Labels
  • boitecompteur contiendra le compteur créé un peu plus tôt
  • boitecouleurs contiendra les boutons permettant de modifier la couleur du titre
  • boiteentree contiendra les éléments ayant servi à la démonstration de l’utilité des Entries
  • boitemenu contiendra les boutons permettant d’afficher les différentes boites. Elle va être la seule à apparaître lorsque l’on lancera le script et permettra d’afficher les autres
boitecompteur = Frame(fenetre, bg="#d1fdff")
boitecouleurs = Frame(fenetre, bg="#d1fdff")
boiteentree = Frame(fenetre, bg="#d1fdff")
boitemenu = Frame(fenetre, bg="#d1fdff")

En on n’oublie pas de modifier la boite de chaque élément pour qu’il n’apparaisse plus dans la fenêtre principale mais dans la boite dans laquelle on veut qu’il apparaisse

#exemple: ici on place le label textecompteur dans la boitecompteur:
textecompteur = Label(boitecompteur, text="nombre de clicks : %s" %(nb_clicks), font=("Helvetica",15), bg="#d1fdff", fg="black")

On va aussi créer des boutons dans boitemenu qui, lorqu’ils seront cliqués appelleront une autre boite avec un .pack() et feront disparaître le menu à l’aide de .pack_forget(). On va aussi mettre en place des boutons de retour au menu dans chacune des autres boites qui vont, eux, faire disparaître leur boite et apparaître le menu en cas de clic;

def afficher_labels():
    boitelabels.pack(expand=YES)
    boitemenu.pack_forget()

def afficher_compteur():
    boitecompteur.pack(expand=YES)
    boitemenu.pack_forget()
    
def afficher_couleurs():
    boitecouleurs.pack(expand=YES)
    boitemenu.pack_forget()
    
def afficher_entree():
    boiteentree.pack(expand=YES)
    boitemenu.pack_forget()
    
def retour_menu():
    boitemenu.pack(expand=YES)
    boitelabels.pack_forget()
    boitecompteur.pack_forget()
    boitecouleurs.pack_forget()
    boiteentree.pack_forget()
    
b_labels = Button(boitemenu, text="Afficher les Labels", font=("Consolas",15), bg="white", fg="black", command=afficher_labels, width=75)
b_compteur = Button(boitemenu, text="Afficher le compteur", font=("Consolas",15), bg="white", fg="black", command=afficher_compteur, width=75)    
b_couleurs = Button(boitemenu, text="Afficher les boutons pour changer la couleur du titre", font=("Consolas",15), bg="white", fg="black", command=afficher_couleurs, width=75)    
b_entree = Button(boitemenu, text="Afficher le champ pour changer le titre", font=("Consolas",15), bg="white", fg="black", command=afficher_entree, width=75)
b_retour1 = Button(boitelabels, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
b_retour2 = Button(boitecompteur, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
b_retour3 = Button(boitecouleurs, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
b_retour4 = Button(boiteentree, text="retourner au menu", font=("Consolas",15), bg="white", fg="black", command=retour_menu, width=35)
Le Menu

Tout ça est bien beau, mais pour l’instant on ne sait qu’afficher différents éléments les uns au dessous des autres, mais pas les uns à côté des autres. C’est là que les grilles vont intervenir

Utiliser les grilles

Pour faire une grille, on va remplacer les .pack() que l’on utilisait par des .grid(). Il faut savoir que si l’on utilise une grille pour un élément, tous les éléments présents dans la même boite devront eux aussi utiliser cette même grille.

Comme on voudrait seulement placer deux des boutons côte à côte, on va les placer dans une sous boite de la boite du menu:

#création de la sous boite
sousboitemenu = Frame(boitemenu, bg="#d1fdff")

Et on modifie la boite des deux boutons concernés, ainsi que leurs dimensions pour qu’ils soient alignés avec les autres. (On ajoute aussi un \n dans le texte du second bouton pour qu’il s’affiche sur deux lignes)

b_compteur = Button(sousboitemenu, text="Afficher le compteur", font=("Consolas",15), bg="white", fg="black", command=afficher_compteur, width=36, height=2)    
b_couleurs = Button(sousboitemenu, text="Afficher les boutons \npour changer la couleur du titre", font=("Consolas",15), bg="white", fg="black", command=afficher_couleurs, width=36, height=2) 

Il est temps maintenant de placer les boutons en grille à l’aide de .grid().

Cette méthode accepte plusieurs arguments:

  • row qui définit la ligne dans laquelle l’élément va être placé
  • column qui définit sa colonne
  • sticky qui définit de quel côté de la fenêtre l’élément doit se rapprocher ( W, E, S ou N pour les quatre points cardinaux)
  • padx et pady (optionnels) qui définissent les marges en x et en y
b_compteur.grid(row=1, column=0, sticky=W, pady=5, padx=5)
b_couleurs.grid(row=1, column=1, sticky=W, pady=5, padx=5)

On obtient alors le résultat suivant:

Conclusion

Voilà, vous possédez maintenant les bases nécessaires pour pouvoir créer vos propres interfaces graphiques pour vos scripts Python !

Si jamais certains éléments ne sont pas assez clairs, vous pouvez toujours télécharger le script créé pour ce tutoriel afin de le tester ou de lire son code.

Projets

Hexapawn, ou une IA évolutive simple en Python

Comment ça on peut coder des IA qui apprennent en Python en 1ère ? C’est pas censé être un truc ultra pointu ? Eh bien en fait c’est relativement facile à faire pour des jeux aux règles simples comme l’Hexapawn.

Un Hexapawn, quésaco

Il s’agit d’un jeu d’échec miniature, qui se joue sur un plateau de jeu constitué de 9 cases (3×3), et dans lequel chaque joueur possède 3 pions – d’où le nom: hexa, six et pawn, pion en anglais.

Les règles du jeu sont simples: les pions se déplacent comme des pions d’échec:

  • Ils ne se déplacent que d’une case à la fois et uniquement vers l’avant
  • Ils ne peuvent manger qu’en diagonale, là aussi dans un rayon d’une case

Le but est de réussir à amener l’un de ses pions de l’autre côté du plateau ou d’éliminer la totalité des pions adverses.

Dans le cas ou aucun pion ne peut plus bouger, il y a égalité

Ce projet a été inspiré par une vidéo de Vsauce2, une chaîne présentant divers jeux ayant lien avec les mathématiques ou la logique.

Particularités du jeu

Comme les règles de l’Hexapawn sont très simples, il suffit simplement d’empêcher l’ordi de refaire des mouvements qui l’ont amené à perdre afin de le faire s’améliorer au fur et a mesure qu’il joue.

La principale difficulté dans la réalisation de ce projet a été de devoir prendre en compte toutes les possibilités de jeu, ce qui rend au final le script assez long.

En bonus, on s’est dit que ce serait sympa d’ajouter un menu afin de personnaliser les couleurs de l’interface

Commencer le projet : les Libraries nécessaires

Ce jeu a été entièrement codé en Python, et en Python, la première chose à faire lorsqu’on commence quelque chose est d’importer les Libraries (programmes externes) nécessaires pour sa réalisation.

#les différentes libraries nécessaires
from tkinter import *
import tkinter as tk
from functools import partial
from random import *
import webbrowser

Les différentes libraries que nous avons choisi d’utiliser sont les suivantes :

  • tkinter (abrégé de ToolKit Interface) qui permet de créer une interface graphique,
  • la fonction partial de la library functools, qui va nous être utile lors de la création des différents boutons,
  • random, qui va permettre d’ajouter de l’aléatoire dans certaines actions,
  • webbrowser, qui va permettre d’ouvrir des pages web.

Maintenant que l’on a importé tous les modules nécessaires, on va pouvoir commencer à coder le projet en lui-même.

Configuration de la fenêtre

Comme l’on utilise tkinter afin de pouvoir donner une interface graphique à notre jeu, on va commencer par configurer notre fenêtre (taille, titre, couleur de fond etc…)

couleur = "#424242"

#mise en place de la fenêtre
window = Tk()
window.title("♟ Hexapawn ♟")
window.geometry("1080x720")
window.config(bg=couleur)

Ici on a donc une fenêtre de couleur grise, dont le titre est « ♟ Hexapawn ♟ » et dont la taille est de 1080 x 720 pixels

Création des variables

Une fois la fenêtre créée, on configure les variables qui seront utilisées par le script (le nombre de points de chacun, l’état des cases -vides au début-, les différentes variables à afficher…)

#définition de certaines variables
couleur_texte = "#666666"
couleur_selection = "#cccccc"
couleur_ordi = "#000000"
couleur_joueur = "#ffffff"
tour = 0
pions_joueur = 3
pions_ordi = 3
pions_bloques = 0
resultat = ""
coups_perdants = []
coups_gagnants = []
jeu = ""
a1 = ""
a2 = ""
a3 = ""
b1 = ""
b2 = ""
b3 = ""
c1 = ""
c2 = ""
c3 = ""
ordi_gagne = False
joueur_gagne = False
egalite = False
points_ordi = 0
points_joueur = 0

Tkinter ne peut pas afficher des variables classiques dans les fenêtres, c’est pourquoi il est nécessaire de créer des variables spéciales que l’on déclare comme ceci :

#définition des variables qui seront affichées dans l'interface tkinter
a1_display = tk.StringVar()
a2_display = tk.StringVar()
a3_display = tk.StringVar()
b1_display = tk.StringVar()
b2_display = tk.StringVar()
b3_display = tk.StringVar()
c1_display = tk.StringVar()
c2_display = tk.StringVar()
c3_display = tk.StringVar()
resultat_display = tk.StringVar()
score_ordi_display = tk.IntVar()
score_joueur_display = tk.IntVar()
valeur = tk.StringVar()
contour_texte = tk.StringVar()
contour_texte.set('''
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
''')

Comme la majorité de ces variables tkinter sont associées à des variables classiques, nous avons décidé d’ajouter « _display » à la fin de leur nom pour pouvoir plus facilement les différencier.

Par exemple, la variable a1 sera associée à la variable tkinter a1_display qui sera actualisée dans le script à chaque fois que a1 change de valeur

Configuration des boites

Maintenant on crée les différentes boites. Elles permettront d’afficher les différents éléments qu’elles contiennent quand elles seront appelées (la boite menu, règle etc…) ou de ne plus les afficher lorsqu’elles seront oubliées.

#mise en place des différentes boites
boite_titre = Frame(window, bg=couleur)
boite_menu = Frame(window, bg=couleur)
boite_regles = Frame(window, bg=couleur)
boite_jeu = Frame(window, bg=couleur)
boite_ordi = Frame(window, bg=couleur)
boite_resultat = Frame(window, bg=couleur)
boite_couleurs = Frame(window, bg=couleur)
boite_couleurs2 = Frame(window, bg=couleur)

Mise en place des Labels

Afin d’avoir une interface claire, il est important d’ajouter des éléments textuels: titre, règles du jeu etc.

Dans tkinter, les éléments textuels sont nommés labels. On les déclare comme ceci:

#mise en place des différents éléments textuels
titre = Label(boite_titre, text =
              '''
 .----------------.  .----------------.  .----------------.  .----------------.  .----------------.  .----------------.  .----------------.  .-----------------.
| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |
| |  ____  ____  | || |  _________   | || |  ____  ____  | || |      __      | || |   ______     | || |      __      | || | _____  _____ | || | ____  _____  | |
| | |_   ||   _| | || | |_   ___  |  | || | |_  _||_  _| | || |     /  \     | || |  |_   __ \   | || |     /  \     | || ||_   _||_   _|| || ||_   \|_   _| | |
| |   | |__| |   | || |   | |_  \_|  | || |   \ \  / /   | || |    / /\ \    | || |    | |__) |  | || |    / /\ \    | || |  | | /\ | |  | || |  |   \ | |   | |
| |   |  __  |   | || |   |  _|  _   | || |    > `' <    | || |   / ____ \   | || |    |  ___/   | || |   / ____ \   | || |  | |/  \| |  | || |  | |\ \| |   | |
| |  _| |  | |_  | || |  _| |___/ |  | || |  _/ /'`\ \_  | || | _/ /    \ \_ | || |   _| |_      | || | _/ /    \ \_ | || |  |   /\   |  | || | _| |_\   |_  | |
| | |____||____| | || | |_________|  | || | |____||____| | || ||____|  |____|| || |  |_____|     | || ||____|  |____|| || |  |__/  \__|  | || ||_____|\____| | |
| |              | || |              | || |              | || |              | || |              | || |              | || |              | || |              | |
| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |
 '----------------'  '----------------'  '----------------'  '----------------'  '----------------'  '----------------'  '----------------'  '----------------'

''', font=("consolas",7), bg = couleur, fg = couleur_texte)

sep = Label(boite_titre, text = "."*200, font=("consolas",7), bg = couleur, fg = couleur_texte)
regles_label = Label(boite_regles, text =
                     '''
Regles du jeu:

Vous possédez 3 pions, qui peuvent se déplacer comme des pions aux échecs:

-ils ne peuvent que se déplacer vers l'avant
-ils ne peuvent se déplacer que d'une case à la fois
-ils ne peuvent "manger" un pion adverse qu'en diagonale

2 conditions de victoire possibles:

-l'adversaire ne possède plus aucun pion
-vous parvenez à amener un pion à l'autre bout du plateau

Pour déplacer un pion, cliquez sur lui puis sur la case vers laquelle vous
voulez qu'il aille.
Lorsque vous avez joué, cliquez sur le bouton sous l'échéquier

'''
, font=("consolas",15), bg = couleur, fg = couleur_texte)
resultat_Label = Label(boite_resultat, text = "", font=("consolas",15), bg = couleur, fg = couleur_texte)
scores = Label(boite_resultat, text = "%s à %s" %(score_joueur_display.get(),score_ordi_display.get()), font=("consolas",15), bg = couleur, fg = couleur_texte)
retour_selection = Label(boite_couleurs, text = "", font=("consolas",10), bg = couleur, fg = couleur_texte)
contour1 = Label(boite_menu, text = contour_texte.get(), font=("consolas",7), bg = couleur, fg = couleur_texte)
contour2 = Label(boite_menu, text = contour_texte.get(), font=("consolas",7), bg = couleur, fg = couleur_texte)
contour3 = Label(boite_menu, text = contour_texte.get(), font=("consolas",7), bg = couleur, fg = couleur_texte)
contour4 = Label(boite_menu, text = contour_texte.get(), font=("consolas",7), bg = couleur, fg = couleur_texte)
contour5 = Label(boite_menu, text = contour_texte.get(), font=("consolas",7), bg = couleur, fg = couleur_texte)
contour6 = Label(boite_menu, text = contour_texte.get(), font=("consolas",7), bg = couleur, fg = couleur_texte)

Pour le titre, nous avons décidé de l’écrire en ASCII à l’aide de ce générateur

Chaque Label possède plusieurs attributs: la boîte dans lequel il va apparaître, le texte qu’il contient, la police et la taille d’écriture, la couleur de fond et enfin la couleur de l’écriture.

Comme vous pouvez le constater, certains de ces Labels font appel à des variables tkinter qui nous avons précédemment définies comme celui-ci par exemple:

scores = Label(boite_resultat, text = "%s à %s" %(score_joueur_display.get(),score_ordi_display.get()), font=("consolas",15), bg = couleur, fg = couleur_texte)

Pour appeler ces variables, il suffit d’écrire leur nom suivi de .get()

Maintenant que l’on a défini les éléments texte, on va pouvoir s’attaquer aux différentes fonctions du script.

Premières fonctions: fonctions de navigation

Comme l’on a décidé d’utiliser une ineterface graphique pour ce projet, la plupart des fonctions seront appelées à l’aide de boutons.

#commande permettant d'afficher les règles du jeu
def command_regles():
    boite_menu.pack_forget()
    boite_regles.pack(pady = 25)

Cette fonction par exemple permettra d’afficher les règles du jeu. Il suffit d’ajouter .pack() à la fin du nom d’une boite pour la faire apparaître, et .pack_forget() pour la faire disparaître.

Ainsi, lorsque cette fonction sera appelée, les éléments de la boite_menu disparaîtront pour laisser place à ceux de la boite_regles

Cette fonction sera associée à un bouton de la manière suivante :

b_regles = Button(boite_menu, text = "Règles du jeu", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = command_regles)

On créé un nouvel élément nommé b_regles: un bouton (Button) à qui on donne différents attributs: une boite, un texte, une police et une taille, une couleur de fond, une couleur de texte, et surtout une fonction (l’attribut command) qui sera appelée en cas de clic.

Lorsque l’on cliquera sur ce bouton, la fonction command_regles sera exécutée, ce qui aura pour effet d’afficher les règles du jeu.

On procède de même avec les autres fonctions qui vont nous permettre de naviguer dans notre fenêtre :

#commande pour retourner au menu depuis les règles
def command_retour_regles():
    boite_menu.pack(pady = 25)
    boite_regles.pack_forget()

#commande pour afficher le menu de personnalisation des couleurs
def command_personnaliser():
    boite_menu.pack_forget()
    boite_couleurs.pack(pady = 25)
    boite_couleurs2.pack()

#commande pour retourner au menu principal depuis celui de personnalisation des couleurs
def command_retour_personnaliser():
    boite_menu.pack(pady = 25)
    boite_couleurs.pack_forget()
    boite_couleurs2.pack_forget()

Ainsi qu’avec leurs boutons respectifs

b_retour_regles = Button(boite_regles, text = "Retour", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = command_retour_regles)
b_personnaliser = Button(boite_menu, text = "Personnaliser", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = command_personnaliser)
b_retour_personnaliser = Button(boite_couleurs2, text = "Retour", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = command_retour_personnaliser)

Personnalisation des couleurs

Grâce au menu de personnalisation des couleurs, les utilisateurs du script pourront choisir les couleurs qui leur plait ainsi créant des mélanges uniques.

Ce menu est constitué de plusieurs boutons :

b_couleur1 = Button(boite_couleurs2, text = "Changer la couleur principale ", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = partial(changer_couleur,0))
b_couleur2 = Button(boite_couleurs2, text = "Changer la couleur secondaire ", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = partial(changer_couleur,1))
b_couleur3 = Button(boite_couleurs2, text = "Changer la couleur de selection", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = partial(changer_couleur,2))
b_couleur_joueur = Button(boite_couleurs2, text = " Changer la couleur du joueur ", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = partial(changer_couleur,3))
b_couleur_ordi = Button(boite_couleurs2, text = " Changer la couleur de l'ordi ", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = partial(changer_couleur,4))
b_personnaliser = Button(boite_menu, text = "Personnaliser", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = command_personnaliser)

couleur_entry = Entry(boite_couleurs, text = "#", textvariable=valeur, font=("Helvetica",15) , bg="white", fg="black")
b_ok = Button(boite_couleurs, text = "Cliquez pour appliquer", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = rien)

C’est ici que la fonction partial que nous avons importée va nous être utile: en effet, tous les boutons de ce menu vont exécuter la même fonction, mais avec un paramètre différent, ce qui nous permet de n’écrire qu’une seule fonction au lieu de 5 différentes.

def changer_couleur(test):
    b_ok.config(command = partial(appliquer,test))
    if test == 0:
        retour_selection.config(text = "couleur principale")
    elif test == 1:
        retour_selection.config(text = "couleur secondaire")
    elif test == 2:
        retour_selection.config(text = "couleur de sélection")
    elif test == 3:
        retour_selection.config(text = "couleur du joueur")
    elif test == 4:
        retour_selection.config(text = "couleur de l'ordi")

def appliquer(test):
    global couleur, couleur_texte, couleur_selection, couleur_joueur, couleur_ordi
    if test == 0:
        couleur = str(valeur.get())
    elif test == 1:
        couleur_texte = str(valeur.get())
    elif test == 2:
        couleur_selection = str(valeur.get())
    elif test == 3:
        couleur_joueur = str(valeur.get())
    elif test == 4:
        couleur_ordi = str(valeur.get())
    window.config(bg = couleur)
    titre.config(bg = couleur, fg = couleur_texte)
    sep.config(bg = couleur, fg = couleur_texte)
    boite_titre.config(bg = couleur)
    boite_menu.config(bg = couleur)
    boite_regles.config(bg = couleur)
    boite_jeu.config(bg = couleur)
    boite_ordi.config(bg = couleur)
    boite_resultat.config(bg = couleur)
    boite_couleurs.config(bg = couleur)
    boite_couleurs2.config(bg = couleur)
    b_a1.config(bg = couleur_texte)
    b_a2.config(bg = couleur)
    b_a3.config(bg = couleur_texte)
    b_b1.config(bg = couleur)
    b_b2.config(bg = couleur_texte)
    b_b3.config(bg = couleur)
    b_c1.config(bg = couleur_texte)
    b_c2.config(bg = couleur)
    b_c3.config(bg = couleur_texte)
    b_jouer.config(bg = couleur_texte, fg = couleur)
    b_regles.config(bg = couleur_texte, fg = couleur)
    b_retour_regles.config(bg = couleur_texte, fg = couleur)
    b_personnaliser.config(bg = couleur_texte, fg = couleur)
    b_retour_personnaliser.config(bg = couleur_texte, fg = couleur)
    b_couleur1.config(bg = couleur_texte, fg = couleur)
    b_couleur2.config(bg = couleur_texte, fg = couleur)
    b_couleur3.config(bg = couleur_texte, fg = couleur)
    b_couleur_ordi.config(bg = couleur_texte, fg = couleur)
    b_couleur_joueur.config(bg = couleur_texte, fg = couleur)
    b_rejouer.config(bg = couleur_texte, fg = couleur)
    b_ordi.config(bg = couleur_texte, fg = couleur)
    b_trouver_hex.config(bg = couleur_texte, fg = couleur)
    b_ok.config(bg = couleur_texte, fg = couleur)
    regles_label.config(bg = couleur, fg = couleur_texte)
    b_retour_jeu.config(bg = couleur_texte, fg = couleur)
    scores.config(bg = couleur, fg = couleur_texte)
    resultat_Label.config(bg = couleur, fg = couleur_texte)
    retour_selection.config(bg = couleur, fg = couleur_texte)
    contour1.config(bg = couleur, fg = couleur_texte)
    contour2.config(bg = couleur, fg = couleur_texte)
    contour3.config(bg = couleur, fg = couleur_texte)
    contour4.config(bg = couleur, fg = couleur_texte)
    contour5.config(bg = couleur, fg = couleur_texte)
    contour6.config(bg = couleur, fg = couleur_texte)

Lorsque le bouton « Cliquez pour appliquer » est cliqué la fonction appliquer est exécutée avec un paramètre différent en fonction du bouton sélectionné auparavant.

La fonction change la couleur demandée puis rafraîchit tous les éléments différents afin que le changement de couleur apparaisse.

Il est à noter que le script ne comprend que certains noms de couleur en anglais ou les couleurs données en hexadécimal

Ce menu comporte aussi un bouton permettant d’ouvrir une page web avec un panneau pour sélectionner la couleur de son choix et avoir son code en hexadécimal :

b_trouver_hex = Button(boite_couleurs2, text = "    Trouver des couleurs     ", font = ("consolas", 15), bg = couleur_texte, fg = couleur, command = pick_hex)

L’ouverture de la page depuis le script est faite grâce a la Library webbrowser

def pick_hex():
    webbrowser.open_new("https://www.google.com/search?client=opera-gx&q=color+picker&sourceid=opera&ie=UTF-8&oe=UTF-8")

Mise en place du plateau de jeu

Après avoir lu les règles du jeu et modifié les couleurs si nécessaire on peut enfin jouer.

En cliquant sur le bouton jouer on exécute la commande suivante :

def command_jouer():
    boite_resultat.pack_forget()
    boite_jeu.pack(pady = 25)
    boite_ordi.pack(pady = 25)
    boite_menu.pack_forget()
    global a1 , a2 , a3 , b1 , b2 , b3 , c1 , c2 , c3 , pions_ordi, pions_joueur, pions_bloques, ordi_gagne, egalite, joueur_gagne, tour, couleur_ordi, couleur_joueur, jeu
    jeu = ""
    a1 , a2 , a3 , b1 , b2 , b3 , c1 , c2 , c3 = "♟" , "♟" , "♟" , "  " , "  " , "  " , "♙" , "♙" , "♙"
    a1_display.set(a1)
    a2_display.set(a2)
    a3_display.set(a3)
    b1_display.set(b1)
    b2_display.set(b2)
    b3_display.set(b3)
    c1_display.set(c1)
    c2_display.set(c2)
    c3_display.set(c3)
    b_a1.config(text = a1_display.get(), fg = couleur_ordi)
    b_a2.config(text = a2_display.get(), fg = couleur_ordi )
    b_a3.config(text = a3_display.get(), fg = couleur_ordi )
    b_b1.config(text = b1_display.get() )
    b_b2.config(text = b2_display.get() )
    b_b3.config(text = b3_display.get() )
    b_c1.config(text = c1_display.get(), fg = couleur_joueur )
    b_c2.config(text = c2_display.get(), fg = couleur_joueur )
    b_c3.config(text = c3_display.get(), fg = couleur_joueur )
    pions_ordi = 3
    pions_joueur = 3
    pions_bloques = 0
    joueur_gagne = False
    ordi_gagne = False
    egalite = False
    tour = 0
    tester_cases_selectionnables()

Elle permet de mettre en place le plateau de jeu en faisant apparaître les boites boite_jeu et boite_ordi et en faisant disparaître les autres.

Ensuite les pions sont placés sur le plateau et le compteur de tours, et ceux des pions sont mis à leurs valurs initiales

Enfin, le script teste les cases à partir desquelles l’on peut bouger nos pions à l’aide de la fonction tester_cases_selectionnables().

Les possibilités de déplacement

La fonction « tester_cases_selectionnables() » teste les cases sur lesquels se trouve les pions du joueur et permet au joueur de cliquer le bouton si jamais un de ses pions y est présent.

def tester_cases_selectionnables():
    if c1 == "♙":
        b_c1.config(command = partial(selected,"c1"), fg = couleur_joueur )

    if c2 == "♙":
        b_c2.config(command = partial(selected,"c2"), fg = couleur_joueur  )

    if c3 == "♙":
        b_c3.config(command = partial(selected,"c3"), fg = couleur_joueur  )

    if b1 == "♙":
        b_b1.config(command = partial(selected,"b1"), fg = couleur_joueur  )

    if b2 == "♙":
        b_b2.config(command = partial(selected,"b2"), fg = couleur_joueur  )

    if b3 == "♙":
        b_b3.config(command = partial(selected,"b3"), fg = couleur_joueur  )

Ensuite, selon la case sélectionnée le script étudie les mouvements possibles et modifie les commandes éxécutées en cas de clic sur la case en conséquence :

def selected(case):
    global a1, a2, a3, b1, b2, b3, c1, c2, c3
    global tour

    if tour == 0 :

        if case == "c1":
            b_b1.config(command = partial(jouer_vers,"c1","b1"))
            b_b2.config( command = rien)
            b_b3.config(command = rien)
            b_c1.config(fg=couleur_selection)
            b_c2.config(fg=couleur_joueur)
            b_c3.config(fg=couleur_joueur)
            b_b2.config(command = rien)
            b_b3.config(command = rien)

        elif case == "c2":
            b_b2.config(command = partial(jouer_vers,"c2","b2"))
            b_c2.config(fg=couleur_selection)
            b_c1.config(fg=couleur_joueur)
            b_c3.config(fg=couleur_joueur)
            b_b1.config(command = rien)
            b_b3.config(command = rien)
#et ainsi de suite avec les autres cases
    elif tour >= 2:

        if case == "c1":
            reset_commandes()
            tester_cases_selectionnables()
            b_c1.config(fg=couleur_selection)
            if b1 == "  ":
                b_b1.config(command = partial(jouer_vers,"c1","b1"))
            if b2 == "♟":
                b_b2.config(command = partial(jouer_vers,"c1","b2"))

        elif case == "c2":
            reset_commandes()
            tester_cases_selectionnables()
            b_c2.config(fg=couleur_selection)
            if b2 == "  ":
                b_b2.config(command = partial(jouer_vers,"c2","b2"))
            if b1 == "♟":
                b_b1.config(command = partial(jouer_vers,"c2","b1"))
            if b3 == "♟":
                b_b3.config(command = partial(jouer_vers,"c2","b3"))
#etc...

Après avoir choisi le pion qu’il souhaitait déplacer, le joueur va cliquer sur la case vers laquelle il veut que le pion se déplace.

La fonction jouer_vers va alors être exécutée avec en paramètres la case de départ et la case d’arrivée du pion.

La fonction va rendre vide la case de départ du pion et va mettre un pion blanc dans la case d’arrivée

def jouer_vers(case1, case2):
    global tour, jeu
    global a1, a2, a3, b1, b2, b3, c1, c2, c3
    global pions_ordi, ordi_gagne

    if tour / 2 == tour // 2 and not ordi_gagne:

        if case1 == "c1":
            c1 = "  "
            c1_display.set(c1)
            b_c1.config(text = c1_display.get())

        elif case1 == "c2":
            c2 = "  "
            c2_display.set(c2)
            b_c2.config(text = c2_display.get())
#etc...
        if case2 == "b1":
            if b1 == "♟":
                pions_ordi -= 1
            b1 = "♙"
            b1_display.set(b1)
            b_b1.config(text = b1_display.get(), fg = couleur_joueur)
            jeu += case2

        elif case2 == "b2":
            if b2 == "♟":
                pions_ordi -= 1
            b2 = "♙"
            b2_display.set(b2)
            b_b2.config(text = b2_display.get(), fg = couleur_joueur)
            jeu += case2
#etc...

Si le joueur a réussi à amener l’un de ses pions de l’autre côté, il gagne un point et le résultat de la partie est affiché avec les scores.

Sinon, c’est à l’ordi de jouer.

        elif case2 == "a3":
            a3 = "♙"
            a3_display.set(a3)
            b_a3.config(text = a3_display.get(), fg = couleur_joueur)
            joueur_gagne = True
            coups_perdants.append(jeu)

        tour += 1

    if pions_joueur == 0:
        ordi_gagne = True

    if ordi_gagne :
        boite_jeu.pack_forget()
        resultat = "Défaite"
        resultat_display.set(resultat)
        resultat_Label.config(text = resultat_display.get())
        boite_resultat.pack()

    else:
        pass

L’IA

Les mouvements possible de l’ordinateur sont étudiés par la fonction « ordi() ».

#début de la fonction ordi()
def ordi():
    global tour
    global a1, a2, a3, b1, b2, b3, c1, c2, c3
    global pions_joueur, points_joueur, ordi_gagne, points_ordi, pions_ordi, joueur_gagne, pions_bloques, resultat, egalite, coups_gagnants, coups_perdants, jeu, couleur_ordi

Elle étudie tout d’abord si il y a un vainqueur ou une égalité ( grâce à la fonction « tester_tie() » expliquée un peu plus plus loin ) .

    if pions_ordi == 0:
        joueur_gagne = True
    if pions_joueur == 0:
        ordi_gagne = True
    tester_tie()


    if pions_bloques == pions_ordi:
        egalite = Tr

Si il n’y a pas de vainqueur ou d’égalité et que c’est au tour de l’ordi de jouer, le script analyse les mouvements possibles de l’ordinateur. si il s’aperçoit qu’un mouvement l’a amené à perdre dans une configuration similaire, il ne l’inclura pas dans la liste des mouvements possibles.

Si, au contraire un des mouvements l’a fait gagner précédemment, il le mettra dans une liste spéciale

 elif tour/2 != tour//2 and not joueur_gagne and not ordi_gagne :
            mvt_possibles = []
            mvt_gagnants = []
            if a1 == "♟":
                if b1 == "  " and jeu + "a1b1" not in coups_perdants :
                    mvt_possibles.append("a1b1")
                    if jeu + "a1b1" in coups_gagnants:
                        mvt_gagnants.append("a1b1")

                if b2 == "♙" and jeu + "a1b2" not in coups_perdants:
                    mvt_possibles.append("a1b2")
                    if jeu + "a1b2" in coups_gagnants:
                        mvt_gagnants.append("a1b2")


            if a2 == "♟":
                if b1 == "♙" and jeu + "a2b1" not in coups_perdants :
                    mvt_possibles.append("a2b1")
                    if jeu + "a2b1" in coups_gagnants:
                        mvt_gagnants.append("a2b1")

                if b2 == "  " and jeu + "a2b2" not in coups_perdants:
                    mvt_possibles.append("a2b2")
                    if jeu + "a2b2" in coups_gagnants:
                        mvt_gagnants.append("a2b2")

                if b3 == "♙" and jeu + "a2b3" not in coups_perdants:
                    mvt_possibles.append("a2b3")
                    if jeu + "a2b3" in coups_gagnants:
                        mvt_gagnants.append("a2b3")
#et ainsi de suite avec toutes les cases...

Ensuite, la fonction teste si des mouvements possibles peuvent amener l’ordi à gagner à coup sûr. Si c’est le cas, un mouvement aléatoire est pioché parmi la liste mvt_gagnants.

Sinon, l’ordi choisit un mouvement aléatoire parmi les mouvements possibles.

            if mvt_gagnants != []:
                mvt_ordi = mvt_gagnants[randint(0,len(mvt_gagnants)-1)]
            else:
                mvt_ordi = mvt_possibles[randint(0,len(mvt_possibles)-1)]

Le mouvement choisi est ensuite « joué »

            if mvt_ordi == "a1b1":
                a1 = "  "
                a1_display.set(a1)
                b_a1.config(text = a1_display.get())
                b1 = "♟"
                b1_display.set(b1)
                b_b1.config(text = b1_display.get(), fg = couleur_ordi)

            elif mvt_ordi == "a1b2":
                a1 = "  "
                a1_display.set(a1)
                b_a1.config(text = a1_display.get())
                b2 = "♟"
                b2_display.set(b2)
                b_b2.config(text = b2_display.get(), fg = couleur_ordi)
                pions_joueur -= 1
#etc...
            elif mvt_ordi == "b1c1":
                b1 = "  "
                b1_display.set(b1)
                b_b1.config(text = b1_display.get())
                c1 = "♟"
                c1_display.set(c1)
                b_c1.config(text = c1_display.get(), fg = couleur_ordi)
                ordi_gagne = True

Le coup joué est ensuite ajouté à la variable jeu.

Si le mouvement amène l’ordi à prendre un pion, le nombre de pions du joueur est décrémenté de 1

Si l’ordi a amené l’un de ses pions de l’autre côté, la variable ordi_gagne devient « vraie » (True)

            jeu += mvt_ordi

Si l’ordi a gagné, c’est à dire si ordi_gagne est True, son score est incrémenté, la variable « jeu » est ajouté à la liste des coups gagnants et le score ainsi que le résultat de la partie sont affichés

            if ordi_gagne:
                coups_gagnants.append(jeu)
                reset_commandes()
                boite_ordi.pack_forget()
                points_ordi += 1
                resultat = "Défaite"
                resultat_display.set(resultat)
                resultat_Label.config(text = resultat_display.get())
                score_ordi_display.set(points_ordi)
                score_joueur_display.set(points_joueur)
                scores.config(text = "%s à %s" %(score_joueur_display.get(), score_ordi_display.get()) )
                boite_resultat.pack()

Ensuite, on passe au tour suivant.

Si le joueur avait déjà gagné au début du tour (l’ordi n’a donc pas joué) ou s’il y a égalité le score est incrémenté en conséquence et l’issue de la partie est affichée

Si aucune de ces conditions n’est vérifiées, c’est au tour du joueur de jouer.

            tour +=1
            reset_commandes()
            tester_cases_selectionnables()
            tester_tie()




    if pions_bloques == pions_ordi:
        egalite = True


    if egalite:
        reset_commandes()
        boite_ordi.pack_forget()
        resultat = "Egalité"
        resultat_display.set(resultat)
        resultat_Label.config(text = resultat_display.get())
        boite_resultat.pack()

    elif joueur_gagne:
        coups_perdants.append(jeu)
        reset_commandes()
        boite_ordi.pack_forget()
        points_joueur += 1
        resultat = "Victoire"
        resultat_display.set(resultat)
        resultat_Label.config(text = resultat_display.get())
        score_ordi_display.set(points_ordi)
        score_joueur_display.set(points_joueur)
        scores.config(text = "%s à %s" %(score_joueur_display.get(), score_ordi_display.get()) )
        boite_resultat.pack()

    else:
        pass

Gagnant, perdant ou ex æquo

Plisieurs conditions peuvent mettre fin à la partie

  • Le joueur ou l’ordi amène l’un de ses pions de l’autre côté du plateau
  • le joueur ou l’ordi ne possèdent plus de pions
  • Tous les pions sont bloqués

Les deux premières conditions sont facilement vérifiables et sont déjà testées directement dans les fonctions ordi() et jouer_vers()

On teste donc s’il y a égalité à l’aide de la fonction tester_tie(), appelée à l’interieur de la fonction ordi() comme vu précédemment.

Cette fonction teste tout simplement pour chaque case si le pion présent n’a plus de possibilités de mouvement, et ajoute au compteur de pions bloqués 1 si jamais le pion ne peut plus bouger.

def tester_tie():
    global a1, a2, a3, b1, b2, b3, c1, c2, c3, pions_bloques
    pions_bloques = 0
    if a1 == "♟":
        if b1 == "♙":
            if b2 == "♟" or b2 == "  ":
                pions_bloques += 1
            else:
                pass
        else:
            pass

    if a2 == "♟":
        if b2 == "♙":
            if b1 == "♟" or b1 == "  ":
                if b3 == "♟" or b3 == "  ":
                    pions_bloques += 1
                else:
                    pass
            else:
                pass
        else:
            pass

    if a3 == "♟":
        if b3 == "♙":
            if b2 == "♟" or b2 == "  ":
                pions_bloques += 1
            else:
                pass
        else:
            pass

    if b1 == "♟":
        if c1 == "♙":
            if c2 == "♟" or c2 == "  ":
                pions_bloques += 1
            else:
                pass
        else:
            pass


    if b2 == "♟":
        if c2 == "♙":
            if c1 == "♟" or c1 == "  ":
                if c3 == "♟" or c3 == "  ":
                    pions_bloques += 1
                else:
                    pass
            else:
                pass
        else:
            pass


    if b3 == "♟":
        if c3 == "♙":
            if c2 == "♟" or c2 == "  ":
                pions_bloques += 1
            else:
                pass
        else:
            pass

Si jamais tous les pions de l’ordi sont bloqués il y a égalité

if pions_bloques == pions_ordi:
        egalite = True

if egalite:
        reset_commandes()
        boite_ordi.pack_forget()
        resultat = "Egalité"
        resultat_display.set(resultat)
        resultat_Label.config(text = resultat_display.get())
        boite_resultat.pack()

L’affichage

Maintenant que toutes les fonction sont définies, il faut afficher tous les différents éléments de la fenêtre:

titre.pack()
sep.pack()
contour1.grid(row = 0, column = 1 , sticky = W, padx = 100, pady = 0)
contour2.grid(row = 1, column = 1 , sticky = W, padx = 100, pady = 0)
contour3.grid(row = 2, column = 1 , sticky = W, padx = 100, pady = 0)
b_jouer.grid(row = 0, column = 2 , sticky = W, pady = 0)
b_regles.grid(row = 1, column = 2 , sticky = W, pady = 0)
b_personnaliser.grid(row = 2, column = 2 , sticky = W, pady = 0)
contour4.grid(row = 0, column = 3 , sticky = W, padx = 100, pady = 0)
contour5.grid(row = 1, column = 3 , sticky = W, padx = 100, pady = 0)
contour6.grid(row = 2, column = 3 , sticky = W, padx = 100, pady = 0)
regles_label.pack()
b_retour_regles.pack()
b_a1.grid(row = 0, column = 0, sticky = W)
b_a2.grid(row = 0, column = 1, sticky = W)
b_a3.grid(row = 0, column = 2, sticky = W)
b_b1.grid(row = 1, column = 0, sticky = W)
b_b2.grid(row = 1, column = 1, sticky = W)
b_b3.grid(row = 1, column = 2, sticky = W)
b_c1.grid(row = 2, column = 0, sticky = W)
b_c2.grid(row = 2, column = 1, sticky = W)
b_c3.grid(row = 2, column = 2, sticky = W)
b_ordi.pack(pady = 15)
b_retour_jeu.pack(pady = 15)
resultat_Label.pack(pady = 15)
scores.pack(pady = 15)
b_rejouer.pack(pady = 15)
boite_titre.pack()
boite_menu.pack(pady = 25)
retour_selection.pack(pady = 10)
couleur_entry.pack(pady = 15)
b_ok.pack(pady = 10)
b_couleur1.grid(row = 0, column = 0, sticky = W, pady = 5, padx = 5)
b_couleur2.grid(row = 0, column = 1, sticky = W, pady = 5, padx = 5)
b_couleur3.grid(row = 0, column = 2, sticky = W, pady = 5, padx = 5)
b_couleur_joueur.grid(row = 1, column = 0, sticky = W, pady = 5, padx = 5)
b_couleur_ordi.grid(row = 1, column = 1, sticky = W, pady = 5, padx = 5)
b_trouver_hex.grid(row = 1, column = 2, sticky = N, pady = 5, padx = 5)
b_retour_personnaliser.grid(row = 2, column = 1, sticky = N, pady = 10, padx = 5)

Et surtout ne pas oublier d’ouvrir la fenêtre en cas d’exéction du script

window.mainloop()

Captures d’écran

Si vous souhaitez vous mesurer à cette IA et vérifier qu’elle apprend bel et bien de ses erreurs, vous pourrez télécharger le script du projet (défi : dépasser un score de 17!).