In [12]:
class TicTacToe(object):
template = '''{}|{}|{}
-+-+-
{}|{}|{}
-+-+-
{}|{}|{}'''
def __init__(self):
"""
Initialise le jeu du morpion.
"""
self.grid = [
[None, None, None],
[None, None, None],
[None, None, None],
]
def play(self, symbol, x, y):
"""
Place le symbol du joueur à l'emplacement x, y de la grille de jeu.
Arguments :
- symbol : caractère à placer, idéalement 'X' ou 'O'
- x : ligne sur laquelle placer le caractère
- y : colonne sur laquelle placer le caractère
Throws :
- AssertionError : si l'emplacement désigné est déjà pris
- IndexError : si l'emplacement est en dehors de la grille
"""
assert self.grid[x][y] is None, "Can't play where the other player played"
self.grid[x][y] = symbol
@property
def inline_grid(self):
inline = []
for row in self.grid:
for cell in row:
inline.append(cell)
return inline
def is_finished(self):
"""
Dis si le jeux est fini : retourne True si toutes les cellules sont remplies, et False dans l'autre cas
"""
return None not in self.inline_grid
def _check_triplet(self, triplet):
if triplet[0] == triplet[1] == triplet[2]:
return triplet[0]
return None
@property
def columns(self):
return list(zip(*self.grid))
@property
def diags(self):
diags = [[], []]
for i in range(3):
diags[0].append(self.grid[i][i])
diags[1].append(self.grid[i][-i])
return diags
def find_winner(self):
"""
Cherche si un des joueurs a gagné. Retourne son symbole si c'est le cas, et retourne None sinon.
"""
for triplet in self.grid + self.columns + self.diags:
winner = self._check_triplet(triplet)
if winner:
return winner
return None
def display(self):
"""
Affiche la grille de jeu
"""
args = [cell or ' ' for cell in self.inline_grid]
print(self.template.format(*args))
def main(self):
"""
Exécute le jeu en entier : à chaque tour :
- affiche le plateau
- affiche le symbole du joueur qui doit jouer
- propose de saisir le numéro de la colonne et de la ligne où mettre le symbole
Affiche les messages d'erreur si il y a besoin.
Quand un joueur gagne, affiche le nom du joueur qui a gagné et quitte.
Quand le plateau est plein, affiche que personne n'a gagné et quitte.
"""
player = 'X'
while not (tictactoe.find_winner() or tictactoe.is_finished()):
self.display()
print('Joueur ' + player)
y = input('Colonne : ')
x = input('Ligne : ')
try:
self.play(player, int(x) - 1, int(y) - 1)
except AssertionError:
print('Cette case est déjà prise')
continue
except (ValueError, IndexError):
print('Vous devez saisir une colonne et une ligne entre 1 et 3')
continue
if player == 'X':
player = 'O'
else:
player = 'X'
winner = self.find_winner()
if winner:
print(winner + ' a gagné')
else:
print('Personne n\'a gagné')
tictactoe = TicTacToe()
tictactoe.main()