from tkinter import * import tkinter.font as font mainWindow = Tk() # Creation de la fenetre principale. mainWindow.geometry('800x800') # Initialisation de la taille de la fenetre principale. mainWindow.title("Jeu - Morpion") # Titre situe en haut a gauche. mainWindow['bg'] = '#72E8A9' # Ajouter un fond de couleur. mainWindow.resizable(height=True,width=True) # Autoriser ou non le redimensionage. mainWindow.minsize(height=700, width=600) # Definie la taille minimal de la fenetre. # Definition d'une police def defindFont(typ,s,w='normal'): """ Fonction qui renvoie une police avec sa taille et son type. """ return font.Font(family=typ, size=s, weight=w) fontTitle = defindFont('Verdana','40','bold') mainTitle = Label(mainWindow, text="Jeu - Morpion", fg='#FFC162', bg='#55A1A6') # Creation d'une instance label (bloc) pour stocker le titre. mainTitle['font'] = fontTitle mainTitle.pack(fill=X,ipady=15) # Affichage de l'instance cree ci-dessus. fill=X, remplie tous l'espace possible horizontalement, ipady: crée un espacement interne dans le bloc. def update_size(event): """ Fonction utiliser pour gerer le responsive des widgets. """ # Modifie la largeur en fonction de la taille de la hauteur /// fonction qui s'execute des que la taille de 'mainFenetre' change. boardFrame.config(width=boardFrame.winfo_height()) # Modifie la largeur et la hauteur des case en fonction de la taille de carre --------------------------- for case in liste_case: case.config(width=1/4*(boardFrameInter.winfo_width()), height=1/4*(boardFrameInter.winfo_width())) #---------------------------------------------------------------------------------------------------------- # Modifie les coordonees des croix------------------------------------ width, height = liste_case[0].winfo_width(), liste_case[0].winfo_height() for croix in liste_croix: croix[0].coords(croix[1],0,0,width,height) croix[0].coords(croix[2],0,height,width,0) #---------------------------------------------------------------------- # Modifie les coordonees des ronds ------------------------------------ for rond in liste_ronds: width, height, r = 1/2*liste_case[0].winfo_width(), 1/2*liste_case[0].winfo_height(), 1/1.15*width rond[0].coords(rond[1], width-r,height-r,width+r,height+r) def plateau(): """ Fonction qui afficher le plateau de jeu. """ #borderPlayButton.place_forget() #board.pack_forget() board.pack(fill=Y, expand=True, pady=150) gameTitleInter.pack(fill=X) gameTitle.pack(side=LEFT) boardFrame.pack(fill=Y, expand=True) boardFrameInter.place(relheight=1.0,relwidth=1.0) # Afficher les lignes -------------------------------------- liste_line[0].place(relx=0.33, anchor=CENTER, relheight=2) liste_line[1].place(rely=0.33, anchor=CENTER, relwidth=2) liste_line[2].place(relx=0.66, anchor=CENTER, relheight=2) liste_line[3].place(rely=0.66, anchor=CENTER, relwidth=2) #-------------------------------------------------------------- # Afficher les frame invisible de chaque case --------------------------- row = 0 index = 0 for i in range(3): column = 0 for j in range(3): liste_case[index].grid(row=row,column=column) column+=1 index+=1 row += 1 #------------------------------------------------------------------------- finishLabelInter.pack(fill=X) def verify(pion, case_joue): """ Fonction qui verifie si le jeu est finie. """ global liste global joueurs dico_inter = {} num = 1 for case in liste_case: dico_inter[case] = "C"+str(num) num+=1 index1 = 0 for liste_p in liste_plateau: index2 = 0 for case in liste_p: if case == dico_inter[case_joue]: liste[index1][index2] = pion index2 += 1 index1 += 1 # Verification pour les lignes et les colonnes for i in range(3): if liste[i][0] == liste[i][1] == liste[i][2] and liste[i][0] != None: return True, joueurs[liste[i][0]] if liste[0][i] == liste[1][i] == liste[2][i] and liste[0][i] != None: return True, joueurs[liste[0][i]] # Verification pour les diagonales if liste[0][0] != None: if liste[0][0] == liste[1][1] == liste[2][2]: return True, joueurs[liste[1][1]] if liste[0][2] != None: if liste[0][2] == liste[1][1] == liste[2][0]: return True, joueurs[liste[1][1]] # Verification d'une egalite if None not in liste[0] and None not in liste[1] and None not in liste[2]: return True, "egalite" return False, None def play(): ############################# #### Programme PRINCIPAL #### ############################# def clic(event): global tour global joueurs """ Fonction permettant de : -Placer les croix et les ronds en alternant. -Change le labelTitle en fonction du tour. -Afficher la fin de la partie """ if tour == 1: event.widget.winfo_children()[0].place(relheight=1.0,relwidth=1.0) else: event.widget.winfo_children()[1].place(relheight=1.0,relwidth=1.0) res = verify(tour, event.widget) if tour == 1: tour = 2 else: tour = 1 gameTitle.config(text=("C'est au tour de : {}".format(joueurs[tour]))) if res[0] == True: """ Le jeu est termine alors ont unbind les events de clique sur des frames. """ for case in liste_case: case.unbind('') if tour == 1: tour = 2 else: tour = 1 gameTitle.config(text=("Le jeu est termine...")) finishLabel.pack(side=LEFT) if res[1] == "egalite": finishLabel.config(text="Match nul...") else: finishLabel.config(text="Le gagnant est : {}".format(joueurs[tour])) restartButton.pack() # Evenement qui detecte un clic sur les frame en question : for case in liste_case: case.bind('', clic) def restart(): """ Fonction qui restart le jeu. """ global plateau_dico global liste global joueurs global tour tab = liste_case for case in tab: case.winfo_children()[0].place_forget() case.winfo_children()[1].place_forget() finishLabel.pack_forget() restartButton.pack_forget() liste=[[None,None,None],[None,None,None],[None,None,None]] joueurs = {1:"X",2:"O"} tour = 1 gameTitle.config(text=("C'est au tour de : {}".format(joueurs[tour]))) play() def close(): """ Fonction qui ferme la fenetre principal. """ mainWindow.destroy() ############################### ######### Page MENU ########### ############################### """ Creation des widget du menu principal. """ borderPlayButton = Frame(mainWindow, bg='#205EA0', pady=2, padx=2) borderPlayButton.place(relx=0.5, rely=0.4, anchor=N) # anchor definie le point d'attache du bloc (ici:NORD, par default:NORD-WEST) playButton = Button(borderPlayButton, text="Jouer", bg='#55A1A6', fg='#FFC162', activebackground='#55A1A6', font=('Verdana',30), bd=0, command=plateau) # Creation d'une instance boutton (bloc) pour stocker le boutton jouer. playButton.pack() borderQuitButton = Frame(mainWindow, bg='#205EA0', pady=2, padx=2) borderQuitButton.place(relx=1, rely=1, anchor=SE) quitButton = Button(borderQuitButton, text="Quitter", bg='#FF7D7B', fg='#205EA0', activebackground='#FFB2A6', font=('Verdana',30), bd=0, command=close) quitButton.pack() ############################### ######### Page JEU ############ ############################### """ Creation des widget du menu jeu. """ board = Frame(mainWindow, bg="#72E8A9") gameTitleInter = Frame(board, bg="#72E8A9") gameTitle = Label(gameTitleInter ,text="C'est au tour de : X", font=('Verdana',22), fg="white", bg="#72E8A9") boardFrame = Frame(board, bg="#72E8A9") mainWindow.bind("", update_size) # Event qui s'execute des que la taille de la fenetre principal change. boardFrameInter = Frame(boardFrame, bg='#72E8A9') boardFrameInter.rowconfigure(0,weight=1) boardFrameInter.rowconfigure(1,weight=1) boardFrameInter.rowconfigure(2,weight=1) boardFrameInter.columnconfigure(0,weight=1) boardFrameInter.columnconfigure(1,weight=1) boardFrameInter.columnconfigure(2,weight=1) # Lignes de jeu ------------------------------------------ liste_line = [] for i in range(2): liste_line.append(Frame(boardFrameInter, bg='white', width=3)) liste_line.append(Frame(boardFrameInter, bg='white', height=3)) #--------------------------------------------------------- # Case de jeu ----------------------------------------- liste_case = [] for i in range(9): liste_case.append(Frame(boardFrameInter, bg='#72E8A9',cursor='hand2')) #------------------------------------------------------- finishLabelInter = Label(board, bg="#72E8A9") finishLabel = Label(finishLabelInter, font=('Verdana',22), fg="red", bg="#72E8A9") restartButton = Button(board, text="Rejouer", bg='#55A1A6', fg='#FFC162', activebackground='#55A1A6', font=('Verdana',22), bd=0, command=restart) # Pion Croix --------------------------------------------------------------------- liste_croix = [[],[],[],[],[],[],[],[],[]] index = 0 width, height = liste_case[0].winfo_width(), liste_case[0].winfo_height() for case in liste_case: liste_croix[index].append(Canvas(case , bg='#72E8A9', highlightthickness=0)) liste_croix[index].append(liste_croix[index][0].create_line(0,0,width,height, fill="blue",width=3)) liste_croix[index].append(liste_croix[index][0].create_line(0,height,width,0, fill="blue",width=3)) index += 1 # ---------------------------------------------------------------------------------- # Plan Ronds ----------------------------------------------------------------------- liste_ronds = [[],[],[],[],[],[],[],[],[]] index = 0 width1, height1, r = 1/2*liste_case[0].winfo_width(), 1/2*liste_case[0].winfo_height(), 1/1.15*liste_case[0].winfo_width() for case in liste_case: liste_ronds[index].append(Canvas(case, bg='#72E8A9', highlightthickness=0)) liste_ronds[index].append(liste_ronds[index][0].create_oval(width1-r,height1-r,width1+r,height1+r,width=3,fill="#72E8A9", outline="#FFB200")) index += 1 # ---------------------------------------------------------------------------------- liste_ronds[0][0].place(relheight=1.0,relwidth=1.0) # IMPOSSIBLE de faire spawn ce widget ''' for rond in liste_ronds: rond[0].place(relheight=1.0,relwidth=1.0)''' ############################### #### Initialisation Du Jeu #### ############################### liste=[[None,None,None],[None,None,None],[None,None,None]] liste_plateau = [["C7","C8","C9"],["C4","C5","C6"],["C1","C2","C3"]] joueurs = {1:"X",2:"O"} tour = 1 play() mainWindow.mainloop() # Cree une boucle infnie qui affiche la fenetre.