Forum Linux.débutant Problème avec un jeu de dame

Posté par  . Licence CC By‑SA.
Étiquettes :
-1
26
mai
2014

Bonjour,
Je tiens à m'excuser si j'ai fais une erreur sur la classification de mon poste, ce site est nouveau pour moi.
Je travaille actuellement avec mon groupe, sur un projet de programmation de jeu, un jeu de dame.
Une grande parti du programme finale marche, or il y a un problème avec les pions rouges, leurs déplacements ne sont pas bons. Pour faire simple ils se déplacent en ligne droite
Aucun problème avec les bleus qui se déplacent normalement. Nous nous somme creusé un bon moment la tête.
mais rien a faire on ne comprend pas (on a vérifié les éventuelles erreurs de frappes).
Nous avons besoin donc d'aide et surtout d'être aiguillé.
En l'attente d'une réponse positive.

Je met le code du programme:
Oui c'est assez lourd, si quelqu'un connait un moyen de réduire la taille je voudrais bien être informé.
Je vous remercie d'avance.

from tkinter import *

def damier():
    #La fonction damier dessinne les 100 cases du damier en noir et blanc#

    i = 0
    while i < 10:
        j = 0

        while j < 10:
            if (i%2)==0:
                if (j%2)==0:
                    can1.create_rectangle(j*case, i*case, (j*case)+case, (i*case)+case, fill='black')
                else:
                    can1.create_rectangle(j*case, i*case, (j*case)+case, (i*case)+case,fill='white')
            else:
                if (j%2)==0:
                    can1.create_rectangle(j*case, i*case, (j*case)+case, (i*case)+case, fill='white')
                else:
                    can1.create_rectangle(j*case, i*case, (j*case)+case, (i*case)+case, fill='black')
            j+=1
        i+=1

def place_pions():
    #Cette partie trace les pions à leur position actuelle sur l'echiquier#
    # on marque les scores de chaque joueur à l'écran
    if started:
        txt1.configure(text=j1+' (Rouge): '+str(rouge))
        txt2.configure(text=j2+' (Bleu): '+str(bleu))
        if joueur == 1:
            chaine.configure(text="Les BLEUS jouent...", fg='blue')
        else:
            chaine.configure(text="Les ROUGES jouent...", fg='red')

    # on commence par les pions blancs (rouge)
    print ("placement des pions")
    # à partir du numéro de case du pion contenu dans le tableau pions_b on en déduit où on doit
    # tracer le cercle
    # on prend la partie entière de la division par 10 pour savoir sin on est sur la première, la deuxième ligne, la troisième .....
    i = 0
    while i < len(pions_b):
        #print("i =",i)
        if pions_b[i] != -1:
            #print("pions_b[i]",pions_b[i])
            y = (((int(pions_b[i]/10))*case) + case/2)
            x = ((pions_b[i]%10)*case) + case/2
            #print("x = ",x)
            #print("y = ",y)
            # On a calculé le centre du cercle. On le dessine
            if i in dame_b:
                can1.create_rectangle(x-10, y-10, x+10, y+10, fill='red')
            else:
                can1.create_oval(x-15, y-15, x+15, y+15, fill='red')

        i += 1

    # ensuite les pions noirs/bleu
    i = 0

    while i < len(pions_n):
        if pions_n[i] != -1:
            x = ((pions_n[i]%10)*case) + case/2
            y = (((int(pions_n[i]/10))*case) + case/2)
            # On a calculé le centre du cercle. On le dessine
            if i in dame_n:
                can1.create_rectangle(x-10, y-10, x+10, y+10, fill='blue')
            else:
                can1.create_oval(x-15, y-15, x+15, y+15, fill='blue')
        i += 1

def pions_prenable():
    #on test si le joueur pouvait prendre une pièce pour la règle \"sauter n'est pas jouer\"#
    global sauter_pas_jouer
    sauter_pas_jouer = []
    if joueur == 0:
        i = 0;
        while i < len(pions_b):
            pr = possibilitees(False, pions_b[i])
            if len(pr) != 0:
                sauter_pas_jouer.append(i)
                sauter_pas_jouer.append(pr[0])
                sauter_pas_jouer.append(pr[1])
                return True
            i += 1
    else:
        i = 0;
        while i < len(pions_n):
            pr = possibilitees(False, pions_n[i])
            if len(pr) != 0:
                sauter_pas_jouer.append(i)
                sauter_pas_jouer.append(pr[0])
                sauter_pas_jouer.append(pr[1])
                return True            
            i += 1
    return False

def ColorCase(num):
        y = ((num/10)*case) + case/2
        x = ((num%10)*case) + case/2
        can1.create_oval(x-15, y-15, x+15, y+15, fill='orange')

def deplacement(dest):
    #On effectue le déplacement des pions#
    global pions_n, pions_b, rouge, bleu
    ligne = dest/10
    if dest in pos:
        if selected in pions_b:
            if dest in prenable:
                pions_n[pions_n.index(prenable[prenable.index(dest)+1])] = -1
                pions_b[pions_b.index(selected)] = dest
                rouge += 1
            elif pions_prenable():
                # sauter n'est pas jouer
                ColorCase(pions_b[sauter_pas_jouer[0]])
                ColorCase(pions_n[pions_n.index(sauter_pas_jouer[2])])                
                showinfo("Sauter n'est pas jouer", "Si vous pouvez capturer un pion vous devez le faire")
                pions_n[pions_n.index(sauter_pas_jouer[2])] = -1
                pions_b[sauter_pas_jouer[0]] = sauter_pas_jouer[1]
                dest = sauter_pas_jouer[1]
                ligne = dest/10
                rouge += 1
            else:
                pions_b[pions_b.index(selected)] = dest

            if ligne == 9:
                dame_b.append(pions_b.index(dest))           
        else:
            if dest in prenable:
                pions_b[pions_b.index(prenable[prenable.index(dest)+1])] = -1
                pions_n[pions_n.index(selected)] = dest
                bleu += 1
            elif pions_prenable():
                # sauter n'est pas jouer
                ColorCase(pions_n[sauter_pas_jouer[0]])
                ColorCase(pions_b[pions_b.index(sauter_pas_jouer[2])])
                showinfo("Sauter n'est pas jouer", "Si vous pouvez capturer un pion vous devez le faire")
                pions_b[pions_b.index(sauter_pas_jouer[2])] = -1
                pions_n[sauter_pas_jouer[0]] = sauter_pas_jouer[1]
                dest = sauter_pas_jouer[1]
                ligne = dest/10
                bleu += 1
            else:
                pions_n[pions_n.index(selected)] = dest

            if ligne == 9:
                dame_n.append(pions_n.index(dest)) 

        return True
    else:
        return False

def case_libre(c):
    ligne = c/10
    colonne = c%10
    if ((ligne%2)==0 and (colonne%2)!= 0) or ((ligne%2)!=0 and (colonne%2)== 0):
        return False 
    else:
        if c in pions_b or c in pions_n:
            return False
        else:
            return True

def possibilitees(glob=True, num_case=0):
    #Procédure évaluant les possibilitées de coup en fonction de la case selectionnées#
    print("possibilités")
    if glob:
        global pos, prenable, selected

    pos = []
    prenable = []

    if not glob:
        n_case = num_case
    else:
        n_case = selected

    print("n_case =",n_case)     

    s_ligne = n_case//10
    s_colonne = n_case%10

    # on évalue les positions autorisées
    if n_case in pions_b:
        # il s'agit d'un pion rouge/blanc
        c = (s_ligne+1)*10+(s_colonne)
        if case_libre(c):
            pos.append(c)
        else:
            c2 = (s_ligne+2)*10+(s_colonne-2)
            if case_libre(c2) and c in pions_n:
                pos.append(c2)
                prenable.append(c2)
                prenable.append(c)

        c = (s_ligne+1)*10+(s_colonne+1)
        if case_libre(c):        
            pos.append(c)
        else:
            c2 = (s_ligne+2)*10+(s_colonne+2)
            if case_libre(c2) and c in pions_n:
                pos.append(c2)
                prenable.append(c2)
                prenable.append(c)

        # si il s'agit d'une dame, il y a d'autre possibilitées
        if pions_b.index(n_case) in dame_b:
            # déplacement haut-droit
            print("dame")
            i = 1
            while i < 10:
                l = s_ligne - i
                cl = s_colonne + i
                if l >= 0 and cl < 10:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_b:
                        break
                    else:
                        c2 = (l-1)*10+(cl+1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break
                i+=1
            # déplacement haut-gauche
            i = 1
            while i < 10:
                l = s_ligne - i
                cl = s_colonne - i
                if l >= 0 and cl >= 0:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_b:
                        break
                    else:
                        c2 = (l-1)*10+(cl-1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break

                i+=1
            # déplacement bas-droit
            i = 1
            while i < 10:
                l = s_ligne + i
                cl = s_colonne + i
                if l < 10 and cl < 10:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_b:
                        break
                    else:
                        c2 = (l+1)*10+(cl+1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break
                i+=1
            # déplacement bas-gauche
            i = 1
            while i < 10:
                l = s_ligne + i
                cl = s_colonne - i
                if l < 10 and cl >= 0:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_b:
                        break
                    else:
                        c2 = (l+1)*10+(cl-1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break
                i+=1

    else:
        # il s'agit d'un pion bleu       
        c = (s_ligne-1)*10+(s_colonne-1)
        if case_libre(c):
            pos.append(c)
        else:
            c2 = (s_ligne-2)*10+(s_colonne-2)
            if case_libre(c2) and c in pions_b:
                pos.append(c2)
                prenable.append(c2)
                prenable.append(c)

        c = (s_ligne-1)*10+(s_colonne+1)
        if case_libre(c):        
            pos.append(c)
        else:
            c2 = (s_ligne-2)*10+(s_colonne+2)
            if case_libre(c2) and c in pions_b:
                pos.append(c2)
                prenable.append(c2)
                prenable.append(c)

        # si il s'agit d'une dame, il y a d'autre possibilitées
        if pions_n.index(n_case) in dame_n:
            # déplacement haut-droit
            i = 1
            while i < 10:
                l = s_ligne - i
                cl = s_colonne + i
                if l >= 0 and cl < 10:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_n:
                        break
                    else:
                        c2 = (l-1)*10+(cl+1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break
                i+=1
            # déplacement haut-gauche
            i = 1
            while i < 10:
                l = s_ligne - i
                cl = s_colonne - i
                if l >= 0 and cl >= 0:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_n:
                        break
                    else:
                        c2 = (l-1)*10+(cl-1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break
                i+=1
            # déplacement bas-droit
            i = 1
            while i < 10:
                l = s_ligne + i
                cl = s_colonne + i
                if l < 10 and cl < 10:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_n:
                        break
                    else:
                        c2 = (l+1)*10+(cl+1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break
                i+=1
            # déplacement bas-gauche
            i = 1
            while i < 10:
                l = s_ligne + i
                cl = s_colonne - i
                if l < 10 and cl >= 0:
                    c = l*10+cl
                    if case_libre(c):
                        pos.append(c)
                    elif c in pions_n:
                        break
                    else:
                        c2 = (l+1)*10+(cl-1)
                        if case_libre(c2):
                            pos.append(c2)
                            prenable.append(c2)
                            prenable.append(c)
                        break
                else:
                    break
                i+=1                

    if glob:
        # pour les tests on affiche les positions possibles
        i = 0
        while i < len(pos):
            #y = (((pos[i]/10)*case) + case/2)
            y = (((int(pos[i]/10))*case) + case/2)
            x = ((pos[i]%10)*case) + case/2
            # On a calculé le centre du cercle. On le dessine
            can1.create_oval(x-15, y-15, x+15, y+15, fill='green')
            i+=1
    else:
        return prenable

def joueur_suivant():
    #on passe au joueur suivant
    global joueur
    if joueur == 0:
        joueur = 1
    else:
        joueur = 0

    pions_prenable()

def select(event):
    #Traite les clicks sur la souris
    global selected
    # on détermine la case sélectionnée par la souris et on la colore en jaune
    ligne = int(event.y/case)
    colonne = int(event.x/case)
    print("ligne =",ligne)
    print("colonne = ",colonne)
    num_case = ligne*10+colonne
    print("num_case =",num_case)

    if selected == -1:
        y = ligne*case + case/2
        x = colonne*case + case/2
        print("x = ",x,"y = ",y) 
        if num_case in pions_b and joueur == 0:
            if pions_b.index(num_case) in dame_b:
                can1.create_rectangle(x-10, y-10, x+10, y+10, fill='yellow')
            else:    
                can1.create_oval(x-15, y-15, x+15, y+15, fill='yellow')
            selected = num_case
            possibilitees()
        elif num_case in pions_n and joueur == 1:
            if pions_n.index(num_case) in dame_n:
                can1.create_rectangle(x-10, y-10, x+10, y+10, fill='yellow')
            else:
                can1.create_oval(x-15, y-15, x+15, y+15, fill='yellow')
            selected = num_case
            possibilitees()

    else:
        # déplacement ou deselection
        if selected == num_case:
            selected = -1
            y = ligne*case + case/2
            x = colonne*case + case/2
            if num_case in pions_b:
                can1.create_oval(x-15, y-15, x+15, y+15, fill='red')
            else:
                can1.create_oval(x-15, y-15, x+15, y+15, fill='blue')
            # on redessine le plateau
            damier()
            place_pions()
        else:
            if deplacement(num_case):
                joueur_suivant()
            selected = -1
            damier()
            place_pions()

def restart():
    #Cette fonction reedémarre la partie avec saisie des noms des deux joueurs
    global bleu, rouge, pions_b, pions_n, selected, joueur, dame_b, dame_n, j1, j2, started
    bleu, rouge, selected, joueur = 0, 0, -1, 0
    pions_b = [0, 2, 4, 6, 8, 11, 13, 15, 17, 19, 20, 22, 24, 26, 28, 31, 33, 35, 37, 39]
    #pions-b est un tableau qui contient le numéro initial de positionnement des pions blancs
    pions_n = [60, 62, 64, 66, 68, 71, 73, 75, 77, 79, 80, 82, 84, 86, 88, 91, 93, 95, 97, 99]
    dame_n = []
    dame_b = []
    j1 = simpledialog.askstring("Nouvelle Partie...", "taper le nom du joueur 1:")
    j2 = simpledialog.askstring("Nouvelle Partie...", "taper le nom du joueur 2:")
    started = True
    damier()
    place_pions()

def interface():
    #Dessine la GUI
    global fenetre, can1, bt1, bt2, chaine, txt1, txt2
    fenetre = Tk()
    fenetre.title("Jeu de Dame")
    can1 = Canvas(fenetre, width=400, height=400, bg='dark grey')
    can1.bind("<Button-1>", select)
    can1.pack(side=TOP)
    chaine = Label(fenetre)
    chaine.configure(text="", fg='red')
    chaine.pack()
    txt1 = Label(fenetre, text='')
    txt2 = Label(fenetre, text='')
    txt1.pack()
    txt2.pack()
    bt1 = Button(fenetre, text='Quitter', command=fenetre.destroy)
    bt1.pack(side=LEFT)
    bt2 = Button(fenetre, text='Nouvelle Partie', command=restart)
    bt2.pack(side=RIGHT)
    damier()
    place_pions()

    fenetre.mainloop()


#--- Programme principal ---
started = False
selected = -1
j1 = ''
j2 = ''
joueur = 0
bleu = 0
rouge = 0
case = 40
# case est la variable définissant la taille des cases dessinnées

# Définition des tableaux co,tenant les numéros de cases
# ou sont implantées les pions
# Les cases de l'échiquier sont numérotées de 0 à 99
# de gauche à droite de haut 

#pions blanc
pions_b = []
dame_b = []
#pions noir
pions_n = []
dame_n = []
sauter_pas_jouer = []

interface()
  • # Remarque

    Posté par  . Évalué à 2. Dernière modification le 26 mai 2014 à 16:29.

    Ton code est difficilement lisible car certains caractères sont interprétés par le site. Il y a un moyen de le rendre lisible avec la balise qui va bien, c'est expliqué ici.

    Tu ne pourras sûrement pas éditer ton journal donc je te propose de mettre ton code (avec la balise adéquate) dans un commentaire.

    Autre remarque, tu mélanges l'anglais et le français dans le nom de tes variables (ou leurs valeurs, j'ai lu le code en diagonal et je ne connais pas bien le langage python), ce n'est pas une bonne idée.

    • [^] # Re: Remarque

      Posté par  . Évalué à 2.

      J'ai remis le code en forme,
      j'espere ne pas avoir perturbé les indentations necessaires à python

  • # comment demander de l'aide & méthode/outils de développement

    Posté par  . Évalué à 2.

    Alors, je ne vais pas aider, ou du moins, pas directement.

    Quand on demande de l'aide sur un programme, on essaie de reproduire le problème avec un bout de code minimal, et d'être succinct.
    Sinon, peu probable que des gens soient motivés à lire l'ensemble du source.

    Autre point, il existe des outils dont on ne te parlera probablement pas à l'école, mais qui sauvent de nombreux chatons tous les jours de la fureur des dev qui perdent patience, j'ai nommé les outils de versionning.
    Pas mal d'avantages, notamment au sujet de comment faire de petites itérations qui évitent d'introduire de super gros bugs, et quand c'est le cas, si les itérations étaient assez petites, de retrouver rapidement le bout de code coupable en cas de régression.
    Personnellement, j'apprécie bien git, mais il existe aussi subversion ( ou svn ), mercurial ( ou hg ), bazaar, fossil… pour débuter sur de petits projets, je dirais que fossil est pas mal, mais je ne connais pas de forge logicielle sur le web qui l'utilisent.

    Le lien entre le VCS et l'aide sur les forums, c'est que si t'es flemmard, tu peux juste balancer un lien vers ton repo. Et si tu es chanceux quelqu'un ira le lire… mais une fois encore, si tu n'as pas de code minimal qui montre le comportement erroné, c'est peu probable.

    Ensuite, au sujet de linuxfr, quand tu mets une balise, genre "```" il faut sauter une ligne avant de la mettre, sinon ça marche pas ( je me suis fait avoir plusieurs fois aussi ).
    D'ailleurs, le bouton pré-visualiser est là pour ça ( l'aiguille dans l'œil du voisin, je la vois mieux que la poutre dans le mien ;) ).

    Enfin, pour conclure, il s'agit d'un problème de programmation, python, je suppose ( commentaires bash-like, orienté objet, je ne connais pas python, mais je ne serais pas surpris )?
    Donc il aurait fallu mettre ce message dans les problèmes de programmation, ce n'est pas spécifique à linux.
    Et bien sûr, il aurait fallu préciser le langage, ainsi que les technologies employées qui pourraient impacter le comportement mis en cause.

    Ah, et dernier point ( pour de vrai ce coup-ci ): essayez de diviser le code au maximum en fonctions.
    Même si la fonction n'est appelée qu'une seule fois, et ne fait que 10 lignes, ça rends le code plus clair, surtout après 2 semaines de pause. Autre avantage: si un jour la même chose est nécessaire ailleurs, il est possible de réutiliser la fonction, et donc d'éviter d'avoir à corriger les choses à 20 coins différents.

    Petit exemple:
    déplacement bas-gauche
    et
    déplacement haut-gauche
    Leur code est très semblable. Suggestion: une fonction qui applique un déplacement serait probablement intéressante, prenant, au hasard ( j'ai juste survolé le code ), une coordonnée à modifier en entrée, un offset à lui appliquer pour la direction, le nombre d'itérations ( j'ai noté 10? ) ainsi que les probables coordonnées du rectangle dont il ne faut pas sortir.

    Une fois le tout refactoré pour être plus propre, ce sera plus simple d'avoir de l'aide, et d'ailleurs, peut-être même que vous aurez trouvé le problème de vous-mêmes.

  • # Testons

    Posté par  . Évalué à 2. Dernière modification le 27 mai 2014 à 07:43.

    J'ai voulu tester. Je suppose que tu utilises la version 3 de python (le nom du module tk est "tkinter" et pas "Tkinter") mais j'ai la même erreur avec python 2.7 :

    Traceback (most recent call last):
    File "/usr/lib/python3.2/tkinter/init.py", line 1426, in call
    return self.func(*args)
    File "dames.py", line 487, in restart
    j1 = simpledialog.askstring("Nouvelle Partie…", "taper le nom du joueur 1:")
    NameError: global name 'simpledialog' is not defined

    lorsque je clique sur le bouton "nouvelle partie"

    (Python 3.2.3)

    Autre chose, j'ai du ajouter la ligne :

    # -*- coding: utf-8 -*-
    

    au début du programme pour qu'il se lance (je suis sous Debian Wheezy), c'est peut-être lié au fait que j'ai copié-collé ton programme…

  • # Ouch

    Posté par  . Évalué à 2.

    vous êtes payés à la ligne?

                i = 1
                while i < 10:
                    l = s_ligne + i
                    cl = s_colonne - i
                    if l < 10 and cl >= 0:
                        c = l*10+cl
                        if case_libre(c):
                            pos.append(c)
                        elif c in pions_n:
                            break
                        else:
                            c2 = (l+1)*10+(cl-1)
                            if case_libre(c2):
                                pos.append(c2)
                                prenable.append(c2)
                                prenable.append(c)
                            break
                    else:
                        break
                    i+=1

    Il y a environ 8 bloc quasiment identique dans une fonction qui fait le café. Si il y a une correction à faire il faut la répercuter 8 fois ou avoir un générateur de code;

    fais en une fonction appelée successivement avec les paramètres qui vont bien et le retour qui va bien
    fct(params, 1,1)
    fct(params, 1,-1)
    fct(params, -1,-1)
    fct(params, -1,1)

    Je note aussi la présence de l pour ligne, selon la police utilisé l et 1 sont quasiment identique et c'est une source d'erreur potentiel, il vaut mieux utiliser x et y.

    Enfin quand une fonction nécessite de scroller (dépasse la hauteur d'un écran) Il faut se poser la question si il n'y a pas moyen de la découper intelligemment.

    Il ne faut pas décorner les boeufs avant d'avoir semé le vent

  • # euh ?

    Posté par  . Évalué à 1. Dernière modification le 28 mai 2014 à 12:31.

    C'est pas tout simplement:

    c = (s_ligne+1)*10+(s_colonne)

    qui devrait en fait être

    c = (s_ligne+1)*10+(s_colonne-1)

    (vu les autres lignes "c = (s_ligne…" qui ont l'air symétriques +1-1, +1+1, -1-1, -1+1) ?

    (sinon en effet, mieux vaut créer un fonction pour gérer ces blocs quasiment identiques, ça aurait été encore plus facile à trouver)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.