Correction de Puissance 4

Quelques propositions d'élèves, et à la fin un corrigé du professeur.

Propositions d'élèves

À la suite de chaque proposition de code, un commentaire de correction du professeur. Le cartouche demandé en introduction a été supprimé ici.

Proposition 1

def puissance4(table_puissance4: list) -> int:
    """Cette fonction prend en paramètre un tableau d'entiers à deux dimensions contenant 42 cases
    (6 lignes, 7 colonnes). Une case de ce tableau contient soit 0 (case vide) soit 1 (pion jaune), soit 2 (pion rouge). 
    Et doit renvoyer 1 ou 2 s'il y a un alignement de 4 pions et 0 si personne n'a gagné.
    >>> 0010000
        0022000
        0121000
        0221000
        2212100
        1211210
    2
    """
    for x in range(6):
        for n in range(4):
            ## Vérif horizontale ##
            if table_puissance4[x][n] == table_puissance4[x][n+1] == table_puissance4[x][n+2] == table_puissance4[x][n+3]:
                if table_puissance4[x][n] == 0:
                    pass
                else:
                    return table_puissance4[x][n]
            ## Vérif verticale ##
            elif table_puissance4[n][x] == table_puissance4[n+1][x] == table_puissance4[n+2][x] == table_puissance4[n+3][x]:
                if table_puissance4[x][n] == 0:
                    pass
                else:
                    return table_puissance4[x][n]
                ## Vérif diagonale droite gauche ##
                elif table_puissance4[x][n] == table_puissance4[x+1][n+1] == table_puissance4[x+2][n+2] == table_puissance4[x+3][n+3]:
                    if table_puissance4[x][n] == 0:
                        pass
                    else:
                        return table_puissance4[x][n]
                ## Vérif diagonale gauche droite ##
                elif table_puissance4[x][6-n] == table_puissance4[x+1][5-n] == table_puissance4[x+2][4-n] == table_puissance4[x+3][3-n]:
                    if table_puissance4[x][n] == 0:
                        pass
                    else:
                        return table_puissance4[x][n]
                else:
                return 0
# tests 
import doctest
doctest.testmod()

# Entrée
table_puissance4 = [input() for _ in range(6)]

# Sortie
print(puissance4(table_puissance4))

Proposition 2

def Puissance_4(grille:list) -> int:
    """ Renvoie le gagnant 1 pour le joueur 1 ou 2 pour le joueur 2 si il arrive à aligné 4 pions identitique,sinon 0 en cas d'égalité
    >>> Puissance_4([[0, 0, 1, 0, 0, 0, 0], [0, 0, 2, 2, 0, 0, 0], [0, 1, 2, 1, 0, 0, 0], [0, 2, 2, 1, 0, 0, 0], [2, 2, 1, 2, 1, 0, 0], [1, 2, 1, 1, 2, 1, 0]])
    2
    """
    # Toutes les directions possibles 
    directions = [(1, 0), (0, 1), (1, 1), (1, -1),(-1,-1),(-1,1),(-1,0),(0,-1)]

    def est_possible(x:int, y:int) -> bool:
        """ Regarde si le déplacement est possible sur une grille 6*7
        >>> est_possible(3, 7)
        False
        >>> est_possible(2, 4)
        True
        """
        return (0 <= y < 6) and (0 <= x < 7)
    
    def recherche_gagnant(x:int, y:int, direction_y:int, direction_x:int) -> int:
        """ Recherche et affiche un joueur si il a réussi à aligné ses pions sur 4 cases à la suite dans chaque direction sinon il affiche 0
        >>> recherche_gagnant(5, 3, 1, 0)
        0
        """
        joueur = grille[y][x]
        for _ in range(1, 4):
            y += direction_y
            x += direction_x
            if not(est_possible(x, y)) or (grille[y][x] != joueur):
                    return 0
        return joueur

    for y in range(6):
        for x in range(7):
            if grille[y][x] != 0:
                for direction_y, direction_x in directions:
                    joueur = recherche_gagnant(x, y, direction_y, direction_x)
                    if joueur != 0:
                        return joueur
    return 0

# tests
import doctest
doctest.testmod()

# Entrée
grille = []
for x in range(6):
    grille.append(list(map(int,input())))

# Sortie
print(Puissance_4(grille))

Proposition 3

nb_lignes = 6
nb_colonnes = 7

plateau = [[0 for _ in range(nb_colonnes)] for _ in range(nb_lignes)]

for ligne in range(nb_lignes):
    entrée_str = list(input())
    entrée = list(map(int, entrée_str))
    for colonne in range(nb_colonnes):
        plateau[ligne][colonne] = entrée[colonne]

directions = [(-1,1),(0,1),(1,1),(1,0)]

def est_dans_le_plateau(ligne, colonne):
    """
    Retourne un booléen si les coordonnées (`ligne`,`colonne`) est
    dans le plateau
    """
    if (ligne < 0) or (ligne >= nb_lignes) or (colonne < 0) or (colonne >= nb_colonnes):
        return False
    return True

gagnant = 0

for ligne in range(nb_lignes):
    for colonne in range(nb_colonnes):
        if gagnant != 0:
            break
        joueur = plateau[ligne][colonne]
        if joueur != 0:
            for direction in directions:
                ligne_temporaire = ligne
                colonne_temporaire = colonne
                alignés = 1
                for _ in range(3):
                    ligne_temporaire += direction[0]
                    colonne_temporaire += direction[1]
                    if est_dans_le_plateau(ligne_temporaire, colonne_temporaire):
                        if(plateau[ligne_temporaire][colonne_temporaire] == joueur):
                            alignés += 1
                if alignés == 4:
                    gagnant = joueur
print(gagnant)

Proposition 4

def puissance_4(nb_lignes: int, nb_colonnes: int , grille: list) -> int:
    """Renvoie le vainqueur ou non du puissance 4.
    >>> puissance_4(6, 7, [[0, 0, 1, 0, 0, 0, 0], [0, 0, 2, 2, 0, 0, 0], [0, 1, 2, 1, 0, 0, 0], [0, 2, 2, 1, 0, 0, 0], [2, 2, 1, 2, 1, 0, 0], [1, 2, 1, 1, 2, 1, 0]])
    2
    """
    sens = [(1, 0), (0, 1), (1, 1), (1, -1)]

    def dans_grille(lig, col):
        return (0 <= lig < nb_lignes) and (0 <= col < nb_colonnes)
    
    def vérifie(lig, col, diff_lig, diff_col):
        pions = grille[lig][col]
        for _ in range(1, 4):
            lig += diff_lig
            col += diff_col
            if not(dans_grille(lig, col)) or (grille[lig][col] != pions):
                    return 0
        return pions

    for lig in range(nb_lignes):
        for col in range(nb_colonnes):
            if grille[lig][col] != 0:
                for diff_lig, diff_col in sens:
                    pions = vérifie(lig, col, diff_lig, diff_col)
                    if pions != 0:
                        return pions
    return ""

# Test
import doctest
doctest.testmod()

# Entrée
nb_colonnes = 7
nb_lignes = 6
grille = [list(map(int, input())) for _ in range(6)]

# Sortie 
print(puissance_4(nb_lignes, nb_colonnes, grille))

Proposition 5

def puissance_4(matrice_jeu):
    """ trouve le gagnon 1 ou 2 si égaliter affiche 0"""
    cologne = 0
    gagnent_est = 0
    ligne = 0
    
    
    def lit_horizontalement(cologne: int, gagnent_est: int):
        """ sa lit horizantalement le jeu"""
        vérifie_gagnent = 0 # si vérifie_gagnant est égale a 3, on a un gagnent
        for z in range (5): #car il y a 6 cologne mais on va prendre un facteur +1 sur la matrice 
            if matrice_jeu[z][cologne] != 0 and matrice_jeu[z][cologne] == matrice_jeu[z + 1][cologne] :
                vérifie_gagnent += 1 
            else:
                vérifie_gagnent = 0
            if vérifie_gagnent == 3:
                gagnent_est = matrice_jeu[z][cologne]
        if gagnent_est == 1 or gagnent_est == 2:
            return gagnent_est
        else:
            if cologne < 5:
                return lit_horizontalement(cologne + 1 , gagnent_est)
            else :
                None
    

    def lit_verticalement(cologne: int, gagnent_est: int):
        vérifie_gagnent = 0 # si vérifie_gagnant est égale a 3, on a un gagnent
        for y in range(6)  : #car il y a 7 ligne mais on va prendre un facteur +1 sur la matrice 
            if matrice_jeu[cologne][y] != 0 and matrice_jeu[cologne][y] == matrice_jeu[cologne][y + 1]: # erreur out of range mais je comprend pas où car si la bouvle fait 4 tour il est quand meme out 
                vérifie_gagnent += 1
            else:
                vérifie_gagnent = 0
            if vérifie_gagnent == 3: 
                gagnent_est = matrice_jeu[cologne][y]
        if gagnent_est == 1 or gagnent_est == 2:
            return gagnent_est
        else:
            if cologne < 5 :
                return lit_verticalement(cologne + 1, gagnent_est)
            else:
                None

    """
    def lit_diagonalement(cologne: int, ligne: int, gagnent_est: int):
        est la je suis bloquer
    """
    lit_horizontalement(cologne, gagnent_est)
    if gagnent_est == 1 or gagnent_est == 2:
        return gagnent_est
    else:
        cologne = 0
        lit_verticalement(cologne, gagnent_est)
        if gagnent_est == 1 or gagnent_est == 2:
            return gagnent_est
        else:
            """
            cologne = 0
            lit_diagonalement(cologne, ligne)
            if gagnent_est == 1 or gagnent_est == 2:
                return gagnent_est
            else :
            """   
            return "0" 


matrice_jeu = [] 
for x in range(6):
    matrice_jeu.append(input())
print(puissance_4(matrice_jeu))
""" il se peut qu'il aurai un probleme de rapiditer et on plus je vois pas commen lire ma diagonal"""

Proposition 6

# 0- Coeur du programme

def est_dans_la_grille(i: int, j: int) -> bool:
    """ Renvoie True si le curseur i,j est dans la grille
    >>> est_dans_la_grille(0, 0)
    True
    >>> est_dans_la_grille(-1, 7)
    False
    """

    #La grille à une taille de 6*7 
    if 0 <= i <= 5 and 0 <= j <= 6: 
        return True
    else:
        return False

def déterminer_gagnant(tableau: list) -> int:
    """ détermine si l'un des joueur a gagné la partie. Renvoie 1 ou 2 selon les pions gagnant et 0 si personne n'a gagné
    >>> déterminer_gagnant(["0000000", "0000000", "0000000", "0000000", "0000000", "0000000"])
    '0'
    >>> déterminer_gagnant(["0010000", "0022000", "0121000", "0221000", "2212100", "1211210"])
    '2'
    """

    # Chaque combinaison correspond à une direction à tester, dans l'ordre on a : 
    # Bas, Droite, Gauche, Haut, Diagonale(Bas/Droite), Diagonale(Haut/Gauche), Diagonale(Bas/Gauche), Diagonale(Haut/Droite)
    combinaison = [(0,1),(1,0),(0,-1),(-1,0),(1,1),(-1,-1),(1,-1),(-1,1)]
    for i in range(6):                                  # Ensuite, pour chaque case de la grille
        for j in range(7):
            if tableau[i][j] != "0":                    # ayant un pion (!= 0)
                for x,y in combinaison:                 # on test pour chaque direction
                    if est_dans_la_grille(i+x*3,j+y*3): # s'il existe une case à 3 pîons de i,j , c'est à dire qui se trouve dans la grille
                                                        # et si cette ligne est constituée uniquement du même pion (1 ou 2)
                        if tableau[i][j] == tableau[i+x][j+y] == tableau[i+x*2][j+y*2] == tableau[i+x*3][j+y*3]:
                            return tableau[i][j]        # Si oui, on renvoie le numéro du gagnant
    return "0"                                          # Si, à la fin, on a trouvé aucunes combinaisons créant une ligne de 4 pions identiques, on renvoie 0

# 1- Tests

import doctest
doctest.testmod()

# 2- Lecture de l'entrée

grille = [input() for _ in range(6)]

# 3- Appel de la fonction / Sortie

print(déterminer_gagnant(grille))

Corrigé du professeur

"""
auteur : Franck CHAMBON
https://prologin.org/train/2003/semifinal/puissance_4
"""

def gagnant_puissance_4(grille: list[str]) -> str:
    """Renvoie le gagnant au jeu de Puissance 4.
    * '0' désigne une case vide, et aussi un match nul.
    
    >>> l_1 = "0010000"
    >>> l_2 = "0022000"
    >>> l_3 = "0121000"
    >>> l_4 = "0221000"
    >>> l_5 = "2212100"
    >>> l_6 = "1211210"
    >>> grille = [l_1, l_2, l_3, l_4, l_5, l_6]
    >>> gagnant_puissance_4(grille)
    '2'

    """
    def est_dans_grille(i: int, j: int) -> bool:
        return (0 <= i < 6) and (0 <= j < 7)
    
    def teste_en(i: int, j: int) -> str:
        """Renvoie "1" ou "2" si un gagnant est trouvé en partant de (i, j),
        sinon renvoie "0".
        """
        candidat = grille[i][j]
        if candidat == "0":
            return "0"
        vecteurs = [
                    (0, 1), # horizontal
                    (1, 0), # vertical
                    (1, 1), # diagonal 1
                    (1, -1) # diagonal 2
                ]
        for di, dj in vecteurs:
            if est_dans_grille(i + 3*di, j + 3*dj):
                if grille[i + di][j + dj] == candidat:
                    if grille[i + 2*di][j + 2*dj] == candidat:
                        if grille[i + 3*di][j + 3*dj] == candidat:
                            return candidat
        return "0"
    
    for i in range(6):
        for j in range(7):
            candidat = teste_en(i, j)
            if candidat != "0":
                return candidat
    return "0"


import doctest
doctest.testmod()

grille = [input() for _ in range(6)]

print(gagnant_puissance_4(grille))

Une version raccourcie de la fonction teste_en est alors :

    def teste_en(i: int, j: int) -> str:
        candidat = grille[i][j]
        if candidat == "0":
            return "0"
        for di, dj in [(0, 1), (1, 0), (1, 1), (1, -1)]:
            if all(grille[i + k*di][j + k*dj] == candidat for k in range(1, 4)):
                return candidat
        return "0"