def __init__(self, parent, n_pixels_par_case, store_filename='annulerdeplacement.txt'): # Nombre de lignes et de colonnes. self.n_lignes = 8 self.n_colonnes = 8 # Noms des lignes et des colonnes. self.chiffres_rangees = ['1', '2', '3', '4', '5', '6', '7', '8'] self.lettres_colonnes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] # Nombre de pixels par case, variable. self.n_pixels_par_case = n_pixels_par_case # Appel du constructeur de la classe de base (Canvas). # La largeur et la hauteur sont déterminés en fonction du nombre de cases. super().__init__(parent, width=self.n_lignes * n_pixels_par_case, height=self.n_colonnes * self.n_pixels_par_case) # On fait en sorte que le redimensionnement du canvas redimensionne son contenu. Cet événement étant également # généré lors de la création de la fenêtre, nous n'avons pas à dessiner les cases et les pièces dans le # constructeur. self.bind('<Configure>', self.redimensionner) # Importation de Échequier et partie et Fenetre self.echequier = Echiquier() self.partie = Partie() self.fenetre = Fenetre # Dictionnaire contenant les pièces. Vous devinerez, si vous réutilisez cette classe dans votre TP4, # qu'il fandra adapter ce code pour plutôt utiliser la classe Echiquier. self.pieces = self.echequier.dictionnaire_pieces # Les variables nécessaires pour la fonction déplacement self.selectionner = 0 self.case_source = "" self.case_cible = "" # Déterminer le gagnant self.gagnant_noir = False self.gagnant_blanc = False # Enregistrement des coups self.texte = "" # Fichier text annuler déplacement self.store_filename = os.path.join(BASE_DIR, store_filename) self.t = 0
def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier() #intialisation de deux listes qui permettront d'afficher les derniers déplacements self.listeDeplacements = [] self.dernierDeplacement = [] self.hist = [] self.nom_fichier_sauvegarde = 'sauvegarde'
class Partie: """La classe Partie contient les informations sur une partie d'échecs, c'est à dire un échiquier, puis un joueur actif (blanc ou noir). Des méthodes sont disponibles pour faire avancer la partie et interagir avec l'utilisateur. Attributes: joueur_actif (str): La couleur du joueur actif, 'blanc' ou 'noir'. echiquier (Echiquier): L'échiquier sur lequel se déroule la partie. """ def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier() def determiner_gagnant(self): """Détermine la couleur du joueur gagnant, s'il y en a un. Pour déterminer si un joueur est le gagnant, le roi de la couleur adverse doit être absente de l'échiquier. Returns: str: 'blanc' si le joueur blanc a gagné, 'noir' si c'est plutôt le joueur noir, et 'aucun' si aucun joueur n'a encore gagné. """ if not self.echiquier.roi_de_couleur_est_dans_echiquier('noir'): return 'blanc' elif not self.echiquier.roi_de_couleur_est_dans_echiquier('blanc'): return 'noir' return 'aucun' def partie_terminee(self): """Vérifie si la partie est terminée. Une partie est terminée si un gagnant peut être déclaré. Returns: bool: True si la partie est terminée, et False autrement. """ return self.determiner_gagnant() != 'aucun' def joueur_suivant(self): """Change le joueur actif: passe de blanc à noir, ou de noir à blanc, selon la couleur du joueur actif. """ if self.joueur_actif == 'blanc': self.joueur_actif = 'noir' else: self.joueur_actif = 'blanc'
def deplacer(self, position_source, position_cible): """Effectue un déplacement de pièce si celui-ci est permis, dans l'objet echiquier et sur le canvas. Args: position_source(str): Case de départ position_cible(str): Case d'arrivée Returns: (bool): True si le déplacement est valide et a été effectué, sinon False.""" # Vérifier et faire le déplacement dans la source de données try: coup = Echiquier.deplacer(self, position_source, position_cible) # Déplacement impossible: propager l'exception au contrôleur d'évenement except PychecsException as erreur: raise erreur # Sinon réfléter le changement au niveau graphique... else: # Si une prise est faite: éliminer l'objet graphique du canvas et de la liste des objets dessinés if position_cible in self.dictionnaire_graphique.keys(): self.effacer_la_piece_a_position(position_cible) # Mettre à jour la liste graphique et faire le déplacement sur le canvas self.deplacer_de_case_a_case(position_source, position_cible) # Si c'est un des roques, il faut aussi déplacer la tour. Cela a été fait dans l'échiquier mais non avec # les objets graphiques! if "roque" in coup["special"]: couleur = self.dictionnaire_pieces[position_cible].couleur position_initiale, position_finale = self.parametres_du_roque( couleur, coup["special"]) self.deplacer_de_case_a_case(position_initiale, position_finale) # Si c'est une prise en passant, il faut éliminer un objet objet graphique pion à la case appropriée if coup["special"] == "en passant": position_prise = position_cible[0] + position_source[1] if position_prise in self.dictionnaire_graphique.keys(): self.effacer_la_piece_a_position(position_prise) # Si c'est une promotion, il faut remplacer le pion promu par la pièce choisie # Il faut aussi réévaluer si le roi est en échec, mat ou pat. if coup["special"] == "promotion": coup["special"] += self.promouvoir(position_cible) coup["resultat"] = self.resultat_du_coup(self.joueur_inactif()) return coup
def __init__(self, parent, n_pixels_par_case): # Nombre de lignes et de colonnes. self.n_lignes = 8 self.n_colonnes = 8 # Noms des lignes et des colonnes. self.chiffres_rangees = ['1', '2', '3', '4', '5', '6', '7', '8'] self.lettres_colonnes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] # Nombre de pixels par case, variable. self.n_pixels_par_case = n_pixels_par_case # Appel du constructeur de la classe de base (Canvas). # La largeur et la hauteur sont déterminées en fonction du nombre de cases. super().__init__(parent, width=self.n_lignes * n_pixels_par_case, height=self.n_colonnes * self.n_pixels_par_case) # On fait en sorte que le redimensionnement du canvas redimensionne son contenu. Cet événement étant également # généré lors de la création de la fenêtre, nous n'avons pas à dessiner les cases et les pièces dans le # constructeur. self.echiquier = Echiquier() self.echiquier.initialiser_echiquier_depart() self.bind('<Configure>', self.redimensionner)
class Partie: """La classe Partie contient les informations sur une partie d'échecs, c'est à dire un échiquier, puis un joueur actif (blanc ou noir). Des méthodes sont disponibles pour faire avancer la partie et interagir avec l'utilisateur. Attributes: joueur_actif (str): La couleur du joueur actif, 'blanc' ou 'noir'. echiquier (Echiquier): L'échiquier sur lequel se déroule la partie. """ def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier() def determiner_gagnant(self): """Détermine la couleur du joueur gagnant, s'il y en a un. Pour déterminer si un joueur est le gagnant, le roi de la couleur adverse doit être absente de l'échiquier. Returns: str: 'blanc' si le joueur blanc a gagné, 'noir' si c'est plutôt le joueur noir, et 'aucun' si aucun joueur n'a encore gagné. """ if not self.echiquier.roi_de_couleur_est_dans_echiquier('noir'): return 'blanc' elif not self.echiquier.roi_de_couleur_est_dans_echiquier('blanc'): return 'noir' return 'aucun' def partie_terminee(self): """Vérifie si la partie est terminée. Une partie est terminée si un gagnant peut être déclaré. Returns: bool: True si la partie est terminée, et False autrement. """ return self.determiner_gagnant() != 'aucun' def demander_positions(self): """Demande à l'utilisateur d'entrer les positions de départ et d'arrivée pour faire un déplacement. Si les positions entrées sont valides (si le déplacement est valide), on retourne les deux positions. On doit redemander tant que l'utilisateur ne donne pas des positions valides. Returns: str, str: Deux chaînes de caractères représentant les deux positions valides fournies par l'utilisateurs. """ while True: # On demande et valide la position source. while True: source = input("Entrez position source: ") if self.echiquier.position_est_valide( source) and self.echiquier.couleur_piece_a_position( source) == self.joueur_actif: break print("Position invalide.\n") # On demande et valide la position cible. cible = input("Entrez position cible: ") if self.echiquier.deplacement_est_valide(source, cible): return source, cible print("Déplacement invalide.\n") def deplacer(self, position_source, position_cible): piece = self.echiquier.recuperer_piece_a_position(position_source) print("la piece est", piece) if piece is None: raise AucunePieceAPosition('Aucune pièce à cet emplacement') elif piece.couleur != self.joueur_actif: raise MauvaiseCouleurPiece( "La pièce source n'appartient pas au joueur actif") self.echiquier.deplacer(position_source, position_cible) self.joueur_suivant() def joueur_suivant(self): """Change le joueur actif: passe de blanc à noir, ou de noir à blanc, selon la couleur du joueur actif. """ if self.joueur_actif == 'blanc': self.joueur_actif = 'noir' else: self.joueur_actif = 'blanc' def jouer(self): """Tant que la partie n'est pas terminée, joue la partie. À chaque tour : - On affiche l'échiquier. - On demande les deux positions. - On fait le déplacement sur l'échiquier. - On passe au joueur suivant. Une fois la partie terminée, on félicite le joueur gagnant! """ while not self.partie_terminee(): print(self.echiquier) print("\nAu tour du joueur {}".format(self.joueur_actif)) source, cible = self.demander_positions() self.echiquier.deplacer(source, cible) self.joueur_suivant() print(self.echiquier) print("\nPartie terminée! Le joueur {} a gagné".format( self.determiner_gagnant()))
def __init__(self, store_filename='partie1.bin', store_filename2='partie2.bin', store_filename3="deplacements1.txt", store_filename4='deplacements2.txt'): super().__init__() self.title("Échiquier") # Background de la fenêtre. self.config(bg="AntiqueWhite1") # La position sélectionnée. self.position_selectionnee = None # Truc pour le redimensionnement automatique des éléments de la fenêtre. self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) # Création du canvas échiquier. self.canvas_echiquier = CanvasEchiquier(self, 60) self.canvas_echiquier.grid(sticky=NSEW) # Ajout d'une étiquette d'information. self.messages = Label(self) self.messages.grid() # Ajout d'un message box self.message_alerte = messagebox # On lie un clic sur le CanvasEchiquier à une méthode. self.canvas_echiquier.bind('<Button-1>', self.canvas_echiquier.jouer) # Les variables nécessaires pour la fonction déplacement self.selectionner = 0 self.case_source = "" self.case_cible = "" self.echiquier = Echiquier() # Frame unique pour les autres fonctions self.cadre_fonctions = Frame(self, relief="groove") self.cadre_fonctions.grid(row=0, column=1, padx=10, pady=10, sticky=S) self.cadre_fonctions.config(bg="AntiqueWhite1") self.cadre_fonctions_partie = Frame(self, relief="groove") self.cadre_fonctions_partie.config(bg="AntiqueWhite1") self.cadre_fonctions_partie.grid(row=0, column=1, padx=10, pady=10, sticky=N) # On importe les fonctions de parties self.partie = Partie() # L'emplacement du file self.store_filename = os.path.join(BASE_DIR, store_filename) self.store_filename2 = os.path.join(BASE_DIR, store_filename2) self.store_filename3 = os.path.join(BASE_DIR, store_filename3) self.store_filename4 = os.path.join(BASE_DIR, store_filename4) # Pour savoir nous sommes actuellement dans quel partie self.partie_actuel = 0 # Label compteur self.m = 2 self.s = 0 self.compteur = StringVar() self.compteur.set(str(self.m) + ":" + str(self.s)) self.lbl_compteur1 = Label(self.cadre_fonctions_partie, textvariable=self.compteur, bd=4, relief="groove", height=2).grid(row=0, column=0, sticky=NSEW, padx=10, pady=10) # Label joueur actif self.joueur_actif = StringVar() self.joueur_actif.set("C'est le tour du joueur {}.".format( self.canvas_echiquier.partie.joueur_actif)) self.lbl_joueur_actif = Label(self.cadre_fonctions_partie, textvariable=self.joueur_actif, relief="groove", bg="green", height=2).grid(row=1, column=0, sticky=NSEW, padx=10, pady=10) # Label Menu de partie self.lbl_options_de_partie = Label(self.cadre_fonctions_partie, text="Menu", relief="sunken", font="Arial 13 bold").grid \ (row=2, column=0, sticky=NSEW, padx=10, pady=10) # Bouton Nouvelle Partie self.btn_nouvelle_partie = Button( self.cadre_fonctions_partie, text="Nouvelle partie", command=self.alerte_nouvelle_partie).grid(row=3, column=0, sticky=NSEW) # Bouton Fin du tour self.btn_fin_du_tour = Button(self.cadre_fonctions_partie, bg="yellow", text="Fin du tour", relief="groove", height=2, command=self.fin_du_tour).grid( row=2, column=0, sticky=NSEW, padx=10, pady=10) # Bouton Sauvegarder self.btn_Sauvegarder = Button( self.cadre_fonctions_partie, text="Sauvegarder la partie", command=self.alerte_sauvegarder_partie).grid(row=4, column=0, sticky=NSEW) # Bouton Charger self.btn_Charger = Button(self.cadre_fonctions_partie, text="Charger une partie", command=self.alerte_charger_partie).grid( row=5, column=0, sticky=NSEW) # Boutton Quitter self.btn_quitter = Button(self.cadre_fonctions_partie, text="Quitter", command=self.quit).grid(row=6, column=0, sticky=NSEW) # Label options de partie self.lbl_options_de_partie = Label(self.cadre_fonctions, text="Options", relief="sunken", font="Arial 13 bold").grid \ (row=1, column=0, sticky=NSEW, padx=10, pady=10) # Boutton revoir la partie self.btn_revoir_partie = Button( self.cadre_fonctions, text="Revoir une partie", command=self.alert_revoir_une_partie).grid(row=7, column=0, sticky=NSEW) # Bouton annuler deplacement self.btn_console = Button(self.cadre_fonctions, text="Annuler le dernier mouvement", command=self.annuler_deplacement).grid( row=8, column=0, sticky=NSEW) # Bouton pour afficher les déplacements effectués self.btn_console = Button( self.cadre_fonctions, text="Afficher les déplacements effectués", command=self.afficher_liste_deplacements).grid(row=9, column=0, sticky=NSEW) # Bouton pour lire les règlements du jeux self.btn_reglement = Button( self.cadre_fonctions, text="Voir les règlements du jeux en ligne", command=self.openweb).grid(row=10, column=0, sticky=NSEW) # Bouton changer thème: self.btn_changer_theme = Button(self.cadre_fonctions, text="Changer le thème", command=self.changer_theme).grid( row=11, column=0, sticky=NSEW)
class CanvasEchiquier(Canvas): """Classe héritant d'un Canvas, et affichant un échiquier qui se redimensionne automatique lorsque la fenêtre est étirée. """ def __init__(self, parent, n_pixels_par_case, store_filename='annulerdeplacement.txt'): # Nombre de lignes et de colonnes. self.n_lignes = 8 self.n_colonnes = 8 # Noms des lignes et des colonnes. self.chiffres_rangees = ['1', '2', '3', '4', '5', '6', '7', '8'] self.lettres_colonnes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] # Nombre de pixels par case, variable. self.n_pixels_par_case = n_pixels_par_case # Appel du constructeur de la classe de base (Canvas). # La largeur et la hauteur sont déterminés en fonction du nombre de cases. super().__init__(parent, width=self.n_lignes * n_pixels_par_case, height=self.n_colonnes * self.n_pixels_par_case) # On fait en sorte que le redimensionnement du canvas redimensionne son contenu. Cet événement étant également # généré lors de la création de la fenêtre, nous n'avons pas à dessiner les cases et les pièces dans le # constructeur. self.bind('<Configure>', self.redimensionner) # Importation de Échequier et partie et Fenetre self.echequier = Echiquier() self.partie = Partie() self.fenetre = Fenetre # Dictionnaire contenant les pièces. Vous devinerez, si vous réutilisez cette classe dans votre TP4, # qu'il fandra adapter ce code pour plutôt utiliser la classe Echiquier. self.pieces = self.echequier.dictionnaire_pieces # Les variables nécessaires pour la fonction déplacement self.selectionner = 0 self.case_source = "" self.case_cible = "" # Déterminer le gagnant self.gagnant_noir = False self.gagnant_blanc = False # Enregistrement des coups self.texte = "" # Fichier text annuler déplacement self.store_filename = os.path.join(BASE_DIR, store_filename) self.t = 0 def dessiner_cases(self): """Méthode qui dessine les cases de l'échiquier. """ for i in range(self.n_lignes): for j in range(self.n_colonnes): debut_ligne = i * self.n_pixels_par_case fin_ligne = debut_ligne + self.n_pixels_par_case debut_colonne = j * self.n_pixels_par_case fin_colonne = debut_colonne + self.n_pixels_par_case position = self.obtenir_position_a_partir_de_coordonnes(i, j) position_selectione = self.case_source # Les couleurs if position == position_selectione: couleur = "yellow" elif (i + j) % 2 == 0: couleur = 'white' else: couleur = 'gray' # On dessine le rectangle. On utilise l'attribut "tags" pour être en mesure de récupérer les éléments # par la suite. self.create_rectangle(debut_colonne, debut_ligne, fin_colonne, fin_ligne, fill=couleur, tags='case') def dessiner_pieces(self): # Caractères unicode représentant les pièces. Vous avez besoin de la police d'écriture DejaVu. caracteres_pieces = { 'PB': '\u2659', 'PN': '\u265f', 'TB': '\u2656', 'TN': '\u265c', 'CB': '\u2658', 'CN': '\u265e', 'FB': '\u2657', 'FN': '\u265d', 'RB': '\u2654', 'RN': '\u265a', 'DB': '\u2655', 'DN': '\u265b' } # Pour tout paire position, pièce: for position, piece in self.echequier.dictionnaire_pieces.items(): # On dessine la pièce dans le canvas, au centre de la case. On utilise l'attribut "tags" pour être en # mesure de récupérer les éléments dans le canvas. coordonnee_y = ( self.n_lignes - self.chiffres_rangees.index(position[1]) - 1) * self.n_pixels_par_case + self.n_pixels_par_case // 2 coordonnee_x = self.lettres_colonnes.index(position[ 0]) * self.n_pixels_par_case + self.n_pixels_par_case // 2 self.create_text(coordonnee_x, coordonnee_y, text=[piece], font=('Deja Vu', self.n_pixels_par_case // 2), tags='piece') def redimensionner(self, event): # Nous recevons dans le "event" la nouvelle dimension dans les attributs width et height. On veut un damier # carré, alors on ne conserve que la plus petite de ces deux valeurs. nouvelle_taille = min(event.width, event.height) # Calcul de la nouvelle dimension des cases. self.n_pixels_par_case = nouvelle_taille // self.n_lignes # On supprime les anciennes cases et on ajoute les nouvelles. self.delete('case') self.dessiner_cases() # On supprime les anciennes pièces et on ajoute les nouvelles. self.delete('piece') self.dessiner_pieces() def obtenir_position_a_partir_de_coordonnes(self, i, j): position = "{}{}".format( self.lettres_colonnes[j], int(self.chiffres_rangees[self.n_lignes - i - 1])) return position def deplacer(self, source, cible): self.echequier.deplacer(source, cible) self.rafraichir() self.echequier.dictionnaire_pieces.update() def rafraichir(self): # On supprimer les anciennes cases et on ajouter les nouvelles. self.delete("case") self.dessiner_cases() # On supprimer les anciennes pièces et on ajoute les nouvelles. self.delete("piece") self.dessiner_pieces() def jouer(self, event): x, y = event.x, event.y ligne = y // self.n_pixels_par_case colonne = x // self.n_pixels_par_case position = "{}{}".format( self.lettres_colonnes[colonne], int(self.chiffres_rangees[self.n_lignes - ligne - 1])) if self.selectionner == 1: self.case_cible = position try: self.deplacer(self.case_source, self.case_cible) if self.echequier.roi_de_couleur_est_dans_echiquier( "blanc") is False: messagebox.showinfo("Félicitation!", "Le joueur noir a gagné la partie!") self.unbind("<Button-1>"), self.jouer elif self.echequier.roi_de_couleur_est_dans_echiquier( "noir") is False: messagebox.showinfo("Félicitation!", "Le joueur blanc a gagné la partie!") self.unbind("<Button-1>"), self.jouer elif self.echequier.recuperer_piece_a_position( self.case_source) is None: self.partie.joueur_suivant() self.unbind("<Button-1>"), self.jouer elif self.echequier.deplacement_est_valide(self.case_source, self.case_cible) is False and \ self.echequier.recuperer_piece_a_position(self.case_cible) is None: raise DeplacementImpossible elif self.echequier.deplacement_est_valide(self.case_source, self.case_cible) is False and \ self.echequier.recuperer_piece_a_position(self.case_cible) is not None: if self.echequier.couleur_piece_a_position( self.case_cible ) == self.echequier.couleur_piece_a_position( self.case_source): pass else: raise PriseImpossible self.texte += "{} {} à {} \n".format( self.echequier.recuperer_piece_a_position(self.case_cible), self.case_source, self.case_cible) except DeplacementImpossible: messagebox.showinfo("Erreur", "Déplacement impossible") except PriseImpossible: messagebox.showinfo("Erreur", "Prise impossible") self.case_source = "" self.case_cible = "" self.selectionner = 0 self.rafraichir() elif self.selectionner == 0: try: if self.echequier.couleur_piece_a_position( position) == self.partie.joueur_actif: self.case_source = position self.rafraichir() self.selectionner += 1 elif self.echequier.couleur_piece_a_position(position) != self.partie.joueur_actif and \ self.echequier.recuperer_piece_a_position(position) is not None: raise SelectionMauvaisePiece except SelectionMauvaisePiece: messagebox.showinfo( "Erreur", "Selection impossible: c'est au tour du joueur {}".format( self.partie.joueur_actif)) else: self.selectionner = 0 self.case_source = "" self.case_cible = "" def sauvegarder(self, filename): with open(filename, 'wb') as f: pickle.dump(self.echequier.dictionnaire_pieces, f) def charger(self, filename): with open(filename, 'rb') as f: data = pickle.load(f) f.close() self.echequier.dictionnaire_pieces = data self.rafraichir() def nouvelle_partie(self): self.echequier.initialiser_echiquier_depart() if self.partie.joueur_actif == "noir": self.partie.joueur_actif = "blanc" self.texte = "" self.rafraichir() def sauvegarder_mouvement(self, filename): with open(filename, 'wb') as f: pickle.dump(self.texte, f) def charger_mouvement(self, filename): with open(filename, 'rb') as f: data = pickle.load(f) f.close() self.texte = data self.rafraichir() def annuler_mouvement(self): derniere_ligne = self.texte[-9:] case_cible_avec = derniere_ligne[-4:] case_cible = case_cible_avec[0:2] case_source = derniere_ligne[0:3] self.echequier.deplacement_absolue(case_cible, case_source) self.rafraichir() self.texte = self.texte[0:-11] def revoir_une_partie(self, filename): self.nouvelle_partie() with open(filename, 'rb') as f: data = pickle.load(f) f.close() self.texte = data partie_en_text = self.texte Nombre_de_ligne = len(partie_en_text) // 11 while Nombre_de_ligne > 0: ligne = partie_en_text[2:11] case_source = ligne[0:2] case_cible = ligne[-4:] self.echequier.deplacement_absolue(case_source, case_cible) Nombre_de_ligne -= 1 partie_en_text = partie_en_text[11:] self.rafraichir() self.update() self.after(1500) pass
class CanvasEchiquier(Canvas): """Classe héritant d'un Canvas, et affichant un échiquier qui se redimensionne automatique lorsque la fenêtre est étirée. """ def __init__(self, parent, n_pixels_par_case): # Nombre de lignes et de colonnes. self.n_lignes = 8 self.n_colonnes = 8 # Noms des lignes et des colonnes. self.chiffres_rangees = ['1', '2', '3', '4', '5', '6', '7', '8'] self.lettres_colonnes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] # Nombre de pixels par case, variable. self.n_pixels_par_case = n_pixels_par_case # Appel du constructeur de la classe de base (Canvas). # La largeur et la hauteur sont déterminées en fonction du nombre de cases. super().__init__(parent, width=self.n_lignes * n_pixels_par_case, height=self.n_colonnes * self.n_pixels_par_case) # On fait en sorte que le redimensionnement du canvas redimensionne son contenu. Cet événement étant également # généré lors de la création de la fenêtre, nous n'avons pas à dessiner les cases et les pièces dans le # constructeur. self.echiquier = Echiquier() self.echiquier.initialiser_echiquier_depart() self.bind('<Configure>', self.redimensionner) #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def dessiner_cases(self): """Méthode qui dessine les cases de l'échiquier. """ for i in range(self.n_lignes): for j in range(self.n_colonnes): debut_ligne = i * self.n_pixels_par_case fin_ligne = debut_ligne + self.n_pixels_par_case debut_colonne = j * self.n_pixels_par_case fin_colonne = debut_colonne + self.n_pixels_par_case # On détermine la couleur. if (i + j) % 2 == 0: couleur = 'white' else: couleur = 'gray' # On dessine le rectangle. On utilise l'attribut "tags" pour être en mesure de récupérer les éléments # par la suite. self.create_rectangle(debut_colonne, debut_ligne, fin_colonne, fin_ligne, fill=couleur, tags='case') #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def dessiner_pieces(self): # Caractères unicode représentant les pièces. Vous avez besoin de la police d'écriture DejaVu. self.caracteres_pieces = { Pion('blanc'): '\u2659', Pion('noir'): '\u265f', Tour('blanc'): '\u2656', Tour('noir'): '\u265c', Cavalier('blanc'): '\u2658', Cavalier('noir'): '\u265e', Fou('blanc'): '\u2657', Fou('noir'): '\u265d', Roi('blanc'): '\u2654', Roi('noir'): '\u265a', Dame('blanc'): '\u2655', Dame('noir'): '\u265b' } # Pour tout paire position, pièce: for position in self.echiquier.dictionnaire_pieces: # On dessine la pièce dans le canvas, au centre de la case. On utilise l'attribut "tags" pour être en # mesure de récupérer les éléments dans le canvas. coordonnee_y = ( self.n_lignes - self.chiffres_rangees.index(position[1]) - 1) * self.n_pixels_par_case + self.n_pixels_par_case // 2 coordonnee_x = self.lettres_colonnes.index(position[ 0]) * self.n_pixels_par_case + self.n_pixels_par_case // 2 piece = self.echiquier.dictionnaire_pieces[position] uni = "" for e in list(self.caracteres_pieces.keys()): if type(e) == type(piece) and e.couleur == piece.couleur: uni = self.caracteres_pieces[e] break self.create_text(coordonnee_x, coordonnee_y, text=uni, font=('Deja Vu', self.n_pixels_par_case // 2), tags='piece') #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def redimensionner(self, event): # Nous recevons dans le "event" la nouvelle dimension dans les attributs width et height. On veut un damier # carré, alors on ne conserve que la plus petite de ces deux valeurs. nouvelle_taille = min(event.width, event.height) # Calcul de la nouvelle dimension des cases. self.n_pixels_par_case = nouvelle_taille // self.n_lignes # On supprime les anciennes cases et on ajoute les nouvelles. self.delete('case') self.dessiner_cases() # On supprime les anciennes pièces et on ajoute les nouvelles. self.delete('piece') self.dessiner_pieces()
def __init__(self, maitre=None, n_pixels_par_case=50, dictionnaire=None, joueur_actif=None, option_chrono=False, option_aide=False, **kwargs): """Constructeur: Args: maitre (widget): Widget qui contiendra notre échiquier. n_pixels_par_case (int): Taille des cases en pixels. x_coin(int): Coordonnée x du coin supérieur gauche de l'échiquier sur le canvas. y_coin(int): Coordonnée y du coin supérieur gauche de l'échiquier sur le canvas. **kwargs: Options du canvas.""" # Constructeurs des parents. tk.Canvas.__init__(self, maitre, **kwargs) Echiquier.__init__(self, dictionnaire) # Structure de données contenant les objets graphiques sur le canvas. self.dictionnaire_graphique = {} self.dictionnaire_cases = {} # Variable contenant les messages à l'utilisateur et le statut de la partie, en cours ou gagnée self.message = tk.StringVar() if not joueur_actif: self.joueur_actif = "blanc" self.message.set( "Début de la partie: au tour des blancs de jouer.") else: self.joueur_actif = joueur_actif self.message.set(f"Au tour des {self.joueur_actif}s de jouer.") ########################## # Le dernier coup complété ########################## self.coup_joue = {} ############################################################## # Compteur de coups. Sera suivi dans le contrôleur de partie ############################################################## self.nombre_de_coups_joues = tk.IntVar() self.nombre_de_coups_joues.set(0) #################################################### # Semaphore avertissant le controleur d'un évènement #################################################### self.evenement = tk.StringVar() self.evenement.set("debut") self.exception = None ################################################## # Paramètres géométriques du dessin de l'échiquier ################################################## self.n_pixels_par_case = n_pixels_par_case self.taille_pieces = int(round(self.n_pixels_par_case * 60 / 100)) self.n_lignes = 8 self.n_colonnes = 8 self.x_coin = 2 * self.n_pixels_par_case self.y_coin = 2 * self.n_pixels_par_case ############################################################################################ # Informations sur le mouvement demandé: utilisé dans clic-souris pour la sélection du coup ############################################################################################ self.piece_selectionnee = False self.piece_a_deplacer = None self.case_depart = "" self.case_arrivee = "" ####################################################################### # Dessin initial de l'échiquier avec les pièces à leurs place de départ ####################################################################### self.dessiner_cases() self.dessiner_reperes() self.initialiser_canvas_depart() # Lier l'évenement clic-souris à la méthode correspondante self.bind("<Button-1>", self.clic_souris) # Cette variable sera utilisée par un controleur de partie pour forcer l'échiquier à attendre le prochain # coup lorsqu'on jouera contre un adversaire. Deux valeurs seront possible: "actif" et "attente". # En mode "attente" l'échiquier ne réagira plus aux clics de souris. self.mode = "actif" # Options de jeu: chronomètre et afficher les mouvements possibles self.option_chrono = option_chrono self.option_aide = option_aide ############################################################################## # Ce dict contient les cases surlignées pour indiquer les mouvements possibles ############################################################################## self.cases_modifiees_pour_aider = {}
class Partie: """La classe Partie contient les informations sur une partie d'échecs, c'est à dire un échiquier, puis un joueur actif (blanc ou noir). Des méthodes sont disponibles pour faire avancer la partie et interagir avec l'utilisateur. Attributes: joueur_actif (str): La couleur du joueur actif, 'blanc' ou 'noir'. echiquier (Echiquier): L'échiquier sur lequel se déroule la partie. """ def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier() def determiner_gagnant(self): """Détermine la couleur du joueur gagnant, s'il y en a un. Pour déterminer si un joueur est le gagnant, le roi de la couleur adverse doit être absente de l'échiquier. Returns: str: 'blanc' si le joueur blanc a gagné, 'noir' si c'est plutôt le joueur noir, et 'aucun' si aucun joueur n'a encore gagné. """ if not self.echiquier.roi_de_couleur_est_dans_echiquier('noir'): return 'blanc' elif not self.echiquier.roi_de_couleur_est_dans_echiquier('blanc'): return 'noir' return 'aucun' def partie_terminee(self): """Vérifie si la partie est terminée. Une partie est terminée si un gagnant peut être déclaré. Returns: bool: True si la partie est terminée, et False autrement. """ return self.determiner_gagnant() != 'aucun' def demander_positions(self): """Demande à l'utilisateur d'entrer les positions de départ et d'arrivée pour faire un déplacement. Si les positions entrées sont valides (si le déplacement est valide), on retourne les deux positions. On doit redemander tant que l'utilisateur ne donne pas des positions valides. Returns: str, str: Deux chaînes de caractères représentant les deux positions valides fournies par l'utilisateurs. """ while True: # On demande et valide la position source. while True: source = input("Entrez position source: ") if self.echiquier.position_est_valide(source) and self.echiquier.couleur_piece_a_position(source) == self.joueur_actif: break print("Position invalide.\n") # On demande et valide la position cible. cible = input("Entrez position cible: ") if self.echiquier.deplacement_est_valide(source, cible): return source, cible print("Déplacement invalide.\n") def joueur_suivant(self): """Change le joueur actif: passe de blanc à noir, ou de noir à blanc, selon la couleur du joueur actif. """ if self.joueur_actif == 'blanc': self.joueur_actif = 'noir' else: self.joueur_actif = 'blanc' def jouer(self): """Tant que la partie n'est pas terminée, joue la partie. À chaque tour : - On affiche l'échiquier. - On demande les deux positions. - On fait le déplacement sur l'échiquier. - On passe au joueur suivant. Une fois la partie terminée, on félicite le joueur gagnant! """ while not self.partie_terminee(): print(self.echiquier) print("\nAu tour du joueur {}".format(self.joueur_actif)) source, cible = self.demander_positions() self.echiquier.deplacer(source, cible) self.joueur_suivant() print(self.echiquier) print("\nPartie terminée! Le joueur {} a gagné".format(self.determiner_gagnant()))
def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier()
# -*- coding: utf-8 -*- """Module principal du package pychecs2. C'est ce module que nous allons exécuter pour démarrer votre jeu. Importez les modules nécessaires et démarrez votre programme à partir d'ici. Le code fourni n'est qu'à titre d'exemple. """ from pychecs2.echecs.partie import Partie from pychecs2.echecs.echiquier import Echiquier from pychecs2.interface.exemple import Fenetre if __name__ == '__main__': # Création d'une instance de Partie. p = Partie() e = Echiquier() # Création et affichage d'une fenêtre (aucun lien avec la partie ci-haut). f = Fenetre() f.countdown() f.mainloop()
class Partie: """La classe Partie contient les informations sur une partie d'échecs, c'est à dire un échiquier, puis un joueur actif (blanc ou noir). Des méthodes sont disponibles pour faire avancer la partie et interagir avec l'utilisateur. Attributes: joueur_actif (str): La couleur du joueur actif, 'blanc' ou 'noir'. echiquier (Echiquier): L'échiquier sur lequel se déroule la partie. """ def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier() def determiner_gagnant(self): """Détermine la couleur du joueur gagnant, s'il y en a un. Pour déterminer si un joueur est le gagnant, le roi de la couleur adverse doit être absente de l'échiquier. Returns: str: 'blanc' si le joueur blanc a gagné, 'noir' si c'est plutôt le joueur noir, et 'aucun' si aucun joueur n'a encore gagné. """ #Cas où le roi noir est absent de l'échiquier. if not self.echiquier.roi_de_couleur_est_dans_echiquier('noir'): return 'blanc' #Cas où le roi blanc est absent de l'échiquier. if not self.echiquier.roi_de_couleur_est_dans_echiquier('blanc'): return 'noir' #Cas où les deux rois sont sur l'échiquier. return 'aucun' def partie_terminee(self): """Vérifie si la partie est terminée. Une partie est terminée si un gagnant peut être déclaré. Returns: bool: True si la partie est terminée, et False autrement. """ #Cas où le joueur blanc ou le joueur noir est le gagnant. if self.determiner_gagnant() == 'blanc' or self.determiner_gagnant() == 'noir': return True #Cas où il n'y a encore aucun gagnant. return False def piece_position_depart(self,position_depart): """ Détermine si la position de départ donner par l'utilisateur est sur l'échiquier. On vérifie qu'il y a bien une pièce du joueur actif sur cette case. S'il n'y a pas de pièce ou que c'est la pièce d'un autre joueur on retourne un message d'erreur. :param position_depart: str: Une chaine de charactère qui représente une position à évaluer. :return: bool: True si le la position est valide et a une pièce du joueur actif, et False autrement. """ #On redemande la position de départ tant que la position n'est pas valide. if not self.echiquier.position_est_valide(position_depart): return False #Tant qu'il n'y a pas de pièces on informe le joueur qu'il ne peux pas choisir cette case de départ et on redemande la position de départ if self.echiquier.recuperer_piece_a_position(position_depart) is None: print("Il n'y a pas de pièce sur cette case") return False #Tant que ce n'est pas une de ses pièces on informe le joueur qu'il ne peut pas jouer cette pièce et on redemande la position de départ. if self.echiquier.couleur_piece_a_position(position_depart) != self.joueur_actif: print("Vous jouer les pieces de l'autre joueur, TRICHEUR!") return False # Si c'est une bonne position, avec un pièce du joueur actif on retourne true. return True def demander_positions(self): """Demande à l'utilisateur d'entrer les positions de départ et d'arrivée pour faire un déplacement. Si les positions entrées sont valides (si le déplacement est valide), on retourne les deux positions. On doit redemander tant que l'utilisateur ne donne pas des positions valides. Returns: str, str: Deux chaînes de caractères représentant les deux positions valides fournies par l'utilisateurs. """ #On demande la position de départ au joueur. position_depart = fenetre.selectionner_pièce() #On redemande la position de départ tant que la position n'est pas une position avec une pièce du joueur. while not self.piece_position_depart(position_depart): position_depart = fenetre.selectionner_pièce() #On demande la position d'arriver au joueur. position_arrive = fenetre.selectionner_arriver() #On redemande la position d'arriver tant que la position n'est pas valide. while not self.echiquier.position_est_valide(position_arrive): position_arrive = fenetre.selectionner_arriver() #retourne les positions de départ et d'arriver. return position_depart, position_arrive def joueur_suivant(self): """Change le joueur actif: passe de blanc à noir, ou de noir à blanc, selon la couleur du joueur actif. """ # Si le joueur actif est blanc on le change en noir if self.joueur_actif == 'blanc': self.joueur_actif = 'noir' #Si le joueur actif est noir on le change en blanc elif self.joueur_actif == 'noir': self.joueur_actif = 'blanc' def jouer(self): """Tant que la partie n'est pas terminée, joue la partie. À chaque tour : - On affiche l'échiquier. - On demande les deux positions. - On fait le déplacement sur l'échiquier. - On passe au joueur suivant. Une fois la partie terminée, on félicite le joueur gagnant! """ partie_est_terminer = False #On forme une boucle de jeu qui va continuer tant que la partie n'est pas terminer. while not partie_est_terminer: #On affiche l'échiquier. f = fenetre() #On informe quel est la couleur du joueur actif. print("C'est au tour du joueur:",self.joueur_actif) deplacement_valide = False #On forme une seconde boucle qui va continuer tant qu'on n'entre pas un déplacement valide. while not deplacement_valide: #On demande à l'utilisateur les positions de départ et d'arriver du déplacement. while position_depart is None: position_depart = fenetre.selectionner_pièce if position_depart is not None: while position_arrive is None: position_arrive = fenetre.selectionner_arriver #Maintenant qu'on a une position de départ et d'arriver,on vérifie que c'est un déplacement valide. deplacement_valide = self.echiquier.deplacer(position_depart,position_arrive) #On verifie si la partie est terminé. partie_est_terminer = self.partie_terminee() #Si c'est le cas on félicite le joueur gagnant. if partie_est_terminer: print("Bravo joueur", self.joueur_actif,"vous avez gagné!") #S'il n'y a pas de gagnant, la partie n'est pas fini, on change de joueur actif. else: self.joueur_suivant() f.mainloop()
def __repr__(self): return Echiquier.__repr__(self)
class Partie: """La classe Partie contient les informations sur une partie d'échecs, c'est à dire un échiquier, puis un joueur actif (blanc ou noir). Des méthodes sont disponibles pour faire avancer la partie et interagir avec l'utilisateur. Attributes: joueur_actif (str): La couleur du joueur actif, 'blanc' ou 'noir'. echiquier (Echiquier): L'échiquier sur lequel se déroule la partie. """ def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier() def determiner_gagnant(self): """Détermine la couleur du joueur gagnant, s'il y en a un. Pour déterminer si un joueur est le gagnant, le roi de la couleur adverse doit être absente de l'échiquier. Returns: str: 'blanc' si le joueur blanc a gagné, 'noir' si c'est plutôt le joueur noir, et 'aucun' si aucun joueur n'a encore gagné. """ if not self.echiquier.roi_de_couleur_est_dans_echiquier('noir'): return 'blanc' elif not self.echiquier.roi_de_couleur_est_dans_echiquier('blanc'): return 'noir' return 'aucun' def partie_terminee(self): """Vérifie si la partie est terminée. Une partie est terminée si un gagnant peut être déclaré. Returns: bool: True si la partie est terminée, et False autrement. """ toutes_les_position = [ 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'g1', 'g2', 'g3', 'g4', 'g5', 'g6', 'g7', 'g8', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8' ] var = 0 for i in toutes_les_position: if isinstance( self.echiquier.recuperer_piece_a_position(i), Pion) == True or isinstance( self.echiquier.recuperer_piece_a_position(i), Tour) == True or isinstance( self.echiquier.recuperer_piece_a_position(i), Fou) == True or isinstance( self.echiquier.recuperer_piece_a_position(i), Cavalier) == True or isinstance( self.echiquier.recuperer_piece_a_position( i), Dame) == True: var = 1 if var == 0: return True else: return self.determiner_gagnant() != 'aucun' def demander_positions(self): """Demande à l'utilisateur d'entrer les positions de départ et d'arrivée pour faire un déplacement. Si les positions entrées sont valides (si le déplacement est valide), on retourne les deux positions. On doit redemander tant que l'utilisateur ne donne pas des positions valides. Returns: str, str: Deux chaînes de caractères représentant les deux positions valides fournies par l'utilisateurs. """ while True: # On demande et valide la position source. while True: source = input("Entrez position source: ") if self.echiquier.position_est_valide( source) and self.echiquier.couleur_piece_a_position( source) == self.joueur_actif: break print("Position invalide.\n") # On demande et valide la position cible. cible = input("Entrez position cible: ") if self.echiquier.deplacement_est_valide(source, cible): return source, cible print("Déplacement invalide.\n") def joueur_suivant(self): """Change le joueur actif: passe de blanc à noir, ou de noir à blanc, selon la couleur du joueur actif. """ if self.joueur_actif == 'blanc': self.joueur_actif = 'noir' else: self.joueur_actif = 'blanc' def jouer(self): """Tant que la partie n'est pas terminée, joue la partie. À chaque tour : - On affiche l'échiquier. - On demande les deux positions. - On fait le déplacement sur l'échiquier. - On passe au joueur suivant. Une fois la partie terminée, on félicite le joueur gagnant! """ while not self.partie_terminee(): print(self.echiquier) print("\nAu tour du joueur {}".format(self.joueur_actif)) source, cible = self.demander_positions() self.echiquier.deplacer(source, cible) self.joueur_suivant() print(self.echiquier) print("\nPartie terminée! Le joueur {} a gagné".format( self.determiner_gagnant()))
class Partie: """ La classe Partie contient les informations sur une partie d'échecs, c'est à dire un échiquier, puis un joueur actif (blanc ou noir). Des méthodes sont disponibles pour faire avancer la partie et interagir avec l'utilisateur. Attributes: joueur_actif (str): La couleur du joueur actif, 'blanc' ou 'noir'. echiquier (Echiquier): L'échiquier sur lequel se déroule la partie. """ def __init__(self): # Le joueur débutant une partie d'échecs est le joueur blanc. self.joueur_actif = 'blanc' # Création d'une instance de la classe Echiquier, qui sera manipulée dans les méthodes de la classe. self.echiquier = Echiquier() #intialisation de deux listes qui permettront d'afficher les derniers déplacements self.listeDeplacements = [] self.dernierDeplacement = [] self.hist = [] self.nom_fichier_sauvegarde = 'sauvegarde' def determiner_gagnant(self): """Détermine la couleur du joueur gagnant, s'il y en a un. Pour déterminer si un joueur est le gagnant, le roi de la couleur adverse doit être absente de l'échiquier. Returns: str: 'blanc' si le joueur blanc a gagné, 'noir' si c'est plutôt le joueur noir, et 'aucun' si aucun joueur n'a encore gagné. """ if not self.echiquier.roi_de_couleur_est_dans_echiquier('noir'): return 'blanc' elif not self.echiquier.roi_de_couleur_est_dans_echiquier('blanc'): return 'noir' return 'aucun' def partie_terminee(self): """Vérifie si la partie est terminée. Une partie est terminée si un gagnant peut être déclaré. Returns: bool: True si la partie est terminée, et False autrement. """ return self.determiner_gagnant() != 'aucun' def annulerDernierMouvement(self): """ Permet d'annuler le dernier mouvement et de rafraichir les pieces blanches et noires qui restent. Un premier scénario ou la liste a 2 ou moins historique d'échiquier. Un deuxième scénario dans le cas contraire. """ if len(self.echiquier.listeDesEchiquiers) <= 2: self.echiquier.initialiser_echiquier_depart() self.joueur_actif = 'blanc' else: del self.echiquier.listeDesEchiquiers[-1] self.echiquier.dictionnaire_pieces = self.echiquier.listeDesEchiquiers[ -1] self.joueur_suivant() self.resteBlanc = set() self.resteNoir = set() for i in self.echiquier.dictionnaire_pieces.values(): if i.est_blanc(): self.resteBlanc.add(i) else: self.resteNoir.add(i) self.gapBlanc = list(self.echiquier.setBlanc - self.resteBlanc) self.gapNoir = list(self.echiquier.setNoir - self.resteNoir) def roque_est_valide(self, position_source, position_cible): """ Identifie si le Roi peut effectuer un Roque. Pour pouvoir effectuer un Roque, il faut que: 1. La pièece à la position_cible soit une Tour 2. La pièce à la position_source soit un Roi 3. Ni le Roi ni la Tour n'aient effectué de mouvement depuis le début de la partie. 4. La voie doit être libre (aucune pièce) entre le Roi et la Tour. 5. Aucune case entre le Roi et la Tour ne soit menacée par l'adversaire. 6. Le roi ne soit pas en échec. 7. La tour ne soit pas menacée. Args: position_source (str): Position du Roi position_cible (str): Position de la Tour Returns: bool: True si le Roi peut Roquer, et False autrement. """ couleur_adversaire = 'blanc' rangee_origine = '8' piece = self.echiquier.recuperer_piece_a_position(position_source) piece_cible = self.echiquier.recuperer_piece_a_position(position_cible) if piece.couleur == 'blanc': couleur_adversaire = 'noir' rangee_origine = '1' #critères de 1 à 3 if isinstance(piece, Roi) and isinstance(piece_cible, Tour) and\ piece.couleur == piece_cible.couleur and\ self.echiquier.recuperer_piece_a_position(position_source) not in self.hist and \ self.echiquier.recuperer_piece_a_position(position_cible) not in self.hist: if position_cible[0] == 'a': #Grand Roque for colonne in self.echiquier.lettres_colonnes[0:5]: #critères 5 à 7 if self.echiquier.case_est_menacee_par( colonne + rangee_origine, couleur_adversaire): return False return True else: #Petit Roque for colonne in self.echiquier.lettres_colonnes[4:]: # critères 5 à 7 if self.echiquier.case_est_menacee_par( colonne + rangee_origine, couleur_adversaire): return False return True def roquer(self, position_source, position_cible): """ Effectue le mouvement de Roque si celui-ce est valide dans l'échiquier. Args: position_source (str): position du Roi dans l'échiquier position_cible (str): position de la Tour dans l'échiquier. """ self.joueur_suivant() if ord(position_source[0]) > ord(position_cible[0]): position_roi = 'c' + position_source[1] self.echiquier.dictionnaire_pieces[position_roi] = \ self.echiquier.recuperer_piece_a_position(position_source) del self.echiquier.dictionnaire_pieces[position_source] position_tour = 'd' + position_cible[1] self.echiquier.dictionnaire_pieces[position_tour] = \ self.echiquier.recuperer_piece_a_position(position_cible) del self.echiquier.dictionnaire_pieces[position_cible] else: position_roi = 'g' + position_source[1] self.echiquier.dictionnaire_pieces[position_roi] = \ self.echiquier.recuperer_piece_a_position(position_source) del self.echiquier.dictionnaire_pieces[position_source] position_tour = 'f' + position_cible[1] self.echiquier.dictionnaire_pieces[position_tour] = \ self.echiquier.recuperer_piece_a_position(position_cible) del self.echiquier.dictionnaire_pieces[position_cible] #Trucs a Thierry piece = self.echiquier.recuperer_piece_a_position(position_source) self.dernierDeplacement = [ "(" + self.joueur_actif + ")" + position_source + "->" + position_cible ] self.listeDeplacements.append(self.dernierDeplacement) echiquierCopy = dict(self.echiquier.dictionnaire_pieces) self.echiquier.listeDesEchiquiers.append(echiquierCopy) self.resteBlanc = set() self.resteNoir = set() for i in self.echiquier.dictionnaire_pieces.values(): if (i.est_blanc()): self.resteBlanc.add(i) else: self.resteNoir.add(i) self.gapBlanc = list(self.echiquier.setBlanc - self.resteBlanc) self.gapNoir = list(self.echiquier.setNoir - self.resteNoir) def deplacer(self, position_source, position_cible): """ Permet de d'appeler le mouvement à la méthode déplacer du module Échiquier. Permet aussi de recalculer les pièces mangées qui sert dans le visuel du jeux. En même temps, sert à écrire ce qui sera communiquer au joueur sur la liste des déplacements dans le Listbox du jeux. Args: position_source (str): Position de source de la pièce position_cible (str): Position cible de la pièce """ piece = self.echiquier.recuperer_piece_a_position(position_source) #Pour le roque if self.echiquier.deplacement_est_valide(position_source, position_cible): self.hist.append(piece) self.echiquier.deplacer(position_source, position_cible) self.joueur_suivant() self.dernierDeplacement = [ "(" + piece.couleur + ")" + position_source + "->" + position_cible ] self.listeDeplacements.append(self.dernierDeplacement) echiquierCopy = dict(self.echiquier.dictionnaire_pieces) self.echiquier.listeDesEchiquiers.append(echiquierCopy) self.dictionnaire_pieces_initial = { 'a1': Tour('blanc'), 'b1': Cavalier('blanc'), 'c1': Fou('blanc'), 'd1': Dame('blanc'), 'e1': Roi('blanc'), 'f1': Fou('blanc'), 'g1': Cavalier('blanc'), 'h1': Tour('blanc'), 'a2': Pion('blanc'), 'b2': Pion('blanc'), 'c2': Pion('blanc'), 'd2': Pion('blanc'), 'e2': Pion('blanc'), 'f2': Pion('blanc'), 'g2': Pion('blanc'), 'h2': Pion('blanc'), 'a7': Pion('noir'), 'b7': Pion('noir'), 'c7': Pion('noir'), 'd7': Pion('noir'), 'e7': Pion('noir'), 'f7': Pion('noir'), 'g7': Pion('noir'), 'h7': Pion('noir'), 'a8': Tour('noir'), 'b8': Cavalier('noir'), 'c8': Fou('noir'), 'd8': Dame('noir'), 'e8': Roi('noir'), 'f8': Fou('noir'), 'g8': Cavalier('noir'), 'h8': Tour('noir'), } self.setBlanc = set() self.setNoir = set() for i in self.dictionnaire_pieces_initial.values(): if i.est_blanc(): self.setBlanc.add(i) else: self.setNoir.add(i) self.resteBlanc = set() self.resteNoir = set() for i in self.echiquier.dictionnaire_pieces.values(): if i.est_blanc(): self.resteBlanc.add(i) else: self.resteNoir.add(i) self.gapBlanc = list(self.echiquier.setBlanc - self.resteBlanc) self.gapNoir = list(self.echiquier.setNoir - self.resteNoir) def joueur_suivant(self): """Change le joueur actif: passe de blanc à noir, ou de noir à blanc, selon la couleur du joueur actif. """ if self.joueur_actif == 'blanc': self.joueur_actif = 'noir' else: self.joueur_actif = 'blanc' def position_mon_roi(self, couleur_joueur_actif): """ Identifie ou se trouve le roi de la couleur entrée en argument dans l'échiquier. Args: couleur_joueur_actif (str): couleur du joueur dont on souhaite connaître la position du Roi. Returns: str: Retourne la position du roi dans l'échiquier. """ for position in self.echiquier.dictionnaire_pieces.keys(): if isinstance(self.echiquier.dictionnaire_pieces[position], Roi) \ and self.echiquier.dictionnaire_pieces[position].couleur == couleur_joueur_actif: return position def mon_roi_en_echec(self): """ Identifie si le Roi du joueur actif est en échec. Par en échec on entend que sa case est menacée par le joueur adverse. Si le joueur actif ne réagit pas à la menace, il perdra la partie au prochain tour. Returns: bool: True si le Roi du joueur actif est en échec, false autrement. """ position_roi = self.position_mon_roi(self.joueur_actif) if self.joueur_actif == 'blanc': autre_couleur = 'noir' else: autre_couleur = 'blanc' if self.partie_terminee(): return False return self.echiquier.case_est_menacee_par(position_roi, autre_couleur) def sauvegarder_partie(self): """ Permet de sauver la partie. """ with open(self.nom_fichier_sauvegarde, "wb") as f: pickle.dump(self.echiquier.dictionnaire_pieces, f) def charger_partie(self): """ Permet de charger une partie sauvegarder avec la méthode sauvergarder_partie """ with open(self.nom_fichier_sauvegarde, "rb") as f: self.echiquier.dictionnaire_pieces = pickle.load(f)