class Modele: """[TKINTER] Gère l'interface d'une instance de Jeu. """ def __init__(self): """Modele -> Modele Initialise l'interface et la loop du programme.""" self.__master = tk.Tk() self.__master.title("Le jeu de la vie") self.__master.resizable(width=False, height=False) self.__jeu = Jeu(TX, TY) self.__time = TIME # UI fUI = tk.Frame() self.__lGen = tk.Label(fUI, text="GEN : 0", font=("Arial", 15)) self.__lGen.pack() # Inputs fInputs = tk.Frame(fUI, bd=3, relief="sunken") self.__eNbCells = tk.Entry(fInputs, width="10", justify="center") self.__eNbCells.pack(pady=5) self.__bAlea = tk.Button(fInputs, text="Générer", width=BUTWIDTH, command=self.genAlea) self.__bAlea.pack(pady=5) fSep = tk.Frame(fInputs, bd=1, height=2, relief="sunken") fSep.pack(pady=10, fill="x") lLignes = tk.Label(fInputs, text="Lignes :") lLignes.pack() self.__eLignes = tk.Entry(fInputs, width=10, justify="center") self.__eLignes.pack() lLignes = tk.Label(fInputs, text="Colonnes :") lLignes.pack() self.__eColonnes = tk.Entry(fInputs, width=10, justify="center") self.__eColonnes.pack() self.__bReinit = tk.Button(fInputs, text="Modifier", width=BUTWIDTH, command=self.reinit) self.__bReinit.pack(pady=5) fInputs.pack(pady=5) # # # self.__lStable = tk.Label(fUI, text="N/A", padx=5, font=("Arial", 12), fg="orange") self.__lStable.pack(pady=15) # Timer fTimer = tk.Frame(fUI, bd=3, relief="sunken") self.__bSuiv = tk.Button(fTimer, text="Suivant", width=BUTWIDTH, command=self.suivant) self.__bSuiv.pack(pady=5) lTimer = tk.Label(fTimer, text="Timer :\n[5 ; 5000]") lTimer.pack() self.__eTimer = tk.Entry(fTimer, width=10, justify="center") self.__eTimer.pack() bTimer = tk.Button(fTimer, text="Changer", width=BUTWIDTH, command=self.changeTimer) bTimer.pack(pady=5) fTimer.pack(pady=5) # # # fUI.grid(row=1, column=0, rowspan=2) # # # # Start, Stop, Clear fButtons = tk.Frame(bd=2, relief="sunken") self.__bStart = tk.Button(fButtons, text="Start", width=BUTWIDTH, command=self.start) self.__bStart.grid(row=0, column=1, padx=5, pady=3) self.__bStop = tk.Button(fButtons, text="Stop", width=BUTWIDTH, state="disabled", command=self.stop) self.__bStop.grid(row=0, column=2, padx=5, pady=3) self.__bClear = tk.Button(fButtons, text="Clear", width=BUTWIDTH, command=self.clear) self.__bClear.grid(row=0, column=3, padx=5, pady=3) fButtons.grid(row=0, column=1, pady=5) # # # # Cases self.__fCases = tk.Frame(bd=3, bg="white", relief="sunken") self.__cases = self.createGrille(TX, TY) self.__fCases.grid(row=1, column=1, padx=10, pady=10) # # # self.__master.mainloop() def controllerClickCase(self, x, y): """Modele (modif), int, int -> function Renvoie la fonction 'clickCase' pour les coordonnées (x, y).""" def clickCase(): """None -> None Change l'état de la cellule (x, y).""" color = "" if self.__jeu.etat(x, y) == False: self.__jeu.changeEtat(x, y, True) color = "black" else: self.__jeu.changeEtat(x, y, False) color = "white" self.__cases[x][y].configure(bg=color) self.reinitLabels() self.stopState() return clickCase def metAJour(self): """Modele (modif) -> None Met à jour l'interface.""" for i in range(self.__jeu.tx()): for j in range(self.__jeu.ty()): if self.__jeu.etat(i, j): self.__cases[i][j].configure(bg="black") else: self.__cases[i][j].configure(bg="white") def clear(self): """Modele (modif) -> None Tue toutes les cellules.""" if self.__jeu.nb_viv() != 0: for i in range(self.__jeu.tx()): for j in range(self.__jeu.ty()): self.__jeu.changeEtat(i, j, False) self.__cases[i][j].configure(bg="white") self.clearState() def suivant(self): """Modele (modif) -> None Passe à la génération suivante.""" self.__jeu.etapeSuivante() if (self.__jeu.stable()): self.__lStable.configure(text="STABLE", fg="green") self.__lGen.configure(fg="green") self.__bSuiv.configure(state="disabled") self.__bReinit.configure(state="normal") self.__start = False if self.__jeu.nb_viv() != 0: self.__bStart.configure(state="disabled") self.__bStop.configure(state="disabled") self.__bClear.configure(state="normal") self.disableButtons(False) else: self.__lStable.configure(text="PAS STABLE", fg="red") self.__lGen.configure(text="GEN : " + str(self.__jeu.gen()), fg="red") self.metAJour() if (self.__start): self.__master.after(self.__time, self.suivant) def createGrille(self, tx, ty): """Modele, int, int -> list(list(Button)) Renvoie une grille de bouttons.""" cases = [] for i in range(tx): ligne = [] for j in range(ty): btn = tk.Button(self.__fCases, bg="white", relief="flat", bd=0, command=self.controllerClickCase(i, j)) btn.grid(row=i, column=j) ligne.append(btn) cases.append(ligne) return cases def reinit(self): """Modele (modif)-> None Change la grille du jeu avec les nouveau paramètres.""" x, y = self.__eLignes.get(), self.__eColonnes.get() if est_entier(x) and est_entier(y): self.__fCases.destroy() x, y = int(x), int(y) self.__jeu = Jeu(x, y) self.__fCases = tk.Frame(bd=3, bg="white", relief="sunken") self.__cases = self.createGrille(x, y) self.__fCases.grid(row=1, column=1, padx=10, pady=10) self.reinitLabels() else: self.__eLignes.delete(0, "end") self.__eColonnes.delete(0, "end") def start(self): """Modele -> None Lance l'éxecution du jeu.""" self.__start = True self.__bSuiv.invoke() if not self.__jeu.stable(): self.startState() def stop(self): """Modele -> None Arrête l'éxecution du jeu.""" self.__start = False self.stopState() def startState(self): """Modele (modif) -> None Affecte un état adapté aux boutons lorsque le jeu est en éxecution.""" self.__bSuiv.configure(state="disabled") self.__bClear.configure(state="disabled") self.__bStart.configure(state="disabled") self.__bReinit.configure(state="disabled") self.__bStop.configure(state="normal") self.__bAlea.configure(state="disabled") self.disableButtons(True) def stopState(self): """Modele (modif) -> None Affecte un état adapté aux boutons lorsque le jeu n'est plus en éxecution.""" self.__bStop.configure(state="disabled") self.__bSuiv.configure(state="normal") self.__bStart.configure(state="normal") self.__bClear.configure(state="normal") self.__bReinit.configure(state="normal") self.__bAlea.configure(state="normal") self.disableButtons(False) def clearState(self): """Modele (modif) -> None Affecte un état adapté aux boutons lorsque le jeu n'est plus en éxecution.""" self.__lStable.configure(text="N/A", fg="orange") self.__lGen.configure(text="GEN : 0", fg="black") self.__bStart.configure(state="normal") self.__bStop.configure(state="disabled") self.__bSuiv.configure(state="normal") self.__bReinit.configure(state="normal") self.__bAlea.configure(state="normal") def reinitLabels(self): """Modele (modif) -> None Réinitialise le texte des labels.""" self.__jeu.resetGen() self.__lGen.configure(text="GEN : 0", fg="black") self.__lStable.configure(text="N/A", fg="orange") def disableButtons(self, val): """Modele (modif), bool -> None Change l'état des bouttons.""" s = "disabled" if (not val): s = "normal" for i in range(self.__jeu.tx()): for j in range(self.__jeu.ty()): self.__cases[i][j].configure(state=s) def changeTimer(self): """Modele -> None Change la valeur du timer.""" t = self.__eTimer.get() if (est_entier(t) and 5 <= int(t) <= 5000): self.__time = int(t) else: self.__eTimer.delete(0, "end") def genAlea(self): """Modele (modif) -> None Génère aléatoirement un ensemble de cellules vivantes.""" n = self.__eNbCells.get() if est_entier(n) and 1 <= int(n) <= (self.__jeu.tx() * self.__jeu.ty()) - self.__jeu.nb_viv(): self.__jeu.placeVCelsRandom(int(n)) self.metAJour() self.reinitLabels() else: self.__eNbCells.delete(0, "end")