Représenter un plateau de morpion partiellement rempli par un…
Exercice de TD · niveau 2 · NSI (première), chapitre 5 — Les dictionnaires · Les usages : enregistrement, comptage, index
Énoncé
Représenter un plateau de morpion partiellement rempli par un dictionnaire dont les clés sont des couples, en ne stockant que les cases occupées. Écrire case_libre(plateau, i, j) puis gagnant(plateau).
Corrigé
def case_libre(plateau, i, j):
"""True si la case (i, j) du plateau est libre.
Precondition : 0 <= i < 3 et 0 <= j < 3.
Le plateau ne stocke QUE les cases occupees : une case absente du
dictionnaire est libre.
"""
assert 0 <= i < 3 and 0 <= j < 3, "case hors du plateau"
return (i, j) not in plateau
def gagnant(plateau):
"""Symbole du gagnant, ou None. Huit alignements a tester."""
lignes = [[(i, 0), (i, 1), (i, 2)] for i in range(3)]
colonnes = [[(0, j), (1, j), (2, j)] for j in range(3)]
diagonales = [[(0, 0), (1, 1), (2, 2)], [(0, 2), (1, 1), (2, 0)]]
for alignement in lignes + colonnes + diagonales:
a, b, c = alignement
if a in plateau and plateau[a] == plateau.get(b) == plateau.get(c):
return plateau[a]
return None
Pourquoi la clé est un couple, et pourquoi elle doit l'être. Un couple est non modifiable : il peut donc servir de clé, là où [i, j] lèverait TypeError: unhashable type: 'list'. C'est la contrainte du chapitre 4 devenue un pouvoir — et ici elle apporte quelque chose qu'un tableau de tableaux ne donne pas : la grille est creuse. Neuf cases, c'est peu ; mais la même écriture représente un plateau de go de intersections dont dix sont occupées, sans stocker les autres.
Le rôle de get dans gagnant. Les trois cases d'un alignement peuvent être vides. plateau[b] lèverait KeyError ; plateau.get(b) rend None, qui n'est égal à aucun symbole, et la comparaison échoue proprement. Le a in plateau en tête est indispensable : sans lui, trois cases vides donneraient None == None == None et la fonction déclarerait None gagnant sur un plateau vide.
Vérification.
p = {(0, 0): "X", (1, 1): "O", (0, 1): "X"}
assert case_libre(p, 2, 2) is True
assert case_libre(p, 0, 0) is False
assert gagnant(p) is None
p[(0, 2)] = "X"
assert gagnant(p) == "X"
assert gagnant({}) is None # le plateau vide
assert gagnant({(0, 0): "O", (1, 1): "O", (2, 2): "O"}) == "O" # la diagonale
try:
case_libre(p, 3, 0)
assert False
except AssertionError as e:
assert "hors" in str(e)
Le test gagnant({}) is None est celui qui démasque l'oubli du a in plateau.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.