from copy import deepcopy from functools import reduce class Piece: def __init__(self, couleur): assert couleur == "noir" or couleur== "blanc" self.couleur = couleur def __str__(self): if self.couleur == "noir": return "N" else: return "B" def flip(self): if self.couleur == "noir": self.couleur = "blanc" else: self.couleur = "noir" def est_opposee(self, couleur): return couleur != self.couleur def est_semblable(self, couleur): return couleur == self.couleur class Case: def __init__(self): self.contenu = None def placer(self,piece): self.contenu = piece def flip(self): assert contenu != None self.contenu.flip() def est_occupee(self): return self.contenu != None def est_vide(self): return self.contenu is None def get_contenu(self): return self.contenu def __str__(self): if self.contenu is None: return " " else: return str(self.contenu) def rang_valide(rang): return 0 <= rang <= 7 DIRECTIONS = [(1,0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)] class Plateau: def __init__(self, source = None): if source is None: self.plateau = [] for _ in range(8): ligne = [] for _ in range(8): ligne.append(Case()) self.plateau.append(ligne) self.plateau[3][3].placer(Piece("noir")) self.plateau[4][4].placer(Piece("noir")) self.plateau[3][4].placer(Piece("blanc")) self.plateau[4][3].placer(Piece("blanc")) else: self.plateau = deepcopy(source.plateau) def get_case(self, ligne, colonne): return self.plateau[ligne][colonne] def get_piece(self, ligne, colonne): return self.get_case(ligne,colonne).get_contenu() def __str__(self): retour = " 0 1 2 3 4 5 6 7\n" retour += " " + "-" * 17 + "\n" num_ligne = 0 for ligne in self.plateau: repr_ligne = reduce(lambda acc,case: acc + str(case) + "|",ligne,"|") retour += str(num_ligne) + repr_ligne + "\n" retour += " " + "-" * 17 + "\n" num_ligne += 1 return retour class Othello: def __init__(self, source = None): if source is None: self.plateau = Plateau() self.joueur_courant = "noir" else: self.plateau = Plateau(source.plateau) self.joueur_courant = source.joueur_courant def changer_joueur(self): if self.joueur_courant == "noir": self.joueur_courant = "blanc" else: self.joueur_courant = "noir" def case_valide(self,x, y): if self.plateau.get_case(x,y).est_occupee(): return False for dir in DIRECTIONS: if self.case_valide_direction(x, y, dir): return True return False def case_valide_direction(self, ligne, colonne, direction): ligne_courante = ligne + direction[0] colonne_courante = colonne + direction[1] valide = 0 <= ligne_courante <= 7 and \ 0 <= colonne_courante <= 7 and \ self.plateau.get_case(ligne_courante, colonne_courante).est_occupee() and\ self.plateau.get_piece(ligne_courante, colonne_courante).est_opposee(self.joueur_courant) if not valide: return False while rang_valide(ligne_courante) and rang_valide(colonne_courante): if self.plateau.get_case(ligne_courante, colonne_courante).est_vide(): return False elif self.plateau.get_piece(ligne_courante, colonne_courante).est_semblable(self.joueur_courant): return True ligne_courante += direction[0] colonne_courante += direction[1] return False def jouer_coup(self, ligne, colonne): self.plateau.get_case(ligne, colonne).placer(Piece(self.joueur_courant)) for dir in DIRECTIONS: if self.case_valide_direction(ligne, colonne, dir): self.retourner(ligne, colonne, dir) self.changer_joueur() def retourner(self, ligne, colonne, direction): termine = False ligne_courante = ligne + direction[0] colonne_courante = colonne + direction[1] while not(termine): self.plateau.get_piece(ligne_courante, colonne_courante).flip() ligne_courante += direction[0] colonne_courante += direction[1] termine = not(rang_valide(ligne_courante)) or\ not(rang_valide(colonne_courante)) or \ self.plateau.get_piece(ligne_courante, colonne_courante).est_semblable(self.joueur_courant) def tenter_coup(self, coup): ligne = coup[0] colonne = coup[1] nouveau_jeu = Othello(self) nouveau_jeu.jouer_coup(ligne, colonne) return nouveau_jeu def liste_coups(self): resultat = [] for ligne in range(8): for colonne in range(8): if self.case_valide(ligne, colonne): resultat.append((ligne, colonne)) return resultat def __str__(self): retour = "À " + self.joueur_courant + " de jouer\n" retour += str(self.plateau) return retour