Adloun

Voici la fonction gagnant rendue par un groupe

Exercice de TD · niveau 3 (difficile) · NSI (première), chapitre 11 — Conduire un projet · Tester pour de vrai

Énoncé

Voici la fonction gagnant rendue par un groupe. Elle a été « testée : ça marche ».


def gagnant(g):
    """Renvoie 'X', 'O' ou None."""
    for i in range(3):
        if g[i][0] == g[i][1] == g[i][2] != ".":
            return g[i][0]
    for j in range(3):
        if g[0][j] == g[1][j] == g[2][j] != ".":
            return g[0][j]
    return None

Corrigé

1. Les diagonales ne sont pas examinées. Sur la grille


diag = [["X", ".", "."],
        [".", "X", "."],
        [".", ".", "X"]]

la fonction renvoie None : elle ne trouve aucune ligne complète, aucune colonne complète, et s'arrête. Le programme continuerait donc la partie alors qu'elle est gagnée — et le joueur suivant pourrait, en théorie, gagner à son tour.

2.


def test_diagonales():
    diag = [["X", ".", "."], [".", "X", "."], [".", ".", "X"]]
    anti = [[".", ".", "O"], [".", "O", "."], ["O", ".", "."]]
    assert gagnant(diag) == "X", "la diagonale n'est pas detectee"
    assert gagnant(anti) == "O", "l'antidiagonale n'est pas detectee"

Le message compte autant que l'assertion : AssertionError sans texte oblige à relire le test pour comprendre ce qui a échoué.

3. Plutôt que d'ajouter deux if de plus — ce qui donnerait quatre morceaux de code presque identiques —, on énumère les huit alignements une fois pour toutes :


def gagnant(g):
    """Renvoie 'X', 'O' ou None si personne n'a encore gagne."""
    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 trio in lignes + colonnes + diagonales:
        a, b, c = [g[i][j] for i, j in trio]
        if a == b == c != ".":
            return a
    return None

Huit trios, un seul test. Le jour où la grille passe en , une seule liste est à changer.

Contrôle : sur les cinq grilles du jeu de tests — ligne, colonne, diagonale, antidiagonale, grille vide — la fonction rend respectivement X, O, X, O, None.

4. Parce qu'une partie d'essai ne se termine presque jamais par une diagonale. Deux joueurs qui découvrent leur propre programme jouent lentement, au milieu, se bloquent, et finissent le plus souvent sur une ligne ou une colonne — ou en match nul. Le cas manquant est précisément celui qu'on ne rencontre pas par hasard.

C'est l'argument central du chapitre : « on a joué toute la séance, ça marche » n'est pas un jeu de tests. Un jeu de tests énumère les cas délibérément, y compris — surtout — ceux qui ne se présentent pas spontanément. Ici, la seule question « de combien de façons peut-on gagner ? » aurait suffi : la réponse est huit, et le code n'en traitait que six.

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.