Connection Menu Contenu

1788
membres
00h57
06
février
2012

Pseudo

Mot de passe

Accueil FORUM
repère : ROMMY Prod > Le tutoriel PYTHON 3.0 > Exercices - chapitre 1 à 5 > Correction : le morpion

Corrections - chapitre 1 à 5

Comme j'ai dit lors de la présentation des exercices, il existe beaucoup de façon pour programmer. Je vais donc corriger avec ma méthode mais si vous avez codé différemment et que vous avez le même résultat, ne modifié pas votre code pour prendre le mien.

Le morpion

Bon pour ce jeu, j'ai décidé d'expliquer en séparant mon code. Je vous donne l'ensemble puis je détaillerai le code en expliquant les fonctions une à une.


Voici donc l'ensemble du code (j'ai volontairement enlevé l'intérieur des fonctions pour que vous voyez plus facilement le fonctionnement):
## morpion.py
## -------------
## Réaliser par ROMMY.P le 11/01/2009
## Pour le tutoriel du site ROMMY Production "http://rommyprod.com"




import string

# place le symbole du joueur sur la case demandée et retourne
# la valeur de tour (inchangée sauf si la case demandée
# est remplie)
def placer(tour, nom_j1, nom_j2):
     ...


# affiche le morpion
def affichage(A1,A2,A3,B1,B2,B3,C1,C2,C3):
     ...


# vérifie si 3 symboles identiques sont alignés
# et modifie "fini" si c'est le cas.
def verification(A1,A2,A3,B1,B2,B3,C1,C2,C3, nom_j1, nom_j2):
     ...



tour_joueur = 0
fini = False
A1, A2, A3 = " ", " ", " "
B1, B2, B3 = " ", " ", " "
C1, C2, C3 = " ", " ", " "
case_remplie = 0
nom_joueur1 = input("entrez le nom du 1er joueur, vous aurez les X: ")
nom_joueur2 = input("entrez le nom du 2eme joueur, vous aurez les O: ")


affichage(A1,A2,A3,B1,B2,B3,C1,C2,C3)
while not fini :
    tour_joueur = placer(tour_joueur, nom_joueur1, nom_joueur2)
    tour_joueur += 1
    affichage(A1,A2,A3,B1,B2,B3,C1,C2,C3)
    verification(A1,A2,A3,B1,B2,B3,C1,C2,C3, nom_joueur1, nom_joueur2)
    if case_remplie == 9 and not fini:
        print ("match nul")
        fini = True

Vous pouvez aussi télécharger le code source

Le programme en lui-même

Voilà le temps d'approfondir est arrivé.


Je vais faire comme l'ordinateur, je vais commencer par le commencement.
Je vais vous montrer toutes les variables utiles et comment ce déroule le programme. Initialisé les variables en début de programmes ou fonctions est une habitude que j'ai prise d'un autre langage. Vous pouvez les déclarer plus tard mais bien sûr avant de les utiliser. Si vous faites ça, faites très attention à la notion de variables globales et locales.
tour_joueur = 0
fini = False
A1, A2, A3 = " ", " ", " "
B1, B2, B3 = " ", " ", " "
C1, C2, C3 = " ", " ", " "
case_remplie = 0
nom_joueur1 = input("entrez le nom du 1er joueur, vous aurez les X: ")
nom_joueur2 = input("entrez le nom du 2eme joueur, vous aurez les O: ")


affichage(A1,A2,A3,B1,B2,B3,C1,C2,C3)
while not fini :
    tour_joueur = placer(tour_joueur, nom_joueur1, nom_joueur2)
    tour_joueur += 1
    affichage(A1,A2,A3,B1,B2,B3,C1,C2,C3)
    verification(A1,A2,A3,B1,B2,B3,C1,C2,C3, nom_joueur1, nom_joueur2)
    if case_remplie == 9 and not fini:
        print ("match nul")
        fini = True
Ensuite on affiche une première fois le morpion où toutes les cases sont vides.
C'est à partir de ce moment que le programme commence vraiment car on entre dans la boucle.

Que fait cette boucle ?
Et bien en fait, elle nous dit que tant que nous n'avons pas fini, elle continuera le programme. Donc tant que l'on n'aura pas mis "fini" à True, le jeu continuera.

Le programme consiste à placer le symbole grâce à la fonction "placer", je vous expliquerai en détail pourquoi j'ai mis "tour_joueur = placer..." quand je vous décrirai cette fonction. Ne faites donc pas attention, cette fonction sert à placer un symbole. Cette fonction fera aussi augmenter la valeur de "case_remplie"
Ensuite on ajoute 1 à tour_joueur pour dire que c'est au suivant. Pour savoir quel est le joueur, on regarde si cette valeur est paire ou non (ça aussi je l'expliquerai dans la fonction "placer").
Ensuite on affiche le morpion avec le symbole ajouté.
Puis on vérifie si 3 symboles sont alignés avec la procédure "vérification". Si c'est le cas, la variable fini sera changée en True.
Et on termine en testant si toutes les cases sont remplies, et que l'on à pas fini (réussi à aligner). Pour dire que c'est un match nul et terminer le jeu car on ne peut plus rien placer.

La fonction placer

Maintenant nous allons aller dans les entrailles de la fonction placer, je vous expliquerai le pourquoi de "tour_joueur = ..." (en fait, j'aurai pu faire autrement mais je voulais absolument vous montrer une fonction.
# place le symbole du joueur sur la case demandée et retourne
# la valeur de tour (inchangée sauf si la case demandée
# est remplie)
def placer(tour, nom_j1, nom_j2):
    global A1, A2, A3, B1, B2, B3
    global C1, C2, C3, case_remplie

    # on regarde c'est le tour de quel joueur.
    if tour%2 == 0:
        symbole = "X"
        nom = nom_j1
    else :
        symbole = "O"
        nom = nom_j2

    texte = nom + ", où voulez vous placer (ex: A1) : "
    case = input(texte)
    case = case.upper()

    # on place le symbole à la case demandée
    if case == "A1" and A1 == " ":
        A1 = symbole
        case_remplie += 1
    elif case == "A2" and A2 == " ":
        A2 = symbole
        case_remplie += 1
    elif case == "A3" and A3 == " ":
        A3 = symbole
        case_remplie += 1
    elif case == "B1 and B1 == " ":
        B1 = symbole
        case_remplie += 1
    elif case == "B2" and B2 == " ":
        B2 = symbole
        case_remplie += 1
    elif case == "B3" and B3 == " ":
        B3 = symbole
        case_remplie += 1
    elif case == "C1" and C1 == " ":
        C1 = symbole
        case_remplie += 1
    elif case == "C2" and C2 == " ":
        C2 = symbole
        case_remplie += 1
    elif case == "C3" and C3 == " ":
        C3 = symbole
        case_remplie += 1
    else :
        print ("la case est déjà remplie, ou vous n'avez pas tapez une case valide.")
        tour -= 1
    return tour
Tout d'abord, cette fonction à trois paramètres, qui sont : le nombre de tours et les noms des deux joueurs. J'ai fait exprès de mettre des noms différents pour que vous ne croyiez pas que ce soit les mêmes variables. Je vous dis, ne mettez pas les mêmes noms car c'est ce que j'ai malheureusement l'habitude de faire et ça me crée bien des problèmes de confusion. Je vous rappelle que les paramètres sont des copies, ici "tour" est une copie de "tour_joueur", etc...

Les variables A1, ..., C3 et case_remplie peuvent être vu par la fonction et celle-ci pourra les modifier car on a transformé ces variables en variables globales grâce à "global".

Ensuite on regarde à qui est le tour pour savoir quel symbole on va mettre. Vous avez vu au début que j'ajoutais 1 à chaque tour. On ne sait donc pas à qui est le tour. Pour ça, je vais tester si le tour est pair ou non. Si c'est pair, c'est le joueur 1 sinon le 2.
Pour tester la parité, on regarde si le reste de la division par 2 vaut 0.
Donc 0, 2, 4 ... sont des chiffres pairs et 1, 3, 5 ... impair (ex : 4/2 donne 2 puis 2/2 donne 0, il n'y a donc pas de reste. Par contre 5/2 a un reste de 1 donc 5 est impair.)
Maintenant que l'on sait à qui est le tour, on peut lui attribuer son symbole.
Je vous avais donné lors de l'énoncé une autre méthode plus simple mais je voulais que vous ayez vu au moins une fois comment on se sert de la parité).

Ensuite on demande au joueur où il veut placer son symbole. On le transforme en majuscule pour faire moins de tests. (je vous l'avais expliqué lors de l'énoncé.)

Puis on teste si la case demandée existe (par exemple A4 n'existe pas), et si la case est vide. Si ce n'est pas le cas, on dit que la case est remplie et on redonne le tour au joueur. J'ai donc enlevé un point au tour car il sera augmenter à la sortie de la fonction, ainsi tour_joueur n'aura pas changé et on sera toujours au même joueurs.

Et on finit par renvoyé "tour" qui aura été modifie ou non. On a vu que c'est tour_joueur qui récupère cette valeur.

L'affichage

Maintenant on va attaquer la procédure "affichage". Bien sûr vous pouvez changer l'affichage si celui-ci ne vous plait pas.
# affiche le morpion
def affichage(A1,A2,A3,B1,B2,B3,C1,C2,C3):
    print ("\n  A   B   C")
    print ("#############")
    print ("#", A1, "|", B1, "|", C1, "# 1")
    print ("#---+---+---#")
    print ("#", A2, "|", B2, "|", C2, "# 2")
    print ("#---+---+---#")
    print ("#", A3, "|", B3, "|", C3, "# 3")
    print ("#############\n")
On a besoin que des variables représentant les cases, c'est pour cela qu'il n'y a pas d'autres paramètres.

Chaque "print" représente une ligne, donc on commence par afficher comment nommée les colonnes.
Le caractère \n veut dire "aller à la ligne". Je vous rappelle qu'à chaque print, il y a une nouvelle ligne (sauf s'il y a une virgule en fin du print précedent). Donc on va à la ligne grâce au "print" puis on va de nouveau à la ligne avec le "\n" ce qui fait que l'on a maintenant une ligne vide avant d'afficher "  A   B   C  ", ce qui permet d'éclaircir l'affichage.
Ensuite on affiche le contour du haut. Puis on affiche les cases correspondant à la ligne 1. Puis une ligne séparatrice, la ligne 2, une ligne séparatrice, la ligne trois et pour finir le contour du bas.
Vous pouvez voir que là aussi j'ai mis "\n" car je veux aussi qu'il y ait une ligne d'espace en dessous du morpion.

La procédure "vérification"

Et pour finir, je vais vous expliquer comment déterminer le vainqueur.
# vérifie si 3 symboles identiques sont alignés
# et modifie "fini" si c'est le cas.
def verification(A1,A2,A3,B1,B2,B3,C1,C2,C3, nom_j1, nom_j2):
    global fini
    if ((A1 == A2 and A1 == A3) or (A1 == B1 and A1 == C1) or (A1 == B2 and A1 == C3)) and A1 != " ":
        if A1 == "X":
            print ("Bravo", nom_j1, "vous avez gagné")
        else :
            print ("Bravo", nom_j2, "vous avez gagné")
        fini = True
    elif ((B1 == B2 and B2 == B3) or (A2 == B2 and B2 == C2) or (A3 == B2 and B2 == C1)) and B2 != " ":
        if B2 == "X":
            print ("Bravo", nom_j1, "vous avez gagné")
        else :
            print ("Bravo", nom_j2, "vous avez gagné")
        fini = True
    elif ((C1 == C3 and C2 == C3) or (A3 == C3 and B3 == C3)) and C3 != " ":
        if C3 == "X":
            print ("Bravo", nom_j1, "vous avez gagné")
        else :
            print ("Bravo", nom_j2, "vous avez gagné")
        fini = True
On aura besoin de modifier "fini" au cas où 3 symboles seraient alignés, donc on utilise "global".

Puis on commence les testent pour voir si les 3 symboles sont identiques (on teste si la valeur des trois cases est identique).
Le premier "if" teste : Vous pouvez voir que chaque test est compris entre paranthèse car c'est soit la 1ère ligne, soit la 1ère colonne, soit la diagonale. Par contre il y a un test qui est en dehors de la parenthèse regroupant ces trois tests car c'est l'une des trois conditions plus la quatrième.
Donc si l'une des trois conditions est vraie et que A1 est non vide (and A1 != " "), on peut dire au joueur qu'il a gagné.
J'ai pris A1 pour tester si la case était vide car comme vous pouvez le remarquer, c'est le point commun entre les trois tests (cette case est présente partout).

Le premier "elif" teste : Et on teste si B2 n'est pas vide car c'est le point commun.

Le deuxième "elif" teste : Et on teste si C3 n'est pas vide car c'est le point commun.

J'ai volontairement oublié de vous expliqué comment savoir qui est le gagnant car je ne voulais pas vous interrompre dans votre lancé.
Etant à l'intérieur du if, cela veut dire que les conditions sont vraies. Donc les cases sont identiques au point commun de tous les tests. On va donc tester cette case en particulier.
On teste la valeur de la case. Si c'est "X", ça correspond au joueur 1 sinon au 2. Faites attention, il faut que les paramètres soit les mêmes que pour la fonction placer. Je m'explique, si vous avez donné au joueur 1 les "X" (c'est le cas ici) et que vous mettez son nom pour le paramètre nom_j2, il y aura une inversion et le gagnant ne sera pas le bon.

Si vous avez fait "tour_joueur = placer(tour_joueur,nom_joueur1,nom_joueur2)" et qu'après vous mettez "verification(A1,A2,A3,B1,B2,B3,C1,C2,C3,nom_joueur2,nom_joueur1)" à la place de "verification(A1,A2,A3,B1,B2,B3,C1,C2,C3,nom_joueur1,nom_joueur2)", le gagnant sera en fait le perdant. A moins que vous ayez aussi inversé à l'intérieur de la fonction.

chapitre precedent sommaire L'énoncé chapitre precedent
repère : ROMMY Prod > Le tutoriel PYTHON 3.0 > Exercices - chapitre 1 à 5 > Correction : le morpion
Qui suis-je ? Contact Charte du site
Plan du site Accessibilité du site

Copyright © ROMMY Production
Le cours, les jeux et les logiciels sont la propriété de son auteur.
Toute reproduction totale ou partielle du cours est interdite sans l'accord de l'auteur.
La modification des jeux et logiciels est interdite sans l'accord de l'auteur.