C'est moi qui ait écrit les cinq fonctions du module matUtil et je m'"autorise" à l'importer sans le nommer, mes fonctions ont des noms suffisamment particuliers il me semble.
Je comprends très bien la nécessité de présenter l'intégralité du code pour que ceux qui veuent aider puissent tester chez eux mais il se trouve déjà dans ce fill de discussion 10 messages au dessus, je le poste de nouveau ici :
#====================================================
# module matUtil
# Liste de toutes les fonctions vues en cours pour
# tester lignes, colonnes et diagonales d'une matrice
#====================================================
def egalListe(tab):
""" teste si tous les élements d'une liste plate sont égaux
arg : une liste plate (non vide); retour : un booléen
[2, 2, 2,] --> True, [2, 1, 2,] --> False"""
for elmt in tab:
if elmt != tab[0]:
return False
return True
def extraitColonne(mat, n):
""" extrait une colonne d'une matrice
arg : une matrice n x p (non vide), num de colonne(int) < p; retour : une liste"""
colonne = []
for i in range(len(mat)):
colonne.append(mat[i][n])
return colonne
def extraitDiagonales(mat):
""" extrait les deux diagonales d'une matrice carrée
arg : une matrice carrée; retour : une liste de deux listes
[première diagonale, deuxième diagonale]
[[1, 2], [3, 4] --> [[1, 4], [2, 3]]"""
diags = [[], []]
for i in range(len(mat)):
diags[0].append(mat[i][i])
diags[1].append(mat[i][-i-1])
return diags
def egalLigne(mat, n):
""" teste si tous les élements d'une ligne d'une matrice sont égaux
arg : une matrice n x p (non vide), num de ligne(int) < n; retour : un booléen """
return egalListe(mat[n])
def egalColonne(mat, n):
""" teste si tous les élements d'une colone d'une matrice sont égaux
arg : une matrice n x p (non vide), num de colonne(int) < p; retour : un booléen """
return egalListe(extraitColonne(mat, n))
if __name__ == "__main__":
print(extraitDiagonales([[1, 2], [3, 4]]))
1) le module matUtil est posté ici quelques messages plus haut, j'ai décidé d'extraire ces fonctions dans un module pour améliorer la lisibilité du code principal, il a été amélioré sur les conseils de fred1599
2) ce "projet" est un exercice imposé par un enseignant (mon choix étant d'y ajouter une interface graphique) et l'algorithme de détection d'alignement était guidé dans l'exercice. Cependant il ne teste pas du tout toutes les colonnes, lignes et diagonales à chaque coup. Il ne teste que la ligne et la colonne courante et éventuellement les diagonales si on se trouve sur l'une (ou les deux) d'entre elles (fonction aGagne() )
3) un futur développement de ce "projet" sera d'y insérer une "IA" contre laquelle on pourra jouer.
4) Je ne souhaite pas proposer une nouvelle partie avant que la partie courante soit terminée.
OK pour les points 1, 3 et 4. Et le morpion de Google propose de jouer à deux, après tout.
Concernant 2, effectivement, tu n'en fais pas autant que ce que j'ai dit. Il n'empêche que je trouve le code assez lourd pour quelque chose d'aussi simple et que des calculs inutiles sont effectués.
D'abord, et comme te l'as dit fred, il faut limiter autant que possible la dépendance d'une fonction à des variables externes qui ne sont pas des paramètres surtout s'il est crédible que ces variables ne soient pas constantes. Cela empêche de faire des tests unitaires et ça nuit à la lisibilité. Le cas typique est ta fonction aGagne (nom pas terrible + mixedCase mais je considère ça comme un détail) dont le code dépend d'une variable grille qui n'est pas un paramètre alors que grille varie tout le temps. En outre cette fonction devrait être placée dans matUtil car elle fait juste un calcul abstrait qui ne dépend pas de ton interface graphique en Tkinter (principe fondamental de codage d'une UI : essayer de se rapprocher d'un MVC et bien séparer la logique de la vue). Ça pour moi c'est une erreur ennuyeuse. Dans le même genre même si c'est plus discutable, ta variable TAILLE qui est une dépendance cachée dans de nombreuses fonctions. Je la mettrais en paramètre (et en minuscules car par convention les variables en capitales sont réservés aux variables invariables).
Maintenant, concernant le codage de tes fonctions de matUtil, dans un premier temps, elles vont bien, elles marchent, c'est déjà ça. La fonction egalListe est algorithmiquement parfaite mais c'est peu lisible et Python permet d'obtenir le même résultat en une ligne de code (l'opérateur == permet de comparer des listes et il le fera de manière optimale par court-circuit)
Ta fonction
def extraitColonne(mat, n):
""" extrait une colonne d'une matrice
arg : une matrice n x p (non vide), num de colonne(int) < p; retour : une liste"""
colonne = []
for i in range(len(mat)):
colonne.append(mat[i][n])
return colonne
n'est pas incorrecte (toutefois : la docstring est peu lisible et le paramètre ne doit pas s'appeler n mais k) mais l'usage est d'écrire une liste en compréhension.
Par ailleurs, ta fonction extraitDiagonales extrait les deux diagonales ce qui n'est clairement pas optimisé (si la première est gagnante, on aura construit la 2e pour rien).
Mais, au-delà de ces détails, ta méthode de détection d'alignement a un inconvénient qu'on a tendance à retrouver dans du code plus avancé : le fait de (re)stocker ce qui n'a pas à l'être. Pour savoir si telle ligne de mon morpion est remplie, ai-je besoin de placer le contenu de la ligne dans une liste (et donc de recopier) pour ensuite les comparer ? Ai-je besoin de recopier la ligne OXOO pour voir si c'est un alignement ou pas (et encore pire si la première case est vide) ? Certainement pas, je suis dans une matrice et j'ai donc des indices qui me permettent de me diriger dans n'importe quelle direction et de faire la comparaison directement. Pour faire ça pythoniquement, utilise des expressions génératrices ainsi que la fonction standard all .
J'ai donc repris matUtil selon (certains de ) vos conseils : (les fonctions de matUtil et leur utilisation étant imposées par l'enseignant)
#=====================================================
# module matUtil
# Liste de toutes les fonctions vues en cours pour
# tester lignes, colonnes et diagonales d'une matrice
#=====================================================
def egalListe(tab):
""" teste si tous les élements d'une liste plate sont égaux
arg : une liste plate (non vide); retour : un booléen
[2, 2, 2,] --> True, [2, 1, 2,] --> False"""
for elmt in tab:
if elmt != tab[0]:
return False
return True
def extraitColonne(mat, k):
""" extrait une colonne d'une matrice
arg : une matrice n x p (non vide), num de colonne(int) < p; retour : une liste"""
return [mat[i][k] for i in range(len(mat))]
def extraitDiagonales(mat):
""" extrait les deux diagonales d'une matrice carrée
arg : une matrice carrée; retour : une liste de deux listes
[première diagonale, deuxième diagonale]
[[1, 2], [3, 4] --> [[1, 4], [2, 3]]"""
diags = [[], []]
for i in range(len(mat)):
diags[0].append(mat[i][i])
diags[1].append(mat[i][-i-1])
return diags
def egalLigne(mat, k):
""" teste si tous les élements d'une ligne d'une matrice sont égaux
arg : une matrice n x p (non vide), num de ligne(int) < n; retour : un booléen """
return egalListe(mat[k])
def egalColonne(mat, k):
""" teste si tous les élements d'une colone d'une matrice sont égaux
arg : une matrice n x p (non vide), num de colonne(int) < p; retour : un booléen """
return egalListe(extraitColonne(mat, k))
def aGagne(grille, lig, col):
""" teste si tous les élements de la colonne ou de la ligne passant par
la case (lig, col) d'une matrice carrée sont égaux, si nécessaire teste
aussi les diagonales. arg : une matrice carree n x n (non vide),
num de ligne, num de colonne (int) < n; retour : un booléen """
return (egalColonne(grille, col) or egalLigne(grille, lig) or
((lig == col) and egalListe(extraitDiagonales(grille)[0])) or
((lig == len(grille) - col - 1)
and egalListe(extraitDiagonales(grille)[1])))
if __name__ == "__main__":
print(extraitDiagonales([[1, 2], [3, 4]]))
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Découverte Python Doc Tkinter Les chaînes de caractères