diff --git a/S1/Echecs/README.md b/S1/Echecs/README.md index 6a3470e..a752268 100644 --- a/S1/Echecs/README.md +++ b/S1/Echecs/README.md @@ -34,7 +34,11 @@ Le jeu de dame n'est pas implémenté, bien qu'il ne soit nécessaire de ne modi * Redimensionnement de la fenêtre -Il suffirait d'appeler PlateauTk.redimCan(min(xMax, yMax)) à chaque redimensionnement de la fenêtre. Cependant j'ai un peu de mal à comprendre comment fonctionne Tk. +Il suffirait d'appeler `PlateauTk.redimCan(min(xMax, yMax))` à chaque redimensionnement de la fenêtre. Cependant j'ai un peu de mal à comprendre comment fonctionne Tk. + +* Documenter et tester les fonctions + +Chaque fonction possède une brève description de son fonctionnemenent. L'ajout des types des arguments serait inutile, étant la majorité du temps des int. Le contenu des arguments s'expliquent par leur nom, à défaut par la description de la fonction. De plus, la majorité des fonctions dépendant de l'instance de leur classe, aucune doctest n'a été écrite, car cela aurait nécessité trop de code pour de simples fonctions. ###Objectifs personnels @@ -46,4 +50,4 @@ Bien que le code fonctionne, soit plutôt flexible, relativement documenté et u Le jeu actuel ne possède aucun point fort (au contraire) qui pourrait le démarquer des jeux d'Échecs existant. Très peu d'utilisateurs pourraient l'utiliser dans une optique autre que le développement ou le test. -Les commentaires affublés d'une marque `TODO` signifient qu'une \ No newline at end of file +Les commentaires affublés d'une marque `TODO` signifient que le code pourrait être amélioré à cet endroit, ou une fonctionnalité pourrait y être ajoutée. \ No newline at end of file diff --git a/S1/Echecs/app.py b/S1/Echecs/app.py index 5498250..61762b0 100755 --- a/S1/Echecs/app.py +++ b/S1/Echecs/app.py @@ -3,11 +3,4 @@ from guiTk import FenetreTk if __name__ == '__main__': - # p = PlateauTk(LogiqueEchecs()) f = FenetreTk() - -# TODO pion → piece Quand nécessaire -# TODO mvtSansEchec → depl -# TODO Entrée / Sortie ? -# TODO Doctest -# TODO cls au lieu de self quand nécessaires diff --git a/S1/Echecs/guiTk.py b/S1/Echecs/guiTk.py index 21b4f3c..ca97ea9 100644 --- a/S1/Echecs/guiTk.py +++ b/S1/Echecs/guiTk.py @@ -21,7 +21,7 @@ class PlateauTk: self.fen = fen # Fenêtre Tk (nécessaire pour lancer un timeout pour l'animation) self.statut = statut # Fonction qui envoie un message à l'utilisateur self.grilleDamier = [] # Tableau contenant les références aux cases du damier - self.grillePions = [] # Tableau contenant les références aux pièces + self.grillePieces = [] # Tableau contenant les références aux pièces self.photos = [] # Liste contenant les différentes photos utilisées (afin qu'elles ne soient pas recyclées) self.imagesOriginales = {} # Dictionnaire associant chaque pièce à son image originale self.imagesRedim = {} # Dictionnaire associant chaque pièce à son image redimensionnée @@ -57,7 +57,7 @@ class PlateauTk: self.redimImages() self.cDamier() self.cGrille() - self.remplirGrille(self.logique.grille) + self.remplirGrille() def nomPiece(self, piece): @@ -161,33 +161,33 @@ class PlateauTk: self.grilleDamier.append(colonne) self.coulDamier() - def cPion(self, x, y, piece): + def cPiece(self, x, y, piece): """ Crée la pièce aux coordonnées données """ if self.logique.ePiece(piece): - self.grillePions[x][y] = self.can.create_image((x + .5) * self.coteCase, (y + .5) * self.coteCase, image=self.imagesRedim[piece]) + self.grillePieces[x][y] = self.can.create_image((x + .5) * self.coteCase, (y + .5) * self.coteCase, image=self.imagesRedim[piece]) else: - self.grillePions[x][y] = False + self.grillePieces[x][y] = False def cGrille(self): """ Crée le tableau contenant les images de pièces """ - self.grillePions = [] - for x in range(0, self.logique.CASES_COTE): # Crée self.grillePions + self.grillePieces = [] + for x in range(0, self.logique.CASES_COTE): # Crée self.grillePieces colonne = [] for y in range(0, self.logique.CASES_COTE): colonne.append(False) - self.grillePions.append(colonne) + self.grillePieces.append(colonne) - def remplirGrille(self, j_grilleF): + def remplirGrille(self): """ Remplis la grille des images de pièce selon la grille des pièces logiques. """ - for x in range(0, self.logique.CASES_COTE): # Remplis self.grillePions + for x in range(0, self.logique.CASES_COTE): # Remplis self.grillePieces for y in range(0, self.logique.CASES_COTE): - self.cPion(x, y, j_grilleF[x][y]) + self.cPiece(x, y, self.logique.grille[x][y]) # Interaction def nomJoueur(self, joueur, pluriel=True): @@ -229,18 +229,18 @@ class PlateauTk: if i['avancement'] < i['total']: if i['type'] == 'd': coords = self.animationDCoords(i) - self.can.coords(i['pion'], coords[0], coords[1]) + self.can.coords(i['piece'], coords[0], coords[1]) # elif i['type'] == 'f': - # TODO Opacité de i['pion'] + # TODO Opacité de i['piece'] # elif i['type'] == 'c': # TODO Opacité de case i['avancement'] += self.INTER_ANIM animationsNv.append(i) else: if i['type'] == 'd': - self.can.coords(i['pion'], i['x2'], i['y2']) + self.can.coords(i['piece'], i['x2'], i['y2']) elif i['type'] == 'f': - self.can.delete(i['pion']) + self.can.delete(i['piece']) elif i['type'] == 'c': self.coulCase(i['x'], i['y'], 0) self.animations = animationsNv @@ -257,14 +257,14 @@ class PlateauTk: if etaitVide: self.animation() - def animerD(self, x1, y1, x2, y2, pion): + def animerD(self, x1, y1, x2, y2, piece): """ - Ajoute une animation pour un déplacment de pion + Ajoute une animation pour un déplacment de piece """ if len(self.animations): for i in self.animations: - if i['type'] == 'd' and i['pion'] == pion: - # Si une animation pour ce pion existe déjà, on la reprend et on la modifie + if i['type'] == 'd' and i['piece'] == piece: + # Si une animation pour cette pièce existe déjà, on la reprend et on la modifie coords = self.animationDCoords(i) i['x1'] = coords[0] # TODO Simplifier avec update() i['y1'] = coords[1] @@ -280,20 +280,20 @@ class PlateauTk: 'y1': y1, 'x2': x2, 'y2': y2, - 'pion': pion, + 'piece': piece, 'type': 'd', 'total': self.TEMPS_ANIM, 'avancement': 0 } - self.can.tag_raise(pion) # Mise au premier plan + self.can.tag_raise(piece) # Mise au premier plan self.animer(animation) - def animerF(self, pion): + def animerF(self, piece): """ - Ajoute une animation pour la suppression d'un pion + Ajoute une animation pour la suppression d'une pièce """ animation = { - 'pion': pion, + 'piece': piece, 'type': 'f', 'total': self.TEMPS_ANIM, 'avancement': 0 @@ -321,31 +321,31 @@ class PlateauTk: self.coulDamier() for x in range(0, self.logique.CASES_COTE): for y in range(0, self.logique.CASES_COTE): - pion = self.logique.grille[x][y] - if self.logique.ePiece(pion): - if self.logique.ePionNoir(pion) ^ self.logique.victorieux: + piece = self.logique.grille[x][y] + if self.logique.ePiece(piece): + if self.logique.ePieceNoir(piece) ^ self.logique.victorieux: self.coulCase(x, y, 2) else: self.coulCase(x, y, 3) - def dPion(self, x1, y1, x2, y2): + def dPiece(self, x1, y1, x2, y2): """ - Déplace le pion aux coordonnées 1 aux coordonnées 2. + Déplace la pièce aux coordonnées 1 aux coordonnées 2. (Vérifie la possibilité du mouvement et crée les animations nécessaires) """ - test = self.logique.dPion(x1, y1, x2, y2) + test = self.logique.dPiece(x1, y1, x2, y2) if test['valide'] == True: # Si déplacement possible for s in test['supprimer']: - self.animerF(self.grillePions[s[0]][s[1]]) + self.animerF(self.grillePieces[s[0]][s[1]]) for d in test['deplacer']: - self.grillePions[d[2]][d[3]], self.grillePions[d[0]][d[1]] = \ - self.grillePions[d[0]][d[1]], False + self.grillePieces[d[2]][d[3]], self.grillePieces[d[0]][d[1]] = \ + self.grillePieces[d[0]][d[1]], False self.animerD((d[0] + .5) * self.coteCase, (d[1] + .5) * self.coteCase, \ (d[2] + .5) * self.coteCase, (d[3] + .5) * self.coteCase, \ - self.grillePions[d[2]][d[3]]) + self.grillePieces[d[2]][d[3]]) else: - self.statut('Déplacment impossible ! (' + test['message'] + ')') + self.statut('Déplacment invalide ! (' + test['message'] + ')') return test['valide'] def dClic(self, x, y): @@ -361,14 +361,14 @@ class PlateauTk: self.mvtPossibleSansEchecs = self.logique.mvtsPossibles(self.dx1, self.dy1) # Surbrillance bleue for i in self.mvtPossibleSansEchecs: # Surbrillances vertes self.coulCase(i[0], i[1], 2) - self.statut('Poser') + self.statut('Cliquez où déposer la pièce.') self.dEtape = not self.dEtape else: # Si pas possible de jouer self.coulCase(self.dx1, self.dy1, 3) self.animerC(self.dx1, self.dy1) else: # Poser self.dx2, self.dy2 = x, y - if self.dPion(self.dx1, self.dy1, self.dx2, self.dy2) or (self.dx1 == self.dx2 and self.dy1 == self.dy2): # Si déplacement fait / Annule dépalcement + if self.dPiece(self.dx1, self.dy1, self.dx2, self.dy2) or (self.dx1 == self.dx2 and self.dy1 == self.dy2): # Si déplacement fait / Annule dépalcement self.coulDamier() # Effacer Surbrillance self.dEtape = not self.dEtape if self.logique.partieFinie: diff --git a/S1/Echecs/logique.py b/S1/Echecs/logique.py index 6a80618..77778ca 100644 --- a/S1/Echecs/logique.py +++ b/S1/Echecs/logique.py @@ -26,42 +26,42 @@ class Logique: colonne.append(self.PCE_VIDE) self.grille.append(colonne) - def ePionBlanc(self, pion): + def ePieceBlanc(self, piece): """ Indique si la pièce est une pièce blanche. """ - return pion in self.BLANCS + return piece in self.BLANCS - def ePionNoir(self, pion): + def ePieceNoir(self, piece): """ Indique si la pièce est une pièce noire. """ - return pion in self.NOIRS + return piece in self.NOIRS def ePiece(self, piece): """ Indique si la pièce est une pièce. """ # return piece != self.PCE_VIDE - return self.ePionBlanc(piece) or self.ePionNoir(piece) + return self.ePieceBlanc(piece) or self.ePieceNoir(piece) def tPiece(self, piece): """ Retourne le type de pièce de la pièce donnée. """ - if self.ePionBlanc(piece): + if self.ePieceBlanc(piece): return piece - self.DECALAGE_BLANCS - elif self.ePionNoir(piece): + elif self.ePieceNoir(piece): return piece - self.DECALAGE_NOIRS else: return self.PCE_VIDE - def aSonTour(self, pion): + def aSonTour(self, piece): """ Indique si la pièce donnée a le droit de jouer. """ - return (self.ePionNoir(pion) and self.joueur == self.NOIR) or \ - (self.ePionBlanc(pion) and self.joueur == self.BLANC) + return (self.ePieceNoir(piece) and self.joueur == self.NOIR) or \ + (self.ePieceBlanc(piece) and self.joueur == self.BLANC) class LogiqueEchecs(Logique): @@ -93,9 +93,9 @@ class LogiqueEchecs(Logique): MVT_SELECTION = 'Mauvais tour' MVT_SUR_PLACE = 'Immobile' MVT_SAUT_AMI = 'Saut ami' - MVT_PION_INC = 'Pion inconnu' + MVT_PIECE_INC = 'Pièce inconnu' MVT_N_AUTORISE = 'Non-autorisé' - MVT_OBSTRUCTION = 'Pion en chemin' + MVT_OBSTRUCTION = 'Pièce en chemin' MVT_ECHEC = 'Échec au roi' def __init__(self): @@ -121,7 +121,7 @@ class LogiqueEchecs(Logique): self.grille[i][6] = self.DECALAGE_BLANCS + self.PCE_PION self.grille[i][7] = self.DECALAGE_BLANCS + speciales[i] - def mvtPossibleSansEchecPion(self, x1, y1, x2, y2): + def deplPossiblePion(self, x1, y1, x2, y2): """ Vérifie si le déplacement est possible pour un pion. """ @@ -143,20 +143,20 @@ class LogiqueEchecs(Logique): elif abs(x1-x2) == 1: # Saut if self.joueur: if y2 == y1 - 1 and \ - self.ePionNoir(self.grille[x2][y2]): + self.ePieceNoir(self.grille[x2][y2]): return self.MVT_OK else: return self.MVT_N_AUTORISE else: if y2 == y1 + 1 and \ - self.ePionBlanc(self.grille[x2][y2]): + self.ePieceBlanc(self.grille[x2][y2]): return self.MVT_OK else: return self.MVT_N_AUTORISE else: return self.MVT_N_AUTORISE - def mvtPossibleSansEchecTour(self, x1, y1, x2, y2): + def deplPossibleTour(self, x1, y1, x2, y2): """ Vérifie si le déplacement est possible pour une tour. """ @@ -174,7 +174,7 @@ class LogiqueEchecs(Logique): return self.MVT_N_AUTORISE return self.MVT_OK - def mvtPossibleSansEchecFou(self, x1, y1, x2, y2): + def deplPossibleFou(self, x1, y1, x2, y2): """ Vérifie si le déplacement est possible pour un fou. """ @@ -198,7 +198,7 @@ class LogiqueEchecs(Logique): else: return self.MVT_N_AUTORISE - def mvtPossibleSansEchecCavalier(self, x1, y1, x2, y2): + def deplPossibleCavalier(self, x1, y1, x2, y2): """ Vérifie si le déplacement est possible pour un cavalier. """ @@ -207,39 +207,39 @@ class LogiqueEchecs(Logique): else: return self.MVT_N_AUTORISE - def mvtPossibleSansEchec(self, x1, y1, x2, y2): # TODO Utiliser la gestion d'erreurs ? + def deplPossible(self, x1, y1, x2, y2): # TODO Utiliser la gestion d'erreurs ? """ Vérifie si le déplacement est possible. """ - pion = self.grille[x1][y1] - if self.aSonTour(pion): + piece = self.grille[x1][y1] + if self.aSonTour(piece): if (x1 != x2 or y1 != y2): if not self.aSonTour(self.grille[x2][y2]): - tPion = self.tPiece(pion) - if tPion == self.PCE_PION: # Pion - return self.mvtPossibleSansEchecPion(x1, y1, x2, y2) - elif tPion == self.PCE_TOUR: # Tour - return self.mvtPossibleSansEchecTour(x1, y1, x2, y2) - elif tPion == self.PCE_CAVALIER: - return self.mvtPossibleSansEchecCavalier(x1, y1, x2, y2) - elif tPion == self.PCE_FOU: - return self.mvtPossibleSansEchecFou(x1, y1, x2, y2) - elif tPion == self.PCE_DAME: - tour = self.mvtPossibleSansEchecTour(x1, y1, x2, y2) - fou = self.mvtPossibleSansEchecFou(x1, y1, x2, y2) + tPiece = self.tPiece(piece) + if tPiece == self.PCE_PION: # Pion + return self.deplPossiblePion(x1, y1, x2, y2) + elif tPiece == self.PCE_TOUR: # Tour + return self.deplPossibleTour(x1, y1, x2, y2) + elif tPiece == self.PCE_CAVALIER: + return self.deplPossibleCavalier(x1, y1, x2, y2) + elif tPiece == self.PCE_FOU: + return self.deplPossibleFou(x1, y1, x2, y2) + elif tPiece == self.PCE_DAME: + tour = self.deplPossibleTour(x1, y1, x2, y2) + fou = self.deplPossibleFou(x1, y1, x2, y2) if tour == self.MVT_OK or fou == self.MVT_OK: return self.MVT_OK elif tour == self.MVT_OBSTRUCTION or fou == self.MVT_OBSTRUCTION: return self.MVT_OBSTRUCTION else: return self.MVT_N_AUTORISE - elif tPion == self.PCE_ROI: + elif tPiece == self.PCE_ROI: if abs(x2-x1) <= 1 and abs(y2-y1) <= 1: return self.MVT_OK else: return self.MVT_N_AUTORISE else: - return self.MVT_PION_INC + return self.MVT_PIECE_INC else: return self.MVT_SAUT_AMI else: @@ -254,19 +254,19 @@ class LogiqueEchecs(Logique): Contrairement aux fonctions de vérification de déplacement, celle-ci vérifie si le mouvement est réalisable si le roi est en échec. """ - test = self.mvtPossibleSansEchec(x1, y1, x2, y2) + test = self.deplPossible(x1, y1, x2, y2) if test == self.MVT_OK: # On copie la partie actuelle pour tester le mouvement et vérifier l'échec copie = copy.deepcopy(self); - copie.dPionSansEchec(x1, y1, x2, y2) + copie.dPieceSansEchec(x1, y1, x2, y2) mvtsPossiblesTousAdverses = [] # On cherche la position du roi - pionRoi = self.PCE_ROI + self.DECALAGE_BLANCS if self.joueur else self.DECALAGE_NOIRS + pieceRoi = self.PCE_ROI + self.DECALAGE_BLANCS if self.joueur else self.DECALAGE_NOIRS roi = [-1, -1] for x in range(0, self.CASES_COTE): for y in range(0, self.CASES_COTE): mvtsPossiblesTousAdverses += copie.mvtsPossiblesSansEchec(x, y) - if copie.grille[x][y] == pionRoi: + if copie.grille[x][y] == pieceRoi: roi = [x, y] if roi in mvtsPossiblesTousAdverses: # Si le roi peut être sauté au tour adverse return self.MVT_ECHEC @@ -282,7 +282,7 @@ class LogiqueEchecs(Logique): tableau = [] for x2 in range(0, self.CASES_COTE): for y2 in range(0, self.CASES_COTE): - if self.mvtPossibleSansEchec(x1, y1, x2, y2) == self.MVT_OK: + if self.deplPossible(x1, y1, x2, y2) == self.MVT_OK: tableau.append([x2, y2]) return tableau @@ -297,13 +297,13 @@ class LogiqueEchecs(Logique): tableau.append([x2, y2]) return tableau - def dPionSansEchec(self, x1, y1, x2, y2): + def dPieceSansEchec(self, x1, y1, x2, y2): """ - Déplace le pion aux coordonnées 1 données aux coordonnées 2 données. + Déplace la pièce aux coordonnées 1 données aux coordonnées 2 données. Ne vérifie pas si le mouvement peut conduire à une prise illégale du roi. (Est utilisé dans pour cette détection) """ - test = self.mvtPossibleSansEchec(x1, y1, x2, y2) + test = self.deplPossible(x1, y1, x2, y2) if test == self.MVT_OK: self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1] self.joueur = not self.joueur @@ -323,17 +323,17 @@ class LogiqueEchecs(Logique): self.victorieux = not self.joueur return True - def dPion(self, x1, y1, x2, y2): + def dPiece(self, x1, y1, x2, y2): """ - Déplace le pion aux coordonnées 1 données aux coordonnées 2 données. + Déplace la pièce aux coordonnées 1 données aux coordonnées 2 données. Renvoie les détails du mouvement. """ test = self.mvtPossible(x1, y1, x2, y2) retour = { 'valide': False, 'message': test, - 'deplacer': [], # Pions à déplacer - 'supprimer': [], # Pions à supprimer + 'deplacer': [], # Pièces à déplacer + 'supprimer': [], # Pièces à supprimer } if test == self.MVT_OK: retour['valide'] = True