Morpion en python [Résolu]

Signaler
Messages postés
31
Date d'inscription
lundi 8 mai 2017
Statut
Membre
Dernière intervention
26 août 2020
-
Messages postés
31
Date d'inscription
lundi 8 mai 2017
Statut
Membre
Dernière intervention
26 août 2020
-
Bonjour je suis sur un projet de Morpion en python. Or j'ai un problème lorsque le programme doit vérifier s'il y a un alignement de croix ou de rond. Je détail, avant de placer l'image croix ou rond dans la grille tkinter, je place un 1 ou 2 dans une liste qui représente la grille sous forme de liste, ce qui facilite la manipulation de placement et la vérification des alignements. Seulement à certains moment lorsque la grille fait plus de 3x3 carreaux, la fonction bigue_verif ligne 290 détecte un alignement alors qu'il n'y en a absolument pas... J'ai essayé tant bien que mal détecter le problème avec de print, je ne le trouve pas.

from tkinter import*
from time import sleep
from random import randint

#Création du tableau qui servira de support de jeu
from tkinter import*


class Morpion_pvb():
    def __init__(self, x, y):
        self.tableau = []
        self.used = []
        self.x = x
        self.y = y
        self.count = 0
        self.pos_tab_x = 999
        self.pos_tab_y = 999
        
    def parametrage(self, x, y):
        for a in range(y):
            self.tableau.append([])
            for b in range(x):
                self.tableau[a].append(0)
        global pos_tab_x
        global pos_tab_y
        pos_tab_x,pos_tab_y = 999, 999
        self.count = 0

    def clic(self, event):
        croix = croix_115x115
        cercle = cercle_115x115
        if self.x < 5 and self.y < 5:
            croix = croix_150x150
            cercle = cercle_150x150
        self.pos_tab_x, self.pos_tab_y = event.y // (dimension -5), event.x // (dimension -5) #Position de la croix dans la liste tableau
        
        if self.count < self.x * self.y and  (self.pos_tab_x, self.pos_tab_y) not in self.used:
            pos_x,pos_y = dimension / 2 + (event.y // (dimension -5)) * dimension, dimension / 2 + (event.x // (dimension -5)) * dimension   #Position sur la grille    
            grille.create_image((pos_y,pos_x), image = croix)
            print(self.pos_tab_x, self.pos_tab_y)
            Player._placer_(self.pos_tab_x, self.pos_tab_y)
            if Player.bigue_verif(self.pos_tab_x, self.pos_tab_y) == Player.numero:
                result.configure(text = "Vous avez gagné, bravo!", fg = "green")
                self.count = 100

            if self.count < self.x * self.y:
                ab = randint(0, self.y - 1)
                bc = randint(0, self.x - 1)
                pos_y, pos_x = ab * dimension + dimension / 2, bc * dimension + dimension / 2
                print(pos_x,pos_y)

                while (ab, bc) in self.used:
                    print(pos_x,pos_y)
                    ab = randint(0, self.y - 1)
                    bc = randint(0, self.x - 1)
                    pos_y, pos_x = ab * dimension + dimension / 2, bc * dimension + dimension / 2
                print(ab,bc)
                print(self.tableau[0])
                print(self.tableau[1])
                print(self.tableau[2])
                print(self.tableau[3])
                print(self.tableau[4])
                print(self.used)
                bot._placer_(ab, bc)
                grille.create_image((pos_x,pos_y), image = cercle)
                if bot.bigue_verif(ab, bc) == bot.numero:
                    result.configure(text = "Vous avez perdu contre un robot qui joue \n au hasard...", fg = "red")
                    self.count = 100
            
# Fonction de la partie
    def _partie_(self, x, y):
        global Player
        global bot
        self.parametrage(x, y)
        Player = joueur(1)
        bot = joueur(2)                                                  
        #Boucle de la partie
        grille.bind("<Button>", self.clic)
        
    
############################################################
##########     CREATION DU TABLEAU DU MORPION     ##########
############################################################
    def start_pvb(self):
        global dimension
        
        #Partie si le tableau fais moins de 5 case de sur la longueur ou la largeur
        if self.x < 5 and self.y < 5:
            dimension = 155
            larg = dimension*self.x
            longu = dimension*self.y
            X0 = Y0 = dimension / 2
            global grille
            global result
            grille = Canvas(p_v_b, background="#292727",
                            width=larg, height=longu)
            result = Label (p_v_b, bg = "#292727", text = "", 
                            font = ("Press start 2p",15), fg = "red")
            for i in range(self.x):
                new = X0 + i*dimension
                centre = (new, Y0)
                for c in range(self.y):
                    centre = (new, Y0 + c*dimension)
                    grille.create_image(centre, image=_white_150x150)
                    
                   
            #Fin de la configuration de la grille
            grille.pack(pady=50)
            result.pack()

            #debut de la partie
            self._partie_(self.x, self.y)

        #Création du tableau si le tableau fais plus de 4 case de sur la longueur ou la largeur
        else:
            dimension = 120
            larg = dimension*self.x
            longu = dimension*self.y

            X0 = Y0 = dimension / 2
            grille = Canvas(p_v_b, background="#292727",
                               width=larg, height=longu)
            result = Label (p_v_b, bg = "#292727", text = "", 
                               font = ("Press start 2p",15), fg = "red")

            for i in range(self.x):
                new = X0 + i*dimension
                centre = (new, Y0)
                for c in range(self.y):
                    centre = (new, Y0 + c*dimension)
                    grille.create_image(centre, image=_white_115x115)
            #Fin de la configuration de la grille

            grille.pack(pady=50)
            result.pack()
            #debut de la partie
            self._partie_(self.x, self.y)
############################################################
#######################     FIN     ########################
############################################################

class joueur ():
    def __init__(self,numero):
        self.numero = numero
        
    def _placer_(self,x,y):
        Morpion_1.tableau[x][y] = self.numero
        Morpion_1.count += 1
        Morpion_1.used.append((x,y))
    def verif_ligne_1 (self,x,y):
        try:
            for z in range(1,3):
                if Morpion_1.tableau[x+1][y] == self.numero:
                    if Morpion_1.tableau[x+2][y] == self.numero:
                        return self.numero
                    else:
                        return 0
                else:
                    return 0
        except:
            return 0
    def verif_ligne_2 (self,x,y):
        try:
            
            if Morpion_1.tableau[x-1][y] == self.numero:
                if Morpion_1.tableau[x-2][y] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0
    def verif_ligne_3 (self,x,y):
        try:
            if Morpion_1.tableau[x-1][y] == self.numero:
                if Morpion_1.tableau[x+1][y] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0
    def verif_colonne_1(self,x,y):
        try:
            
            if Morpion_1.tableau[x][y-1] == self.numero:
                if Morpion_1.tableau[x][y-2] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0 
    def verif_colonne_2 (self,x,y):
        try:
        
            if Morpion_1.tableau[x][y+1] == self.numero:
                if Morpion_1.tableau[x][y+2] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0
    def verif_colonne_3 (self,x,y):
        try:
            if Morpion_1.tableau[x][y-1] == self.numero:
                if Morpion_1.tableau[x][y+1] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0
    def verif_diagonale_1 (self,x,y):
        try:
        
            if Morpion_1.tableau[x-1][y-1] == self.numero:
                if Morpion_1.tableau[x-2][y-2] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0
    def verif_diagonale_2 (self,x,y):
        try:

            if Morpion_1.tableau[x+1][y+1] == self.numero:
                if Morpion_1.tableau[x+2][y+2] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0   
    def verif_diagonale_3 (self,x,y):
        try:

            if Morpion_1.tableau[x+1][y-1] == self.numero:
                if Morpion_1.tableau[x+2][y-2] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0  
    def verif_diagonale_4 (self,x,y):
        try:

            if Morpion_1.tableau[x-1][y+1] == self.numero:
                if Morpion_1.tableau[x-2][y+2] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0 
    def verif_diagonale_5 (self,x,y):
        try:
            if Morpion_1.tableau[x-1][y-1] == self.numero:
                if Morpion_1.tableau[x+1][y+1] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0
    def verif_diagonale_6 (self,x,y):
        try:
            if Morpion_1.tableau[x+1][y-1] == self.numero:
                if Morpion_1.tableau[x-1][y+1] == self.numero:
                    return self.numero
                else:
                    return 0
            else:
                return 0
        except:
            return 0
    def bigue_verif(self,x,y):
        liste_verif = [
            self.verif_ligne_1(x,y), self.verif_ligne_2(x,y), self.verif_ligne_3(x,y), 
            self.verif_colonne_1(x,y), self.verif_colonne_2(x,y), self.verif_colonne_3(x,y), 
            self.verif_diagonale_1(x,y), self.verif_diagonale_2(x,y), self.verif_diagonale_3(x,y), 
            self.verif_diagonale_4(x,y), self.verif_diagonale_5(x,y), self.verif_diagonale_6(x,y)
            ]
        
        if self.numero in liste_verif:
            print(liste_verif)
            return self.numero
        else: 
            return 0




def start_game():
    x = champ_longueur.get()
    y = champ_largeur.get()
    global Morpion_1
    try:
        x = int(x)
        y = int(y)
        if (x <= 2 and y <= 2) or (x > 6 and y > 6) or x <= 2 or y <= 2 or x > 6 or y > 6:
            explain4.configure(fg="red")
            return 0
    except:
        explain1.configure(
                text="Vous devez impérativement remplir \n le champ avec des valeurs entre ")
        return 0
    frame1.pack_forget()
    Morpion_1 = Morpion_pvb(x, y)
    Morpion_1.start_pvb()


p_v_b = Tk()  # Création de la fenêtre

croix_150x150 = PhotoImage(file="./image/croix_150x150.png")
cercle_150x150 = PhotoImage(file="./image/cercle_150x150.png")
_white_150x150 = PhotoImage(file="./image/white_150x150.png")
croix_115x115 = PhotoImage(file="./image/croix_115x115.png")
cercle_115x115 = PhotoImage(file="./image/cercle_115x115.png")
_white_115x115 = PhotoImage(file="./image/white_115x115.png")

p_v_b.title('Player VS Bot')
p_v_b.geometry("1000x900")
p_v_b.minsize(720, 480)
p_v_b.configure(background="#292727")

#Avant partie
frame1 = Frame(p_v_b, bg="#292727")
titre = Label(frame1, text="Player VS Bot", font=(
    "Press start 2p", 23), fg="#1BD6F1", bg='#292727')
explain1 = Label(frame1, bg='#292727', text="Veuillez cliquer sur start après avoir rempli \n le champ par de valeur entre ",
                 fg="#1BD6F1", font=("Arial", 30))
explain4 = Label(frame1, bg='#292727', text="3 et 6 compris",
                 fg="#1BD6F1", font=("Arial", 30))
champ_longueur = Entry(frame1, bg="#A6E7BC", width=10)
champ_largeur = Entry(frame1, bg="#A6E7BC", width=10)
explain2 = Label(frame1, bg='#292727',
                 text="Longueur du Morpion:", fg="white", font=("Arial", 20))
explain3 = Label(frame1, bg='#292727', text="Largeur du Morpion:",
                 fg="white", font=("Arial", 20))
pvb_start = Button(frame1, bg="#FFFFED", text="Start", font=(
    "Press start 2p", 20), fg="black", height=3, width=25, command=start_game)
charge_fake = Label(frame1, bg="#292727", text="",
                    fg="white", font=("Press start 2p", 30))
titre.pack(pady=30)
explain1.pack()
explain4.pack()
explain2.pack(pady=20)
champ_largeur.pack(pady=10)
explain3.pack(pady=20)
champ_longueur.pack()
pvb_start.pack(pady=100)
charge_fake.pack()
frame1.pack()

#Début de partie


p_v_b.mainloop()

6 réponses

Messages postés
12418
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
1 octobre 2020
697
bonjour, peux-tu être plus précis? est-ce le test en ligne 298 qui ne fait pas ce que tu imagines?
Messages postés
31
Date d'inscription
lundi 8 mai 2017
Statut
Membre
Dernière intervention
26 août 2020

Oui c'est ça, enfaite j'i de nombreuse fonction qui vérifie tous les alignements possibles, si par exemple il y a un alignement en ligne, la fonction verif_ligne va retourner le numero associer au joueur ou au bot, s'il n'y aucun alignement, les fonctions de verification retournent toutes 0. Ce que fais la fonction bigue_verif, c'est contenir ce que toutes les fonctions retournent dans une liste et si le numero associé au joueur est dans la liste c'est que le joueur a gagné. Or la fonction bigue_verif qui est appelé, elle ne donne pas le résultat attendu, elle fonctionne parfaitement lorsqu'il y a un alignement mais dis qu'il y a un alignement quand il n'y en a pas. (merci beaucoup pour votre aide dans mon projet elle m'est précieuse)
Messages postés
12418
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
1 octobre 2020
697
quel est l'appel qui ne retourne pas le résultat attendu? tu peux ajouter des print() pour détecter cela.
Messages postés
31
Date d'inscription
lundi 8 mai 2017
Statut
Membre
Dernière intervention
26 août 2020

J'ai bien compris quel appelle fonctionnait mal, c'est quand j'appelle bigue_verif aux lignes 66 et 42. J'ai rajouté des print pour voir ce que contient la liste dans bigue verif lorsque le jeu bug, et je peu donc voir quelle verif a un probleme, or la verif qui a un problème change en fonction de parties, il y a meme des fois ou 2 verfi sont validées alors qu'acune ne devrait l'être ( j'ai peu être oublié de préciser que ces bugs n'arrivent pas lorsque la grille fait par exemple 3x3 cases ). Je ne sais pas si cela réponds à votre question.
Messages postés
12418
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
1 octobre 2020
697
si tu veux corriger le programme que tu as écrit, tu pourrais choisir une des fonctions verif qui posent problème, et y ajouter des print pour comprendre ce qu'elle fait.
Messages postés
31
Date d'inscription
lundi 8 mai 2017
Statut
Membre
Dernière intervention
26 août 2020

Bonsoir cela fait plusieurs jours que je ne trouve pas de réponse malgré mes tentative... J'ai demandé à ma cousine qui s'y connait pas mal en python mais je n'ai pas été débloqué, si vous avez une piste je la veux bien.
Messages postés
397
Date d'inscription
vendredi 25 septembre 2015
Statut
Membre
Dernière intervention
26 août 2020
189
Bonjour,
je n'ai pas regardé le code en détail mais les fonctions de vérifications me semblent étonnantes.
À la ligne 152 il y a une boucle mais la variable z n'est jamais utilisée, quel est l'interet ?
Ensuite vous vérifiez 2 cases aux lignes 153 et 154 mais normalement pour gagner au morpion il faut aligner 3 cases non ?
Et puis si j'ai bien compris vous avez fait une extension du morpion pour jouer sur des grilles plus grandes que 3x3 mais du coup pourquoi il y a uniquement les fonctions verif_ligne_1, verif_ligne_2 et verif_ligne_3 ? Les lignes suivantes ne sont pas vérifiées pour des grilles plus grandes que 3x3 ? Ne serait-ce pas plus simple de faire une boucle qui vérifie chaque ligne une par une ?
Messages postés
12418
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
1 octobre 2020
697
c'est assez mal programmé, mais le programme ne vérifie pas l'ensemble du jeu, il ne vérifie que la ligne, la colonne, et les diagonales (si elles existent) du dernier jeton placé.
l'idée est bonne, la programmation ne l'est pas.
avant de l'étendre à plus de 3*3, il faudrait réécrire cela complètement.
pour la vérification de la ligne, il faudrait écrire une seule fonction
verif_ligne (self,x,y)
, qui vérifie la ligne complète, en tenant compte de sa dimension, bien sûr.
Messages postés
31
Date d'inscription
lundi 8 mai 2017
Statut
Membre
Dernière intervention
26 août 2020

Les fonctions verifs_ligne_1,2,3... ne sont pas pour les ligne 1,2 et trois mais bein pour les allignement sur un quelconque ligne/colonne/diagonale et si on ne vérifie que 2 case c'est car on a comme argument les cordonnées du dernier coup joué donc toute les verif sont en fonction du dernier coup joué.
Messages postés
31
Date d'inscription
lundi 8 mai 2017
Statut
Membre
Dernière intervention
26 août 2020

Bonjour, j'ai finalement résolu le problème qui venait du fait que les indexes de liste peuvent être négatifs et que du coup ca part de la fin pour sélectionner la valeur demandée. Or j'ignorait totalement cela. Pour ce que est de revoir l'écriture de mon code je compte le faire quand j'aurais plus de temps mais je le ferais car on m'a beaucoup dit qu'il n'était vraiment pas beau. Merci pour votre réponse un fois de plus