Morbak500 : jeu de morpion (tic-tac-toe)

Description

Un petit jeu de morpion (tic-tac-toe) en python2.6.

- le premier script morbak500.pyw est relativement basique et est une réponse à la question que se posait un membre du site sur 'comment faire une interface Tkinter pour un morpion ?'.

- le deuxième morbak500c.pyw permet de changer de format (3x3,4x4,5x5) et contient une petite Intelligence Artificielle à 3 niveaux.

Source / Exemple :


# -*- coding: cp1252 -*-
################################################################################
#                                                                              #
#                               Morbak 500                                     #
#                                                                              #
#                            Jeu de morpion                                    #
#                             version 2.1                                      #
#                         Langage : Python 2.6                                 #
#                       Auteur : Guillaume Michon                              #
#                           date 14/05/1013                                    #
################################################################################

from Tkinter import *
from random import randrange

def nouvelle_partie():
    """Méthode appelée à chaque nouvelle partie. Demande le nom des joueurs et leur type (humain/ordinateur)."""
    global nomJoueur1,typeJoueur1,scoreJoueur1,niveauIntelOrdi1,nomJoueur2,typeJoueur2,scoreJoueur2,niveauIntelOrdi2,\
            tempsRepOrdi,var,fenetre2,entree,rb_intelOrdi1,rb_intelOrdi2,joueurActif

    #--- Réinitialisation des scores et des noms des joueurs ---#
    nomJoueur1 = 'Joueur 1'
    typeJoueur1 = 'humain'
    scoreJoueur1 = 0    
    canevaJoueur1.itemconfig(textNomJoueur1,text=nomJoueur1)
    canevaJoueur1.itemconfig(textScore1,text=str(scoreJoueur1))    
    niveauIntelOrdi1 = 0

    nomJoueur2 =  'Joueur 2'
    typeJoueur2 = 'humain'
    scoreJoueur2 = 0    
    canevaJoueur2.itemconfig(textNomJoueur2,text=nomJoueur2)
    canevaJoueur2.itemconfig(textScore2,text=str(scoreJoueur2))    
    niveauIntelOrdi2 = 0
    
    tempsRepOrdi = 750 #- temps entre chaque coup de l'ordi
    
    #--- Création des widgets de saisie de nom et de niveau d'intelligence de l'ordinateur pour le premier joueur ---#
    var = 1
    fenetre2 = Toplevel()
    fenetre2.resizable(0,0)
    tabGeometry = fenetre.geometry().split('+')
    pos = '+' + tabGeometry[1] + '+' + tabGeometry[2]
    fenetre2.geometry(pos)
    fenetre2.wait_visibility()
    fenetre2.grab_set()
    fenetre2.transient(fenetre)
    fenetre2.focus_force()
    fenetre2.protocol("WM_DELETE_WINDOW",fermeture_croix)

    label = Label(fenetre2,text='Nom du Joueur 1 :' )
    label.grid(column=0,row=0)
    entree = Entry(fenetre2,bd=5)
    entree.bind('<Return>',recup_nom)
    entree.grid(column=0,row=1)
    label = Label(fenetre2,text='Ordinateur :')
    label.grid(column=0,row=2)    
    rb_intelOrdi1 = IntVar()
    tabTexteValeur = [('sans',0),('MouDuBulbe',40),('MrToulMonde',85),('Kasparov',100)]
    ligne = 3
    for texte,valeur in tabTexteValeur:
        rb = Radiobutton(fenetre2,text=texte,variable=rb_intelOrdi1,value=valeur,command=sel_intelOrdi1)
        rb.grid(column=0,row=ligne,sticky=W)
        ligne += 1
    label = Label(fenetre2,text='Entrer ou Croix pour valider')
    label.grid(column=0,row=7)     
    #--- Attente de la fermeture de la fenêtre contenant ces widgets avant de poursuivre
    fenetre.wait_window(fenetre2)

    #--- Création des widgets de saisie de nom et de niveau d'intelligence de l'ordinateur pour le deuxième joueur ---#
    var = 2
    fenetre2 = Toplevel()
    fenetre2.resizable(0,0)    
    fenetre2.geometry(pos)
    fenetre2.wait_visibility()
    fenetre2.grab_set()
    fenetre2.transient(fenetre)
    fenetre2.focus_force()
    fenetre2.protocol("WM_DELETE_WINDOW",fermeture_croix)
    
    label = Label(fenetre2,text='Nom du Joueur 2 :')
    label.grid(column=0,row=0)
    entree = Entry(fenetre2,bd=5)
    entree.grid(column=0,row=1)
    entree.bind('<Return>',recup_nom)
    label = Label(fenetre2,text='Ordinateur :')
    label.grid(column=0,row=2)
    rb_intelOrdi2 = IntVar()
    ligne = 3    
    for texte,valeur in tabTexteValeur:
        rb = Radiobutton(fenetre2,text=texte,variable=rb_intelOrdi2,value=valeur,command=sel_intelOrdi2)
        rb.grid(column=0,row=ligne,sticky=W)
        ligne += 1
    label = Label(fenetre2,text='Entrer ou Croix pour valider')
    label.grid(column=0,row=7)     
    #--- Attente de la fermeture de la fenêtre contenant ces widgets avant de poursuivre
    fenetre.wait_window(fenetre2)
    
    #--- On determine le joueur qui a la main
    joueurActif = randrange(1,3)
    
    initialisation()

def fermeture_croix():
    """Méthode qui est invoquée quand on clique sur la croix de la fenêtre de saisie."""
    
    recup_nom('<Return>')
    
def recup_nom(event):
    """Méthode qui récupère le nom saisie pour chaque joueur."""
    global nomJoueur1,nomJoueur2
    
    saisie = entree.get()    
    if var == 1:
        if saisie != '':
            nomJoueur1 = saisie
            canevaJoueur1.itemconfig(textNomJoueur1,text=nomJoueur1)
    else:
        if saisie != '':
            nomJoueur2 = saisie
            canevaJoueur2.itemconfig(textNomJoueur2,text=nomJoueur2)
            
    fenetre2.destroy()

def sel_intelOrdi1():
    """Méthode qui détermine le niveau d'intelligence de l'ordinateur 1 en fonction des choix de l'utilisateur."""
    global niveauIntelOrdi1,typeJoueur1
    
    niveauIntelOrdi1 = rb_intelOrdi1.get()
    if niveauIntelOrdi1 == 0:
        entree.delete(0,END)
        typeJoueur1 = 'humain'
    else:
        typeJoueur1 = 'ordinateur'
        tabTexteValeur = [('sans',0),('MouDuBulbe',40),('MrToulMonde',85),('Kasparov',100)]
        for texteValeur in tabTexteValeur:
            if niveauIntelOrdi1 == texteValeur[1]:
                entree.delete(0,END)
                entree.insert(0,texteValeur[0])
                
def sel_intelOrdi2():
    """Méthode qui détermine le niveau d'intelligence de l'ordinateur 2 en fonction des choix de l'utilisateur."""    
    global niveauIntelOrdi2,typeJoueur2
    
    niveauIntelOrdi2 = rb_intelOrdi2.get()
    if niveauIntelOrdi2 == 0:
        entree.delete(0,END)
        typeJoueur2 = 'humain'
    else:
        typeJoueur2 = 'ordinateur'
        tabTexteValeur = [('sans',0),('MouDuBulbe',40),('MrToulMonde',85),('Kasparov',100)]
        for texteValeur in tabTexteValeur:
            if niveauIntelOrdi2 == texteValeur[1]:
                entree.delete(0,END)
                entree.insert(0,texteValeur[0])
    
def initialisation():
    """Méthode d'initialisation des variables de jeu."""
    global matriceJeu,tabCasesGagnantes

    # on efface tout
    caneva.delete(ALL)
    #on dessine la grille
    grille_jeu()

    # on initialise une matrice de jeu
    matriceJeu = []
    for i in range(nbrLigne):
        matriceJeu.append([0]*nbrColonne)

    # tableau qui contiendra les coordonnées matricielles des cases gagnantes
    tabCasesGagnantes = []

    # on cache tous les emotes
    canevaJoueur1.itemconfigure(emoteJoueur1Gagne,state=HIDDEN)
    canevaJoueur1.itemconfigure(emoteJoueur1Perdu,state=HIDDEN)
    canevaJoueur1.itemconfigure(emoteJoueur1MatchNul,state=HIDDEN)    
    canevaJoueur2.itemconfigure(emoteJoueur2Gagne,state=HIDDEN)
    canevaJoueur2.itemconfigure(emoteJoueur2Perdu,state=HIDDEN)
    canevaJoueur2.itemconfigure(emoteJoueur1MatchNul,state=HIDDEN)

    menuBarre.entryconfig(1,state=DISABLED)
    # actions à exécuter en fonction du joueur qui a la main 
    if joueurActif == 1:
        canevaJoueur1.config(bg='light green')
        canevaJoueur2.config(bg='ivory')
        if typeJoueur1 == 'humain':
            caneva.bind('<Button-1>',click_souris)
        else:
            fenetre.after(tempsRepOrdi,coup_ordi,2,22)
    else:
        canevaJoueur2.config(bg='light green')
        canevaJoueur1.config(bg='ivory')
        if typeJoueur2 == 'humain':
                caneva.bind('<Button-1>',click_souris)
        else:
            fenetre.after(tempsRepOrdi,coup_ordi,22,2)

def click_souris(event):
    """Méthode qui place le nombre du joueur humain qui a la main dans la matrice de jeu."""
    global joueurActif
    
    if event.x > margeGauche and event.x < margeGauche+(nbrLigne*largeurSprite) and event.y > margeHaut and event.y < margeHaut+(nbrColonne*hauteurSprite):
        indiceColonne = (event.x-margeGauche)/largeurSprite
        indiceLigne = (event.y-margeHaut)/hauteurSprite

        if matriceJeu[indiceLigne][indiceColonne] == 0:
            if joueurActif == 1:
                matriceJeu[indiceLigne][indiceColonne] = 2
                affichage()                
                verif_morpion(2,22)
            else:                                          
                matriceJeu[indiceLigne][indiceColonne] = 22
                verif_morpion(22,2)
                affichage()                

def coup_ordi(nombreJoueurActif,nombreAdversaire):
    """Fonction principale de l'intelligence artificielle."""
    # l'algorithmie fonctionne par priorité mais en fonction de l'IA certaines d'entre-elles seront évitées (marge d'erreur):
    #   1 - recherche d'un coup gagnant pour le joueur qui a la main
    #   2 - recherche d'un coup gagnant pour l'adversaire, pour contrecarré ce coup
    #   3 - recherche du coup le plus judicieux à jouer en fonction de la longueur des ensembles du joueur qui a la main
    #   4 - placement au hazard
    global joueurActif

    caneva.unbind('<Button-1>')
    # tableau contenant tous les coups possibles en coordonnée matricielle du joueur qui a la main
    tabCoupsJoueurActifPossibles = []
    # coordonnée matricielle du coup a jouer
    coordCoup = None

    if joueurActif == 1:
        niveauIntelOrdi = niveauIntelOrdi1
    else:
        niveauIntelOrdi = niveauIntelOrdi2

    # un jet de 100 est effectué, si sa valeur est supérieur au niveau de l'IA, certains algorithmes de recherche de positionnement seront évités 
    hazard = randrange(0,100)
    if hazard <= niveauIntelOrdi:
        #--- 1ère priorité
        tabCoupsJoueurActifPossibles = recherche_coups_possibles(nombreJoueurActif,nombreAdversaire)
        # si dans le tableau renvoyé par 'recherche_coups_possibles' une chaine de coups dans une direction n'a qu'un élément alors c'est un coup gagnant
        for coup in tabCoupsJoueurActifPossibles:
            if len(coup) == 1:
                coordCoup = coup[0]
                break

    hazard = randrange(0,100)
    if hazard <= niveauIntelOrdi:
        #--- 2ème priorité
        if not coordCoup :
            tabCoupsAdversesPossibles = recherche_coups_possibles(nombreAdversaire,nombreJoueurActif)
        # si dans le tableau renvoyé par 'recherche_coups_possibles' une chaine de coups dans une direction n'a qu'un élément alors c'est un coup gagnant                        
            for coup in tabCoupsAdversesPossibles:
                if len(coup) == 1:
                    coordCoup = coup[0]
                    break

    hazard = randrange(0,100)
    if hazard <= niveauIntelOrdi:
        #--- 3ème priorité
        if not coordCoup:
            # si au moins une forme a été placée 'tabCoupsJoueurActifPossibles' n'est pas vide
            if tabCoupsJoueurActifPossibles:
                longeurRef = 1000
                # tableau contenant les plus petites chaines de coups possibles
                tabCoupsJudicieux = []
                # remplissage de ce tableau
                for chaineCoupsPossibles in tabCoupsJoueurActifPossibles:
                    if len(chaineCoupsPossibles) < longeurRef:
                        tabCoupsJudicieux = []        
                        longeurRef = len(chaineCoupsPossibles)
                        tabCoupsJudicieux.append(chaineCoupsPossibles)
                    elif len(chaineCoupsPossibles) == longeurRef:
                        tabCoupsJudicieux.append(chaineCoupsPossibles)
                # on tire au hazard une direction dans ce tableau
                hazard = randrange(len(tabCoupsJudicieux))
                directionRetenue = tabCoupsJudicieux[hazard]
                # et dans la chaine retenue on tire au hazard une position
                hazard = randrange(len(directionRetenue))
                coordCoup = directionRetenue[hazard]

    #--- 4ème priorité                                       
    if not coordCoup :
        # tableau contenant tous les coups encore possibles 
        tabZero = []
        for indiceLigne in range(len(matriceJeu)):
            for indiceColonne in range(len(matriceJeu[0])):
                if matriceJeu[indiceLigne][indiceColonne] == 0:
                    tabZero.append([indiceLigne,indiceColonne])
        if tabZero:
            hazard = randrange(0,len(tabZero))
            coordCoup = tabZero[hazard]
        else:
            return

    # on positionne le chiffre du joueur qui a la main dans la matrice de jeu                                   
    matriceJeu[coordCoup[0]][coordCoup[1]] = nombreJoueurActif
    # on reactualise l'affichage
    affichage()
    # on verifie si un morpion s'est formé
    verif_morpion(nombreJoueurActif,nombreAdversaire)
    affichage()

def recherche_coups_possibles(nombre1,nombre2):
    """" Fonction de recherche de tous les positionnements possibles en ligne,colonne et diagonale (coord. matricielles des zéro) en fonction d'un chiffre particulier."""
    global tabCasesGagnantes
    
    # tableau contenant toutes les chaines de coups possibles
    tabCoupsPossibles = []

    #--- recherche en Ligne
    indiceLigne = 0
    for ligne in matriceJeu:
        tabZero = [] # tableau contenant tous les zero de l'exploration dans une direction 
        tabCasesGagnantes = [] # le tableau contenant toutes les coordonées matricielles des cases gagnantes
        if nombre1 in ligne and nombre2 not in ligne:
            for indiceColonne in range(len(ligne)):
                # dans chaque direction d'exploration le tableau de coord. des cases gagnantes est rempli des coordonnées d'exploration
                tabCasesGagnantes.append([indiceLigne,indiceColonne])
                if matriceJeu[indiceLigne][indiceColonne] == 0:
                    tabZero.append([indiceLigne,indiceColonne])
            # si à la fin d'une exploration le tableau des zero est vide il y a forcemment morpion de formé
            if not tabZero:
                retour = 'morpion'
                return retour
            tabCoupsPossibles.append(tabZero)
        indiceLigne += 1

    #--- recherche en Colonne
    for indiceColonne in range(len(matriceJeu[0])):
        colonne = []
        tabZero = []
        tabCasesGagnantes = []        
        for indiceLigne in range(len(matriceJeu)):
            colonne.append(matriceJeu[indiceLigne][indiceColonne])
        if nombre1 in colonne and nombre2 not in colonne:
            for indLigne in range(len(colonne)):
                tabCasesGagnantes.append([indLigne,indiceColonne])
                if colonne[indLigne] == 0:
                    tabZero.append([indLigne,indiceColonne])
            if not tabZero:
                retour = 'morpion'
                return retour
            tabCoupsPossibles.append(tabZero)

    #--- recherche suivant la Diagonale gauche-droite
    diagonale = []
    tabZero = []
    tabCasesGagnantes = []    
    for indiceLigneColonne in range(len(matriceJeu)):
        diagonale.append(matriceJeu[indiceLigneColonne][indiceLigneColonne])
    if nombre1 in diagonale and nombre2 not in diagonale:
        for indiceLigneColonne in range(len(diagonale)):
            tabCasesGagnantes.append([indiceLigneColonne,indiceLigneColonne])
            if diagonale[indiceLigneColonne] == 0:
                tabZero.append([indiceLigneColonne,indiceLigneColonne])
        if not tabZero:
            retour = 'morpion'
            return retour
        tabCoupsPossibles.append(tabZero)

    #--- recherche suivant la Diagonale droite-gauche
    diagonale = []
    tabZero = []
    tabCasesGagnantes = []    
    for indiceLigneColonne in range(len(matriceJeu)):
        diagonale.append(matriceJeu[indiceLigneColonne][len(matriceJeu[0])-1-indiceLigneColonne])
    if nombre1 in diagonale and nombre2 not in diagonale:
        for indiceLigneColonne in range(len(diagonale)):
            tabCasesGagnantes.append([indiceLigneColonne,len(matriceJeu[0])-1-indiceLigneColonne])            
            if diagonale[indiceLigneColonne] == 0:
                tabZero.append([indiceLigneColonne,len(matriceJeu[0])-1-indiceLigneColonne])
        if not tabZero:
            retour = 'morpion'
            return retour
        tabCoupsPossibles.append(tabZero)

    tabZero = []
    tabCasesGagnantes = []    
    for indiceLigne in range(len(matriceJeu)):
        for indiceColonne in range(len(matriceJeu[0])):
            if matriceJeu[indiceLigne][indiceColonne] == 0:
                tabZero.append([indiceLigne,indiceColonne])

    return tabCoupsPossibles
        
def verif_morpion(nombreJoueurActif,nombreAdversaire):
    """Méthode qui vérifie si un morpion s'est formé."""

    # 'recherche_coups_possibles' renvoie soit un tableau de coord. de zéro correspondant aux placements possibles qui peuvent encore faire un morpion
    # soit un tableau vide si ce n'est plus le cas, soit le mot 'morpion' si le dernier placement en a formé un
    retourDeRecherche = recherche_coups_possibles(nombreJoueurActif,nombreAdversaire)

    # si 'recherche_coups_possibles' a renvoyé un tableau de coord de zéro vide ou non
    if retourDeRecherche != 'morpion':
        la_main_passe()

    # si ce tableau est vide on regarde si des zéro sont encore présent dans la matrice de jeu
    if not retourDeRecherche:
        matchNul = True
        for ligne in matriceJeu:
            if 0 in ligne:
                matchNul = False
        if matchNul:
            menuBarre.entryconfig(1,state=ACTIVE)
            canevaJoueur1.itemconfigure(emoteJoueur1MatchNul,state=NORMAL)
            canevaJoueur2.itemconfigure(emoteJoueur1MatchNul,state=NORMAL)

    # si 'recherche_coups_possibles' a décelé un morpion
    elif retourDeRecherche == 'morpion':
        affichage()
        partie_gagnee()       

def la_main_passe():
    """"Méthode qui effectue les actions nécessaires lorsque la main passe."""
    global joueurActif

    joueurActif += 1
    if joueurActif == 3:
        joueurActif = 1
    if joueurActif == 1 :
        canevaJoueur1.config(bg='light green')
        canevaJoueur2.config(bg='ivory')
        if typeJoueur1 == 'humain':
            caneva.bind('<Button-1>',click_souris)
        else:
            fenetre.after(1000,coup_ordi,2,22)
        
    else:
        canevaJoueur2.config(bg='light green')
        canevaJoueur1.config(bg='ivory')
        if typeJoueur2 == 'humain':
            caneva.bind('<Button-1>',click_souris)
        else:
            fenetre.after(tempsRepOrdi,coup_ordi,22,2)
    
def partie_gagnee():
    """"Méthode qui effectue les actions nécessaires lorsque la partie est gagnée."""
    global scoreJoueur1,scoreJoueur2

    caneva.unbind('<Button-1>')
    menuBarre.entryconfig(1,state=ACTIVE)
    if joueurActif == 1 :
        scoreJoueur1 += 1
        canevaJoueur1.itemconfig(textScore1,text=str(scoreJoueur1))
        canevaJoueur1.itemconfigure(emoteJoueur1Gagne,state=NORMAL)
        canevaJoueur2.itemconfigure(emoteJoueur1Perdu,state=NORMAL)
    else:
        scoreJoueur2 += 1
        canevaJoueur2.itemconfig(textScore2,text=str(scoreJoueur2))
        canevaJoueur1.itemconfigure(emoteJoueur1Perdu,state=NORMAL)
        canevaJoueur2.itemconfigure(emoteJoueur1Gagne,state=NORMAL)
        
def affichage():
    """Méthode actualisant l'affichage de la mtrice de jeu."""
    
    for indiceLigne in range(len(matriceJeu)):
        for indiceColonne in range(len(matriceJeu[0])):
            coordX = margeGauche+(indiceColonne*largeurSprite)
            coordY = margeHaut+(indiceLigne*hauteurSprite)
            if matriceJeu[indiceLigne][indiceColonne] == 2:
                caneva.create_image(coordX,coordY,image=imageCroix,anchor=NW)
            if matriceJeu[indiceLigne][indiceColonne] == 22:
                caneva.create_image(coordX,coordY,image=imageRond,anchor=NW)                

            if tabCasesGagnantes:
                 for case in tabCasesGagnantes:
                     rectangle = caneva.create_rectangle(case[1]*largeurSprite+margeGauche,case[0]*hauteurSprite+margeHaut,
                                        case[1]*largeurSprite+margeGauche+largeurSprite,case[0]*largeurSprite+margeHaut+hauteurSprite,fill='gold')
                     caneva.lower(rectangle)

def grille_jeu():
    """Méthode affichant la grille de jeu."""
    for coordY_ligne in range(margeHaut,(nbrLigne*hauteurSprite)+margeHaut+1,hauteurSprite):
        if (coordY_ligne-margeHaut) % (nbrLigne*hauteurSprite) == 0:
            epaisseur = 5
        else:
            epaisseur = 1
        
        caneva.create_line(margeGauche,coordY_ligne,(nbrColonne*largeurSprite)+margeGauche,coordY_ligne,width=epaisseur)

    for coordX_colonne in range(margeGauche,(nbrColonne*largeurSprite)+margeGauche+1,largeurSprite):
        if (coordX_colonne-margeGauche) % (nbrColonne*largeurSprite) == 0:
            epaisseur = 5
        else:
            epaisseur = 2
        
        caneva.create_line(coordX_colonne,margeHaut,coordX_colonne,(nbrLigne*hauteurSprite)+margeHaut,width=epaisseur)

def format3x3():
    """Méthode passant la matrice de jeu et le caneva principal au format 3x3."""
    global nbrLigne,nbrColonne

    nbrLigne = nbrColonne = 3

    caneva.delete(ALL)
    caneva.config(width=(2*margeGauche)+(nbrColonne*largeurSprite),height=(2*margeHaut)+(nbrLigne*hauteurSprite))
    canevaJoueur1.config(width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite))
    canevaJoueur2.config(width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite))                             
    grille_jeu()

    nouvelle_partie()
    
def format4x4():
    """Méthode passant la matrice de jeu et le caneva principal au format 4x4."""    
    global nbrLigne,nbrColonne
    
    nbrLigne = nbrColonne = 4

    caneva.delete(ALL)
    caneva.config(width=(2*margeGauche)+(nbrColonne*largeurSprite),height=(2*margeHaut)+(nbrLigne*hauteurSprite))
    canevaJoueur1.config(width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite))
    canevaJoueur2.config(width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite))                             
    grille_jeu()

    nouvelle_partie()
    
def format5x5():
    """Méthode passant la matrice de jeu et le caneva principal au format 5x5."""    
    global nbrLigne,nbrColonne
    
    nbrLigne = nbrColonne = 5

    caneva.delete(ALL)
    caneva.config(width=(2*margeGauche)+(nbrColonne*largeurSprite),height=(2*margeHaut)+(nbrLigne*hauteurSprite))
    canevaJoueur1.config(width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite))
    canevaJoueur2.config(width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite))                             
    grille_jeu()

    nouvelle_partie()

def quitter():
    """Quitte l'application."""

    fenetre.quit()       
    fenetre.destroy()
    
if __name__ == '__main__':
    #--- Fenêtre Principale ---
    fenetre = Tk()
    fenetre.configure(bg='light blue')
    fenetre.title("Morbak500")
    fenetre.resizable(0,0)
    hauteurEcran = fenetre.winfo_height()
    largeurEcran = fenetre.winfo_width()
    fenetre.winfo_screenwidth()
    pos_x = str(((fenetre.winfo_screenwidth()-largeurEcran)/2)-300)
    pos_y = str(((fenetre.winfo_screenheight()-hauteurEcran)/2)-300)
    pos = '+' + pos_x + '+' + pos_y
    fenetre.geometry(pos)

    #--- Chargement des images ---
    imageCroix = PhotoImage(file="croix.gif")
    imageRond = PhotoImage(file="rond.gif")
    imageEmoteGagne = PhotoImage(file="emoteGagne.gif")
    imageEmotePerdu = PhotoImage(file="emotePerdu.gif")
    imageEmoteMatchNul = PhotoImage(file="emoteMatchNul.gif")

    #--- Variables de mise en forme ---
    largeurSprite = imageCroix.width()
    hauteurSprite = imageRond.height()
    margeGauche, margeHaut = 20, 20
    nbrLigne, nbrColonne = 3, 3

    #--- Caneva principal ---
    caneva = Canvas(fenetre,bg='light blue',width=(2*margeGauche)+(nbrColonne*largeurSprite),height=(2*margeHaut)+(nbrLigne*hauteurSprite),relief='groove')
    caneva.grid(row=0,column=1)

    #--- Caneva du joueur 1 ---
    canevaJoueur1 = Canvas(fenetre,bg='ivory',width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite),relief='ridge')
    canevaJoueur1.grid(row=0,column=0)
    canevaJoueur1.create_image(40,10,image=imageCroix,anchor=NW)
    nomJoueur1 = 'Joueur 1'
    textNomJoueur1 = canevaJoueur1.create_text(75,100,text=nomJoueur1,anchor=N,font="Century 16 normal bold",fill='black')
    scoreJoueur1 = 0
    textScore1 = canevaJoueur1.create_text(75,150,text=str(scoreJoueur1),anchor=N,font="Century 28 normal bold",fill='black')
    emoteJoueur1Gagne = canevaJoueur1.create_image(45,200,image=imageEmoteGagne,anchor=NW,state=HIDDEN)    
    emoteJoueur1Perdu = canevaJoueur1.create_image(45,200,image=imageEmotePerdu,anchor=NW,state=HIDDEN)
    emoteJoueur1MatchNul = canevaJoueur1.create_image(45,200,image=imageEmoteMatchNul,anchor=NW,state=HIDDEN)

    #--- Caneva du joueur 2 ---
    canevaJoueur2 = Canvas(fenetre,bg='ivory',width=150,height=(2*margeHaut)+(nbrLigne*hauteurSprite),relief='ridge')
    canevaJoueur2.grid(row=0,column=2)
    canevaJoueur2.create_image(40,10,image=imageRond,anchor=NW)
    nomJoueur2 = 'Joueur 2'
    textNomJoueur2 = canevaJoueur2.create_text(75,100,text=nomJoueur2,anchor=N,font="Century 16 normal bold",fill='black')
    scoreJoueur2 = 0 
    textScore2 = canevaJoueur2.create_text(75,150,text=str(scoreJoueur2),anchor=N,font="Century 28 normal bold",fill='black')
    emoteJoueur2Gagne = canevaJoueur2.create_image(45,200,image=imageEmoteGagne,anchor=NW,state=HIDDEN)  
    emoteJoueur2Perdu = canevaJoueur2.create_image(45,200,image=imageEmotePerdu,anchor=NW,state=HIDDEN)
    emoteJoueur2MatchNul = canevaJoueur2.create_image(45,200,image=imageEmoteMatchNul,anchor=NW,state=HIDDEN)

    #--- Barre de menu ---
    menuBarre = Menu(fenetre,tearoff=0)
    fenetre.config(menu=menuBarre)    
    menuNllePartie = Menu(menuBarre,tearoff=0)
    menuBarre.add_cascade(label='Nouvelle Partie',menu=menuNllePartie)

    menuFormat = Menu(menuNllePartie)
    menuNllePartie.add_cascade(label='Format',menu=menuFormat)
    menuFormat.add_radiobutton(label='3x3',command=format3x3)
    menuFormat.add_radiobutton(label='4x4',command=format4x4)
    menuFormat.add_radiobutton(label='5x5',command=format5x5)
    menuBarre.add_command(label='Nouvelle Manche',command=initialisation,state=DISABLED)

    menuNllePartie.add_separator()
    menuNllePartie.add_command(label='Quitter',command=quitter)

    grille_jeu()
    fenetre.mainloop()

Codes Sources

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.