[Echecs] Redevenu ami avec PyLint
This commit is contained in:
parent
a38bf44a9b
commit
ab48ed3e69
|
@ -1,42 +1,51 @@
|
||||||
from tkinter import *
|
from tkinter import *
|
||||||
from logique import LogiqueEchecs
|
from logique import LogiqueEchecs
|
||||||
|
|
||||||
|
|
||||||
class PlateauTk:
|
class PlateauTk:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Plateau de jeu de damier en canvas Tk
|
Plateau de jeu de damier en canvas Tk
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RATIO_PCE_CASE = .95 # Place que prend la pièce sur la case
|
RATIO_PCE_CASE = .95 # Place que prend la pièce sur la case
|
||||||
TEMPS_ANIM = 200 # Temps en ms d'une animation
|
TEMPS_ANIM = 200 # Temps en ms d'une animation
|
||||||
INTER_ANIM = 10 # Temps en ms entre deux actualisations d'animation
|
INTER_ANIM = 10 # Temps en ms entre deux actualisations d'animation
|
||||||
|
|
||||||
COTE_TOUT_DEFAUT = 500 # Coté par défaut du plateau
|
COTE_TOUT_DEFAUT = 500 # Coté par défaut du plateau
|
||||||
|
|
||||||
def __init__(self, fen, can, statut, logique):
|
def __init__(self, fen, can, statut, logique):
|
||||||
"""
|
"""
|
||||||
Constructeur de PlateauTk
|
Constructeur de PlateauTk
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.can = can # Canvas
|
self.can = can # Canvas
|
||||||
self.fen = fen # Fenêtre Tk (nécessaire pour lancer un timeout pour l'animation)
|
# Fenêtre Tk (nécessaire pour lancer un timeout pour l'animation)
|
||||||
self.statut = statut # Fonction qui envoie un message à l'utilisateur
|
self.fen = fen
|
||||||
self.grilleDamier = [] # Tableau contenant les références aux cases du damier
|
self.statut = statut # Fonction qui envoie un message à l'utilisateur
|
||||||
self.grillePieces = [] # Tableau contenant les références aux pièces
|
# Tableau contenant les références aux cases du damier
|
||||||
self.photos = [] # Liste contenant les différentes photos utilisées (afin qu'elles ne soient pas recyclées)
|
self.grilleDamier = []
|
||||||
self.imagesOriginales = {} # Dictionnaire associant chaque pièce à son image originale
|
self.grillePieces = [] # Tableau contenant les références aux pièces
|
||||||
self.imagesRedim = {} # Dictionnaire associant chaque pièce à son image redimensionnée
|
self.photos = [] # Liste contenant les différentes photos utilisées
|
||||||
self.animations = [] # Liste contenant les animations en cours
|
# (afin qu'elles ne soient pas recyclées)
|
||||||
|
# Dictionnaire associant chaque pièce à son image originale
|
||||||
|
self.imagesOriginales = {}
|
||||||
|
# Dictionnaire associant chaque pièce à son image redimensionnée
|
||||||
|
self.imagesRedim = {}
|
||||||
|
self.animations = [] # Liste contenant les animations en cours
|
||||||
|
|
||||||
self.dEtape = True # Étape du déplacement (True : prendre la pièce, False : poser la pièce)
|
# Étape du déplacement (True : prendre la pièce, False : poser la
|
||||||
self.dx1 = -1 # Coordonnées X de la pièce sélectionnée
|
# pièce)
|
||||||
self.dy1 = -1 # Coordonnées Y de la pièce sélectionnée
|
self.dEtape = True
|
||||||
self.dx2 = -1 # Coordonnées X de la destination
|
self.dx1 = -1 # Coordonnées X de la pièce sélectionnée
|
||||||
self.dy2 = -1 # Coordonnées Y de la destination
|
self.dy1 = -1 # Coordonnées Y de la pièce sélectionnée
|
||||||
self.mvtsPossibles = [] # Liste des mouvements possibles pour la pièce sélectionnée
|
self.dx2 = -1 # Coordonnées X de la destination
|
||||||
self.coteCase = 0 # Coté d'une case
|
self.dy2 = -1 # Coordonnées Y de la destination
|
||||||
|
# Liste des mouvements possibles pour la pièce sélectionnée
|
||||||
self.logique = logique # Logique du jeu
|
self.mvtsPossibles = []
|
||||||
|
self.coteCase = 0 # Coté d'une case
|
||||||
|
|
||||||
|
self.logique = logique # Logique du jeu
|
||||||
|
|
||||||
self.importerImages()
|
self.importerImages()
|
||||||
self.redimCan(self.COTE_TOUT_DEFAUT)
|
self.redimCan(self.COTE_TOUT_DEFAUT)
|
||||||
|
@ -59,33 +68,34 @@ class PlateauTk:
|
||||||
self.cGrille()
|
self.cGrille()
|
||||||
self.remplirGrille()
|
self.remplirGrille()
|
||||||
|
|
||||||
|
def nomPiece(self, tPiece):
|
||||||
def nomPiece(self, piece):
|
|
||||||
"""
|
"""
|
||||||
Renvoi le nom de fichier de la pièce donnée
|
Renvoi le nom de fichier de la pièce donnée
|
||||||
"""
|
"""
|
||||||
tPiece = self.logique.tPiece(piece)
|
|
||||||
if tPiece == self.logique.PCE_PION:
|
if tPiece == self.logique.PCE_PION:
|
||||||
return 'pion'
|
nom = 'pion'
|
||||||
elif tPiece == self.logique.PCE_TOUR:
|
elif tPiece == self.logique.PCE_TOUR:
|
||||||
return 'tour'
|
nom = 'tour'
|
||||||
elif tPiece == self.logique.PCE_CAVALIER:
|
elif tPiece == self.logique.PCE_CAVALIER:
|
||||||
return 'cavalier'
|
nom = 'cavalier'
|
||||||
elif tPiece == self.logique.PCE_FOU:
|
elif tPiece == self.logique.PCE_FOU:
|
||||||
return 'fou'
|
nom = 'fou'
|
||||||
elif tPiece == self.logique.PCE_DAME:
|
elif tPiece == self.logique.PCE_DAME:
|
||||||
return 'dame'
|
nom = 'dame'
|
||||||
elif tPiece == self.logique.PCE_ROI:
|
elif tPiece == self.logique.PCE_ROI:
|
||||||
return 'roi'
|
nom = 'roi'
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
return nom
|
||||||
|
|
||||||
def importerImage(self, piece, couleur): # TODO piece stocke déjà la couleur
|
# TODO piece stocke déjà la couleur
|
||||||
|
def importerImage(self, piece, couleur):
|
||||||
"""
|
"""
|
||||||
Importe l'image de la pièce donnée
|
Importe l'image de la pièce donnée
|
||||||
"""
|
"""
|
||||||
nom = 'sprites/'+self.nomPiece(piece)+couleur+'.gif'
|
nom = 'sprites/' + \
|
||||||
self.imagesOriginales.update({piece:PhotoImage(file=nom)})
|
self.nomPiece(self.logique.tPiece(piece)) + couleur + '.gif'
|
||||||
|
self.imagesOriginales.update({piece: PhotoImage(file=nom)})
|
||||||
|
|
||||||
def importerImages(self):
|
def importerImages(self):
|
||||||
"""
|
"""
|
||||||
|
@ -100,13 +110,15 @@ class PlateauTk:
|
||||||
"""
|
"""
|
||||||
Redimensionne l'image de la pièce donnée
|
Redimensionne l'image de la pièce donnée
|
||||||
"""
|
"""
|
||||||
self.imagesRedim.update({piece:self.imagesOriginales[piece].subsample(sample)})
|
self.imagesRedim.update(
|
||||||
|
{piece: self.imagesOriginales[piece].subsample(sample)})
|
||||||
|
|
||||||
def redimImages(self):
|
def redimImages(self):
|
||||||
"""
|
"""
|
||||||
Redimensionne l'image des pièces du jeu
|
Redimensionne l'image des pièces du jeu
|
||||||
"""
|
"""
|
||||||
sample = int(504 // (self.coteCase * self.RATIO_PCE_CASE)) # TODO S'en sort pour être toujours plus grand
|
sample = int(504 // (self.coteCase * self.RATIO_PCE_CASE)
|
||||||
|
) # TODO S'en sort pour être toujours plus grand
|
||||||
for piece in self.logique.BLANCS:
|
for piece in self.logique.BLANCS:
|
||||||
self.redimImage(piece, sample)
|
self.redimImage(piece, sample)
|
||||||
for piece in self.logique.NOIRS:
|
for piece in self.logique.NOIRS:
|
||||||
|
@ -118,28 +130,29 @@ class PlateauTk:
|
||||||
"""
|
"""
|
||||||
Retourne la couleur hexadécimale de la case de couleur et de contexte donnée
|
Retourne la couleur hexadécimale de la case de couleur et de contexte donnée
|
||||||
"""
|
"""
|
||||||
if contexte == 1: # Sélectionné
|
if contexte == 1: # Sélectionné
|
||||||
return '#a0cefe' if blanc else '#478bd1'
|
return '#a0cefe' if blanc else '#478bd1'
|
||||||
elif contexte == 2: # Possible / Victoire
|
elif contexte == 2: # Possible / Victoire
|
||||||
return '#bafea0' if blanc else '#6ed147'
|
return '#bafea0' if blanc else '#6ed147'
|
||||||
elif contexte == 3: # Impossible / Défaite
|
elif contexte == 3: # Impossible / Défaite
|
||||||
return '#fea0ab' if blanc else '#d14758'
|
return '#fea0ab' if blanc else '#d14758'
|
||||||
else: # Normal
|
else: # Normal
|
||||||
return '#ffce9e' if blanc else '#d18b47'
|
return '#ffce9e' if blanc else '#d18b47'
|
||||||
|
|
||||||
def cCase(self, x, y):
|
def cCase(self, x, y):
|
||||||
"""
|
"""
|
||||||
Crée la case aux coordonnées données
|
Crée la case aux coordonnées données
|
||||||
"""
|
"""
|
||||||
couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), 0)
|
return self.can.create_rectangle(x * self.coteCase, y * self.coteCase,
|
||||||
return self.can.create_rectangle(x * self.coteCase, y * self.coteCase, (x + 1) * self.coteCase, (y + 1) * self.coteCase)
|
(x + 1) * self.coteCase, (y + 1) * self.coteCase)
|
||||||
|
|
||||||
def coulCase(self, x, y, contexte=0):
|
def coulCase(self, x, y, contexte=0):
|
||||||
"""
|
"""
|
||||||
Colorie la case aux coordonnées données selon le contexte donné
|
Colorie la case aux coordonnées données selon le contexte donné
|
||||||
"""
|
"""
|
||||||
couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), contexte)
|
couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), contexte)
|
||||||
self.can.itemconfig(self.grilleDamier[x][y], fill=couleur, outline=couleur)
|
self.can.itemconfig(
|
||||||
|
self.grilleDamier[x][y], fill=couleur, outline=couleur)
|
||||||
|
|
||||||
def coulDamier(self, contexte=0):
|
def coulDamier(self, contexte=0):
|
||||||
"""
|
"""
|
||||||
|
@ -154,7 +167,7 @@ class PlateauTk:
|
||||||
Génère le damier
|
Génère le damier
|
||||||
"""
|
"""
|
||||||
self.grilleDamier = []
|
self.grilleDamier = []
|
||||||
for x in range(0, self.logique.CASES_COTE): # TODO Peut être amélioré
|
for x in range(0, self.logique.CASES_COTE): # TODO Peut être amélioré
|
||||||
colonne = []
|
colonne = []
|
||||||
for y in range(0, self.logique.CASES_COTE):
|
for y in range(0, self.logique.CASES_COTE):
|
||||||
colonne.append(self.cCase(x, y))
|
colonne.append(self.cCase(x, y))
|
||||||
|
@ -166,7 +179,8 @@ class PlateauTk:
|
||||||
Crée la pièce aux coordonnées données
|
Crée la pièce aux coordonnées données
|
||||||
"""
|
"""
|
||||||
if self.logique.ePiece(piece):
|
if self.logique.ePiece(piece):
|
||||||
self.grillePieces[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:
|
else:
|
||||||
self.grillePieces[x][y] = False
|
self.grillePieces[x][y] = False
|
||||||
|
|
||||||
|
@ -208,7 +222,8 @@ class PlateauTk:
|
||||||
"""
|
"""
|
||||||
Change le statut indiquant au joueur en cours de jouer.
|
Change le statut indiquant au joueur en cours de jouer.
|
||||||
"""
|
"""
|
||||||
self.statut('Aux ' + self.nomJoueur(self.logique.joueur, pluriel=True) + ' de sélectionner une pièce.')
|
self.statut('Aux ' + self.nomJoueur(self.logique.joueur, pluriel=True) +
|
||||||
|
' de sélectionner une pièce.')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def animationDCoords(i):
|
def animationDCoords(i):
|
||||||
|
@ -216,8 +231,8 @@ class PlateauTk:
|
||||||
Retourne les coordonnées auxquelles doit se placer une pièce en cours d'animation
|
Retourne les coordonnées auxquelles doit se placer une pièce en cours d'animation
|
||||||
"""
|
"""
|
||||||
# TODO Faire autre chose qu'une animation linéaire constante
|
# TODO Faire autre chose qu'une animation linéaire constante
|
||||||
x = i['x1'] + (i['x2']-i['x1']) * (i['avancement']/i['total'])
|
x = i['x1'] + (i['x2'] - i['x1']) * (i['avancement'] / i['total'])
|
||||||
y = i['y1'] + (i['y2']-i['y1']) * (i['avancement']/i['total'])
|
y = i['y1'] + (i['y2'] - i['y1']) * (i['avancement'] / i['total'])
|
||||||
return [x, y]
|
return [x, y]
|
||||||
|
|
||||||
def animation(self):
|
def animation(self):
|
||||||
|
@ -245,7 +260,8 @@ class PlateauTk:
|
||||||
self.coulCase(i['x'], i['y'], 0)
|
self.coulCase(i['x'], i['y'], 0)
|
||||||
self.animations = animationsNv
|
self.animations = animationsNv
|
||||||
if len(animationsNv): # Si il y aura encore des animations à faire
|
if len(animationsNv): # Si il y aura encore des animations à faire
|
||||||
self.fen.after(self.INTER_ANIM, self.animation) # On prévoit une image (boucle)
|
# On prévoit une image (boucle)
|
||||||
|
self.fen.after(self.INTER_ANIM, self.animation)
|
||||||
|
|
||||||
def animer(self, animation):
|
def animer(self, animation):
|
||||||
"""
|
"""
|
||||||
|
@ -264,9 +280,10 @@ class PlateauTk:
|
||||||
if len(self.animations):
|
if len(self.animations):
|
||||||
for i in self.animations:
|
for i in self.animations:
|
||||||
if i['type'] == 'd' and i['piece'] == piece:
|
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
|
# Si une animation pour cette pièce existe déjà, on la
|
||||||
|
# reprend et on la modifie
|
||||||
coords = self.animationDCoords(i)
|
coords = self.animationDCoords(i)
|
||||||
i['x1'] = coords[0] # TODO Simplifier avec update()
|
i['x1'] = coords[0] # TODO Simplifier avec update()
|
||||||
i['y1'] = coords[1]
|
i['y1'] = coords[1]
|
||||||
i['x2'] = x2
|
i['x2'] = x2
|
||||||
i['y2'] = y2
|
i['y2'] = y2
|
||||||
|
@ -285,7 +302,7 @@ class PlateauTk:
|
||||||
'total': self.TEMPS_ANIM,
|
'total': self.TEMPS_ANIM,
|
||||||
'avancement': 0
|
'avancement': 0
|
||||||
}
|
}
|
||||||
self.can.tag_raise(piece) # Mise au premier plan
|
self.can.tag_raise(piece) # Mise au premier plan
|
||||||
self.animer(animation)
|
self.animer(animation)
|
||||||
|
|
||||||
def animerF(self, piece):
|
def animerF(self, piece):
|
||||||
|
@ -300,7 +317,7 @@ class PlateauTk:
|
||||||
}
|
}
|
||||||
self.animer(animation)
|
self.animer(animation)
|
||||||
|
|
||||||
def animerC(self, x ,y):
|
def animerC(self, x, y):
|
||||||
"""
|
"""
|
||||||
Ajoute une animation pour l'effacement de la surbrillance d'une case
|
Ajoute une animation pour l'effacement de la surbrillance d'une case
|
||||||
"""
|
"""
|
||||||
|
@ -317,7 +334,8 @@ class PlateauTk:
|
||||||
"""
|
"""
|
||||||
Indique à l'utilisateur la victoire et décore le plateau pour l'occasion
|
Indique à l'utilisateur la victoire et décore le plateau pour l'occasion
|
||||||
"""
|
"""
|
||||||
self.statut('Victoire des ' + self.nomJoueur(self.logique.victorieux) + ' !')
|
self.statut(
|
||||||
|
'Victoire des ' + self.nomJoueur(self.logique.victorieux) + ' !')
|
||||||
self.coulDamier()
|
self.coulDamier()
|
||||||
for x in range(0, self.logique.CASES_COTE):
|
for x in range(0, self.logique.CASES_COTE):
|
||||||
for y in range(0, self.logique.CASES_COTE):
|
for y in range(0, self.logique.CASES_COTE):
|
||||||
|
@ -334,16 +352,16 @@ class PlateauTk:
|
||||||
(Vérifie la possibilité du mouvement et crée les animations nécessaires)
|
(Vérifie la possibilité du mouvement et crée les animations nécessaires)
|
||||||
"""
|
"""
|
||||||
test = self.logique.dPiece(x1, y1, x2, y2)
|
test = self.logique.dPiece(x1, y1, x2, y2)
|
||||||
if test['valide'] == True: # Si déplacement possible
|
if test['valide'] == True: # Si déplacement possible
|
||||||
for s in test['supprimer']:
|
for s in test['supprimer']:
|
||||||
self.animerF(self.grillePieces[s[0]][s[1]])
|
self.animerF(self.grillePieces[s[0]][s[1]])
|
||||||
for d in test['deplacer']:
|
for d in test['deplacer']:
|
||||||
self.grillePieces[d[2]][d[3]], self.grillePieces[d[0]][d[1]] = \
|
self.grillePieces[d[2]][d[3]], self.grillePieces[d[0]][d[1]] = \
|
||||||
self.grillePieces[d[0]][d[1]], False
|
self.grillePieces[d[0]][d[1]], False
|
||||||
self.animerD((d[0] + .5) * self.coteCase, (d[1] + .5) * self.coteCase, \
|
self.animerD((d[0] + .5) * self.coteCase, (d[1] + .5) * self.coteCase,
|
||||||
(d[2] + .5) * self.coteCase, (d[3] + .5) * self.coteCase, \
|
(d[2] + .5) *
|
||||||
self.grillePieces[d[2]][d[3]])
|
self.coteCase, (d[3] + .5) * self.coteCase,
|
||||||
|
self.grillePieces[d[2]][d[3]])
|
||||||
else:
|
else:
|
||||||
self.statut('Déplacment invalide ! (' + test['message'] + ')')
|
self.statut('Déplacment invalide ! (' + test['message'] + ')')
|
||||||
return test['valide']
|
return test['valide']
|
||||||
|
@ -353,29 +371,34 @@ class PlateauTk:
|
||||||
Réagit en fonction d'un clic sur une case aux coordonnées données
|
Réagit en fonction d'un clic sur une case aux coordonnées données
|
||||||
"""
|
"""
|
||||||
if not self.logique.partieFinie:
|
if not self.logique.partieFinie:
|
||||||
if self.dEtape: # Prendre
|
if self.dEtape: # Prendre
|
||||||
self.dx1, self.dy1 = x, y
|
self.dx1, self.dy1 = x, y
|
||||||
self.coulDamier() # Effacement des surbrillances
|
self.coulDamier() # Effacement des surbrillances
|
||||||
if self.logique.aSonTour(self.logique.grille[self.dx1][self.dy1]): # Si possible jouer
|
# Si peut jouer
|
||||||
|
if self.logique.aSonTour(self.logique.grille[self.dx1][self.dy1]):
|
||||||
self.coulCase(self.dx1, self.dy1, 1)
|
self.coulCase(self.dx1, self.dy1, 1)
|
||||||
self.mvtPossibleSansEchecs = self.logique.mvtsPossibles(self.dx1, self.dy1) # Surbrillance bleue
|
self.mvtsPossibles = \
|
||||||
for i in self.mvtPossibleSansEchecs: # Surbrillances vertes
|
self.logique.mvtsPossibles(
|
||||||
|
self.dx1, self.dy1) # Surbrillance bleue
|
||||||
|
for i in self.mvtsPossibles: # Surbrillances vertes
|
||||||
self.coulCase(i[0], i[1], 2)
|
self.coulCase(i[0], i[1], 2)
|
||||||
self.statut('Cliquez où déposer la pièce.')
|
self.statut('Cliquez où déposer la pièce.')
|
||||||
self.dEtape = not self.dEtape
|
self.dEtape = not self.dEtape
|
||||||
else: # Si pas possible de jouer
|
else: # Si ne peut jouer
|
||||||
self.coulCase(self.dx1, self.dy1, 3)
|
self.coulCase(self.dx1, self.dy1, 3)
|
||||||
self.animerC(self.dx1, self.dy1)
|
self.animerC(self.dx1, self.dy1)
|
||||||
else: # Poser
|
else: # Poser
|
||||||
self.dx2, self.dy2 = x, y
|
self.dx2, self.dy2 = x, y
|
||||||
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
|
if self.dPiece(self.dx1, self.dy1, self.dx2, self.dy2) or \
|
||||||
self.coulDamier() # Effacer Surbrillance
|
(self.dx1 == self.dx2 and self.dy1 == self.dy2):
|
||||||
|
# Si déplacement fait / annulé
|
||||||
|
self.coulDamier() # Effacer Surbrillance
|
||||||
self.dEtape = not self.dEtape
|
self.dEtape = not self.dEtape
|
||||||
if self.logique.partieFinie:
|
if self.logique.partieFinie:
|
||||||
self.victoire()
|
self.victoire()
|
||||||
else:
|
else:
|
||||||
self.statutPrendre()
|
self.statutPrendre()
|
||||||
else: # Si mauvais déplacement
|
else: # Si mauvais déplacement
|
||||||
self.coulCase(self.dx2, self.dy2, 3)
|
self.coulCase(self.dx2, self.dy2, 3)
|
||||||
self.animerC(self.dx2, self.dy2)
|
self.animerC(self.dx2, self.dy2)
|
||||||
|
|
||||||
|
@ -383,27 +406,29 @@ class PlateauTk:
|
||||||
"""
|
"""
|
||||||
Réagit en fonction d'un clic
|
Réagit en fonction d'un clic
|
||||||
"""
|
"""
|
||||||
# if event.x in range(0, self.coteCase * self.logique.CASES_COTE) and event.y in range(0, self.coteCase * self.logique.CASES_COTE):
|
# if event.x in range(0, self.coteCase * self.logique.CASES_COTE) \
|
||||||
|
# and event.y in range(0, self.coteCase * self.logique.CASES_COTE):
|
||||||
self.dClic(event.x // self.coteCase, event.y // self.coteCase)
|
self.dClic(event.x // self.coteCase, event.y // self.coteCase)
|
||||||
|
|
||||||
|
|
||||||
class FenetreTk:
|
class FenetreTk:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Fenêtre pour jouer à des jeux sur damier
|
Fenêtre pour jouer à des jeux sur damier
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PLACEHOLDER_DIMENSIONS = 300 # Coté du canvas vide du début
|
PLACEHOLDER_DIMENSIONS = 300 # Coté du canvas vide du début
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
Constructeur de FenetreTk
|
Constructeur de FenetreTk
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.fen = None # Objet Fenêtre
|
self.fen = None # Objet Fenêtre
|
||||||
self.can = None # Objet Canvas
|
self.can = None # Objet Canvas
|
||||||
self.chaine = None # Objet Label de statut
|
self.chaine = None # Objet Label de statut
|
||||||
|
|
||||||
self.plateau = None # Plateau de jeu
|
self.plateau = None # Plateau de jeu
|
||||||
|
|
||||||
self.creerFen()
|
self.creerFen()
|
||||||
self.fen.mainloop()
|
self.fen.mainloop()
|
||||||
|
@ -414,12 +439,15 @@ class FenetreTk:
|
||||||
"""
|
"""
|
||||||
self.fen = Tk()
|
self.fen = Tk()
|
||||||
self.fen.title("Jeu de plateau")
|
self.fen.title("Jeu de plateau")
|
||||||
self.can = Canvas(self.fen, width=self.PLACEHOLDER_DIMENSIONS, height=self.PLACEHOLDER_DIMENSIONS, bg="ivory")
|
self.can = Canvas(self.fen, width=self.PLACEHOLDER_DIMENSIONS,
|
||||||
|
height=self.PLACEHOLDER_DIMENSIONS, bg="ivory")
|
||||||
self.can.grid(row=0, column=1, columnspan=3)
|
self.can.grid(row=0, column=1, columnspan=3)
|
||||||
self.chaine = Label(self.fen, text="Bienvenue !")
|
self.chaine = Label(self.fen, text="Bienvenue !")
|
||||||
self.chaine.grid(row=2, column=2, padx=3, pady=3)
|
self.chaine.grid(row=2, column=2, padx=3, pady=3)
|
||||||
Button(self.fen, text="Nv. Partie", command=self.nvPartie).grid(row=2, column=1, padx=3, pady=3)
|
Button(self.fen, text="Nv. Partie", command=self.nvPartie)\
|
||||||
Button(self.fen, text="Quitter", command=self.fen.destroy).grid(row=2, column=3, padx=3, pady=3)
|
.grid(row=2, column=1, padx=3, pady=3)
|
||||||
|
Button(self.fen, text="Quitter", command=self.fen.destroy)\
|
||||||
|
.grid(row=2, column=3, padx=3, pady=3)
|
||||||
|
|
||||||
def statut(self, texte, delai=0):
|
def statut(self, texte, delai=0):
|
||||||
"""
|
"""
|
||||||
|
@ -435,4 +463,5 @@ class FenetreTk:
|
||||||
Démarre une nouvelle partie.
|
Démarre une nouvelle partie.
|
||||||
"""
|
"""
|
||||||
del self.plateau
|
del self.plateau
|
||||||
self.plateau = PlateauTk(self.fen, self.can, self.statut, LogiqueEchecs())
|
self.plateau = PlateauTk(
|
||||||
|
self.fen, self.can, self.statut, LogiqueEchecs())
|
||||||
|
|
|
@ -1,13 +1,34 @@
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
|
||||||
class Logique:
|
class Logique:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Logique des jeux sur damier
|
Logique des jeux sur damier
|
||||||
|
(Ne peut être utilisé seul)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PCE_VIDE = 0 # Valeur à mettre sur la grille quand il n'y a pas de pièce
|
PCE_VIDE = 0 # Valeur à mettre sur la grille quand il n'y a pas de pièce
|
||||||
BLANC = True # Valeur correspondant au joueur blanc
|
BLANC = True # Valeur correspondant au joueur blanc
|
||||||
NOIR = False # Valeur correspondant au joueur noir
|
NOIR = False # Valeur correspondant au joueur noir
|
||||||
|
|
||||||
|
# Valeurs devant être remplies par une classe héritante
|
||||||
|
CASES_COTE = 0 # Cases de coté
|
||||||
|
|
||||||
|
# Valeur à partir de laquelle sont comprises les pièces blanches
|
||||||
|
DECALAGE_BLANCS = 0
|
||||||
|
# Valeur à partir de laquelle sont comprises les pièces noires
|
||||||
|
DECALAGE_NOIRS = 0
|
||||||
|
|
||||||
|
BLANCS = range(0) # Intervalle contenant les pièces blanches
|
||||||
|
NOIRS = range(0) # Intervalle contenant les pièces noires
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.grille = [] # Grille de jeu
|
||||||
|
self.cGrille()
|
||||||
|
self.joueur = self.BLANC # Premier joueur
|
||||||
|
self.partieFinie = False
|
||||||
|
self.victorieux = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def eCaseBlanche(x, y):
|
def eCaseBlanche(x, y):
|
||||||
|
@ -20,7 +41,7 @@ class Logique:
|
||||||
"""
|
"""
|
||||||
Crée le tableau self.grille.
|
Crée le tableau self.grille.
|
||||||
"""
|
"""
|
||||||
for x in range(self.CASES_COTE): # TODO Peut être amélioré
|
for x in range(self.CASES_COTE): # TODO Peut être amélioré
|
||||||
colonne = []
|
colonne = []
|
||||||
for y in range(self.CASES_COTE):
|
for y in range(self.CASES_COTE):
|
||||||
colonne.append(self.PCE_VIDE)
|
colonne.append(self.PCE_VIDE)
|
||||||
|
@ -40,7 +61,7 @@ class Logique:
|
||||||
|
|
||||||
def ePiece(self, piece):
|
def ePiece(self, piece):
|
||||||
"""
|
"""
|
||||||
Indique si la pièce est une pièce.
|
Indique si la pièce donnée est une pièce.
|
||||||
"""
|
"""
|
||||||
# return piece != self.PCE_VIDE
|
# return piece != self.PCE_VIDE
|
||||||
return self.ePieceBlanc(piece) or self.ePieceNoir(piece)
|
return self.ePieceBlanc(piece) or self.ePieceNoir(piece)
|
||||||
|
@ -61,15 +82,16 @@ class Logique:
|
||||||
Indique si la pièce donnée a le droit de jouer.
|
Indique si la pièce donnée a le droit de jouer.
|
||||||
"""
|
"""
|
||||||
return (self.ePieceNoir(piece) and self.joueur == self.NOIR) or \
|
return (self.ePieceNoir(piece) and self.joueur == self.NOIR) or \
|
||||||
(self.ePieceBlanc(piece) and self.joueur == self.BLANC)
|
(self.ePieceBlanc(piece) and self.joueur == self.BLANC)
|
||||||
|
|
||||||
|
|
||||||
class LogiqueEchecs(Logique):
|
class LogiqueEchecs(Logique):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Logique du jeu d'Échecs
|
Logique du jeu d'Échecs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CASES_COTE = 8 # Cases de coté
|
CASES_COTE = 8 # Cases de coté
|
||||||
|
|
||||||
# Type de pièces
|
# Type de pièces
|
||||||
PCE_PION = 1
|
PCE_PION = 1
|
||||||
|
@ -79,12 +101,15 @@ class LogiqueEchecs(Logique):
|
||||||
PCE_DAME = 5
|
PCE_DAME = 5
|
||||||
PCE_ROI = 6
|
PCE_ROI = 6
|
||||||
|
|
||||||
DECALAGE_BLANCS = 0 # Valeur à partir de laquelle sont compris les pièces blanches
|
# Valeur à partir de laquelle sont comprises les pièces blanches
|
||||||
DECALAGE_NOIRS = 10 # Valeur à partir de laquelle sont compris les pièces noires
|
DECALAGE_BLANCS = 0
|
||||||
|
# Valeur à partir de laquelle sont comprises les pièces noires
|
||||||
BLANCS = range(DECALAGE_BLANCS+PCE_PION, DECALAGE_BLANCS+PCE_ROI+1) # Intervalle contenant les pièces blancs
|
DECALAGE_NOIRS = 10
|
||||||
NOIRS = range(DECALAGE_NOIRS+PCE_PION, DECALAGE_NOIRS+PCE_ROI+1) # Intervalle contenant les pièces noirs
|
|
||||||
|
|
||||||
|
BLANCS = range(DECALAGE_BLANCS + PCE_PION, DECALAGE_BLANCS + PCE_ROI + 1)
|
||||||
|
# Intervalle contenant les pièces blanches
|
||||||
|
NOIRS = range(DECALAGE_NOIRS + PCE_PION, DECALAGE_NOIRS + PCE_ROI + 1)
|
||||||
|
# Intervalle contenant les pièces noires
|
||||||
|
|
||||||
# Codes d'erreur de mouvement
|
# Codes d'erreur de mouvement
|
||||||
MVT_INCONNU = 'Cause inconnue'
|
MVT_INCONNU = 'Cause inconnue'
|
||||||
|
@ -102,18 +127,15 @@ class LogiqueEchecs(Logique):
|
||||||
"""
|
"""
|
||||||
Constructeur de LogiqueEchecs
|
Constructeur de LogiqueEchecs
|
||||||
"""
|
"""
|
||||||
self.grille = [] # Grille de jeu
|
Logique.__init__(self)
|
||||||
self.cGrille()
|
|
||||||
self.remplirGrille()
|
self.remplirGrille()
|
||||||
self.joueur = self.BLANC # Premier joueur
|
|
||||||
self.partieFinie = False
|
|
||||||
self.victorieux = None
|
|
||||||
|
|
||||||
def remplirGrille(self):
|
def remplirGrille(self):
|
||||||
"""
|
"""
|
||||||
Remplis la grille avec les pièces nécessaire à une nouvelle partie.
|
Remplis la grille avec les pièces nécessaire à une nouvelle partie.
|
||||||
"""
|
"""
|
||||||
speciales = [self.PCE_TOUR, self.PCE_CAVALIER, self.PCE_FOU, self.PCE_ROI, self.PCE_DAME]
|
speciales = [self.PCE_TOUR, self.PCE_CAVALIER,
|
||||||
|
self.PCE_FOU, self.PCE_ROI, self.PCE_DAME]
|
||||||
speciales += speciales[2::-1]
|
speciales += speciales[2::-1]
|
||||||
for i in range(0, 8):
|
for i in range(0, 8):
|
||||||
self.grille[i][0] = self.DECALAGE_NOIRS + speciales[i]
|
self.grille[i][0] = self.DECALAGE_NOIRS + speciales[i]
|
||||||
|
@ -125,7 +147,7 @@ class LogiqueEchecs(Logique):
|
||||||
"""
|
"""
|
||||||
Vérifie si le déplacement est possible pour un pion.
|
Vérifie si le déplacement est possible pour un pion.
|
||||||
"""
|
"""
|
||||||
if x1 == x2 and self.grille[x2][y2] <= 0: # Avance
|
if x1 == x2 and self.grille[x2][y2] <= 0: # Avance
|
||||||
if self.joueur:
|
if self.joueur:
|
||||||
if y2 == y1 - 1:
|
if y2 == y1 - 1:
|
||||||
return self.MVT_OK
|
return self.MVT_OK
|
||||||
|
@ -140,16 +162,16 @@ class LogiqueEchecs(Logique):
|
||||||
return self.MVT_OK
|
return self.MVT_OK
|
||||||
else:
|
else:
|
||||||
return self.MVT_N_AUTORISE
|
return self.MVT_N_AUTORISE
|
||||||
elif abs(x1-x2) == 1: # Saut
|
elif abs(x1 - x2) == 1: # Saut
|
||||||
if self.joueur:
|
if self.joueur:
|
||||||
if y2 == y1 - 1 and \
|
if y2 == y1 - 1 and \
|
||||||
self.ePieceNoir(self.grille[x2][y2]):
|
self.ePieceNoir(self.grille[x2][y2]):
|
||||||
return self.MVT_OK
|
return self.MVT_OK
|
||||||
else:
|
else:
|
||||||
return self.MVT_N_AUTORISE
|
return self.MVT_N_AUTORISE
|
||||||
else:
|
else:
|
||||||
if y2 == y1 + 1 and \
|
if y2 == y1 + 1 and \
|
||||||
self.ePieceBlanc(self.grille[x2][y2]):
|
self.ePieceBlanc(self.grille[x2][y2]):
|
||||||
return self.MVT_OK
|
return self.MVT_OK
|
||||||
else:
|
else:
|
||||||
return self.MVT_N_AUTORISE
|
return self.MVT_N_AUTORISE
|
||||||
|
@ -161,13 +183,13 @@ class LogiqueEchecs(Logique):
|
||||||
Vérifie si le déplacement est possible pour une tour.
|
Vérifie si le déplacement est possible pour une tour.
|
||||||
"""
|
"""
|
||||||
if y1 == y2:
|
if y1 == y2:
|
||||||
sens = (x2-x1)//abs(x2-x1)
|
sens = (x2 - x1) // abs(x2 - x1)
|
||||||
for x in range(x1+sens, x2, sens):
|
for x in range(x1 + sens, x2, sens):
|
||||||
if self.ePiece(self.grille[x][y1]):
|
if self.ePiece(self.grille[x][y1]):
|
||||||
return self.MVT_OBSTRUCTION
|
return self.MVT_OBSTRUCTION
|
||||||
elif x1 == x2:
|
elif x1 == x2:
|
||||||
sens = (y2-y1)//abs(y2-y1)
|
sens = (y2 - y1) // abs(y2 - y1)
|
||||||
for y in range(y1+sens, y2, sens):
|
for y in range(y1 + sens, y2, sens):
|
||||||
if self.ePiece(self.grille[x1][y]):
|
if self.ePiece(self.grille[x1][y]):
|
||||||
return self.MVT_OBSTRUCTION
|
return self.MVT_OBSTRUCTION
|
||||||
else:
|
else:
|
||||||
|
@ -178,23 +200,23 @@ class LogiqueEchecs(Logique):
|
||||||
"""
|
"""
|
||||||
Vérifie si le déplacement est possible pour un fou.
|
Vérifie si le déplacement est possible pour un fou.
|
||||||
"""
|
"""
|
||||||
if abs(x2-x1) == abs(y2-y1):
|
if abs(x2 - x1) == abs(y2 - y1):
|
||||||
sensX = (x2-x1)//abs(x2-x1)
|
sensX = (x2 - x1) // abs(x2 - x1)
|
||||||
sensY = (y2-y1)//abs(y2-y1)
|
sensY = (y2 - y1) // abs(y2 - y1)
|
||||||
x = x1
|
x = x1
|
||||||
y = y1
|
y = y1
|
||||||
dist = 0
|
dist = 0
|
||||||
distTot = abs(x2-x1)
|
distTot = abs(x2 - x1)
|
||||||
while dist < distTot:
|
while dist < distTot:
|
||||||
dist += 1
|
dist += 1
|
||||||
x += sensX
|
x += sensX
|
||||||
y += sensY
|
y += sensY
|
||||||
if self.ePiece(self.grille[x][y]):
|
if self.ePiece(self.grille[x][y]):
|
||||||
if dist == distTot:
|
if dist == distTot:
|
||||||
return self.MVT_OK # Saut
|
return self.MVT_OK # Saut
|
||||||
else:
|
else:
|
||||||
return self.MVT_OBSTRUCTION
|
return self.MVT_OBSTRUCTION
|
||||||
return self.MVT_OK # Vide
|
return self.MVT_OK # Vide
|
||||||
else:
|
else:
|
||||||
return self.MVT_N_AUTORISE
|
return self.MVT_N_AUTORISE
|
||||||
|
|
||||||
|
@ -202,23 +224,24 @@ class LogiqueEchecs(Logique):
|
||||||
"""
|
"""
|
||||||
Vérifie si le déplacement est possible pour un cavalier.
|
Vérifie si le déplacement est possible pour un cavalier.
|
||||||
"""
|
"""
|
||||||
if (abs(x2-x1) == 2 and abs(y2-y1) == 1) or (abs(y2-y1) == 2 and abs(x2-x1) == 1):
|
if (abs(x2 - x1) == 2 and abs(y2 - y1) == 1) or (abs(y2 - y1) == 2 and abs(x2 - x1) == 1):
|
||||||
return self.MVT_OK
|
return self.MVT_OK
|
||||||
else:
|
else:
|
||||||
return self.MVT_N_AUTORISE
|
return self.MVT_N_AUTORISE
|
||||||
|
|
||||||
def deplPossible(self, x1, y1, x2, y2): # TODO Utiliser la gestion d'erreurs ?
|
# TODO Utiliser la gestion d'erreurs ?
|
||||||
|
def deplPossible(self, x1, y1, x2, y2):
|
||||||
"""
|
"""
|
||||||
Vérifie si le déplacement est possible.
|
Vérifie si le déplacement est possible.
|
||||||
"""
|
"""
|
||||||
piece = self.grille[x1][y1]
|
piece = self.grille[x1][y1]
|
||||||
if self.aSonTour(piece):
|
if self.aSonTour(piece):
|
||||||
if (x1 != x2 or y1 != y2):
|
if x1 != x2 or y1 != y2:
|
||||||
if not self.aSonTour(self.grille[x2][y2]):
|
if not self.aSonTour(self.grille[x2][y2]):
|
||||||
tPiece = self.tPiece(piece)
|
tPiece = self.tPiece(piece)
|
||||||
if tPiece == self.PCE_PION: # Pion
|
if tPiece == self.PCE_PION: # Pion
|
||||||
return self.deplPossiblePion(x1, y1, x2, y2)
|
return self.deplPossiblePion(x1, y1, x2, y2)
|
||||||
elif tPiece == self.PCE_TOUR: # Tour
|
elif tPiece == self.PCE_TOUR: # Tour
|
||||||
return self.deplPossibleTour(x1, y1, x2, y2)
|
return self.deplPossibleTour(x1, y1, x2, y2)
|
||||||
elif tPiece == self.PCE_CAVALIER:
|
elif tPiece == self.PCE_CAVALIER:
|
||||||
return self.deplPossibleCavalier(x1, y1, x2, y2)
|
return self.deplPossibleCavalier(x1, y1, x2, y2)
|
||||||
|
@ -234,8 +257,8 @@ class LogiqueEchecs(Logique):
|
||||||
else:
|
else:
|
||||||
return self.MVT_N_AUTORISE
|
return self.MVT_N_AUTORISE
|
||||||
elif tPiece == self.PCE_ROI:
|
elif tPiece == self.PCE_ROI:
|
||||||
if abs(x2-x1) <= 1 and abs(y2-y1) <= 1:
|
if abs(x2 - x1) <= 1 and abs(y2 - y1) <= 1:
|
||||||
return self.MVT_OK
|
return self.MVT_OK
|
||||||
else:
|
else:
|
||||||
return self.MVT_N_AUTORISE
|
return self.MVT_N_AUTORISE
|
||||||
else:
|
else:
|
||||||
|
@ -256,19 +279,23 @@ class LogiqueEchecs(Logique):
|
||||||
"""
|
"""
|
||||||
test = self.deplPossible(x1, y1, x2, y2)
|
test = self.deplPossible(x1, y1, x2, y2)
|
||||||
if test == self.MVT_OK:
|
if test == self.MVT_OK:
|
||||||
# On copie la partie actuelle pour tester le mouvement et vérifier l'échec
|
# On copie la partie actuelle pour tester le mouvement et vérifier
|
||||||
copie = copy.deepcopy(self);
|
# l'échec
|
||||||
|
copie = copy.deepcopy(self)
|
||||||
copie.dPieceSansEchec(x1, y1, x2, y2)
|
copie.dPieceSansEchec(x1, y1, x2, y2)
|
||||||
mvtsPossiblesTousAdverses = []
|
mvtsPossiblesTousAdverses = []
|
||||||
# On cherche la position du roi
|
# On cherche la position du roi
|
||||||
pieceRoi = 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]
|
roi = [-1, -1]
|
||||||
for x in range(0, self.CASES_COTE):
|
for x in range(0, self.CASES_COTE):
|
||||||
for y in range(0, self.CASES_COTE):
|
for y in range(0, self.CASES_COTE):
|
||||||
mvtsPossiblesTousAdverses += copie.mvtsPossiblesSansEchec(x, y)
|
mvtsPossiblesTousAdverses += copie.mvtsPossiblesSansEchec(
|
||||||
|
x, y)
|
||||||
if copie.grille[x][y] == pieceRoi:
|
if copie.grille[x][y] == pieceRoi:
|
||||||
roi = [x, y]
|
roi = [x, y]
|
||||||
if roi in mvtsPossiblesTousAdverses: # Si le roi peut être sauté au tour adverse
|
# Si le roi peut être sauté au tour adverse
|
||||||
|
if roi in mvtsPossiblesTousAdverses:
|
||||||
return self.MVT_ECHEC
|
return self.MVT_ECHEC
|
||||||
else:
|
else:
|
||||||
return test
|
return test
|
||||||
|
@ -305,7 +332,8 @@ class LogiqueEchecs(Logique):
|
||||||
"""
|
"""
|
||||||
test = self.deplPossible(x1, y1, x2, y2)
|
test = self.deplPossible(x1, y1, x2, y2)
|
||||||
if test == self.MVT_OK:
|
if test == self.MVT_OK:
|
||||||
self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1]
|
self.grille[x1][y1], self.grille[x2][
|
||||||
|
y2] = self.PCE_VIDE, self.grille[x1][y1]
|
||||||
self.joueur = not self.joueur
|
self.joueur = not self.joueur
|
||||||
|
|
||||||
def vEchecMat(self):
|
def vEchecMat(self):
|
||||||
|
@ -332,15 +360,16 @@ class LogiqueEchecs(Logique):
|
||||||
retour = {
|
retour = {
|
||||||
'valide': False,
|
'valide': False,
|
||||||
'message': test,
|
'message': test,
|
||||||
'deplacer': [], # Pièces à déplacer
|
'deplacer': [], # Pièces à déplacer
|
||||||
'supprimer': [], # Pièces à supprimer
|
'supprimer': [], # Pièces à supprimer
|
||||||
}
|
}
|
||||||
if test == self.MVT_OK:
|
if test == self.MVT_OK:
|
||||||
retour['valide'] = True
|
retour['valide'] = True
|
||||||
if self.ePiece(self.grille[x2][y2]):
|
if self.ePiece(self.grille[x2][y2]):
|
||||||
retour['supprimer'].append([x2, y2])
|
retour['supprimer'].append([x2, y2])
|
||||||
retour['deplacer'].append([x1, y1, x2, y2])
|
retour['deplacer'].append([x1, y1, x2, y2])
|
||||||
self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1]
|
self.grille[x1][y1], self.grille[x2][
|
||||||
|
y2] = self.PCE_VIDE, self.grille[x1][y1]
|
||||||
self.joueur = not self.joueur
|
self.joueur = not self.joueur
|
||||||
self.vEchecMat()
|
self.vEchecMat()
|
||||||
return retour
|
return retour
|
||||||
|
|
Reference in a new issue