Bibm@th

Forum de mathématiques - Bibm@th.net

Bienvenue dans les forums du site BibM@th, des forums où on dit Bonjour (Bonsoir), Merci, S'il vous plaît...

Vous n'êtes pas identifié(e).

#1 06-08-2015 10:42:28

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 13 774

[Python]Jeu du Morpion solitaire

Bonjour,

Voici donc mon jeu du Morpion solitaire. (python 3. Attention pour Python 2 il me semble que ce n'est pas tkinter, mais Tkinter)
Rappel des règles

Le but du jeu est de tracer des traits horizontaux, verticaux obliques de G à D et  de D à G...
Pour ce faire vous devez joindre 5 croix alignées dans l'une des 4 directions.
On ne peut réutiliser pour un tracé qu'une croix déjà utilisée.
Vous ne pouvez poser poser qu'une croix à la fois...
Le jeu proposé est une variante incluant un bonus.
En effet, il arrivera, au cours de votre partie que 5 croix soient spontanément alignées sans pose de croix préalable : vous serez crédité alors d'un point de bonus.
Chaque point de bonus vous permet de poser une 2e croix consécutivement, mais vous ne pourrez poser plus de 2 croix consécutives.

Le programme.
La géométrie du jeu se passe de commentaires.
Le menu "Menu" vous permet
* d'effacer une la croix sous le curseur, pour autant que celle-ci n'ait pas encore servi.
* d'engager une nouvelle partie
* d'Enregistrer une partie en cours
d'"Enregistrer sous" une partie en cours, un n° vous sera demandé et votre partie sera enregistrée sous le nom Morpecrxx.txt où xx est le n° choisi. Les enregistrements seront faits dans un le sous-dossier Sauvegardes (qui sera créé automatiquement) du dossier en cours (celui où figure le programme).
* de charger une partie enregistrée
* de quitter proprement
Déplacer le curseur se fait à la souris par clics sur les 8 boutons de direction.
La position choisie, cliquez sur +...

Les tracés se font obligatoirement :
Horizontalement de G à D
Verticalement de Haut en Bas
Obliquement de G à D du haut vers le bas
Obliquement de D à G de haut en bas
Les boutons ne sont pas très clairs, j'y réfléchis : je vais voir si je suis capable de mettre une image sur un bouton, au lieu du texte.
Je pourrais utiliser une police qui comprend des flèches, mais je voudrais trouver une police figurant à la fois dans Win, Linux et Mac...

La technique.
Un drapeau (flag) est à 0 au début du jeu.
Lorsqu'une croix est posée, il est mis à 1 (puis à 2 en cas de pose de 2e croix et de bonus existant, décrémenté de 1). Le prog teste si l'emplacement où vous vous voulez déposer une croix n'est pas déjà occupé.
Pour chaque point de l'écran est associé un tuple (un couple) (a,b) initialisé à (0,256) puis (1,256) après pose d'une croix... Si le a vaut 1 c'est que tentez de poser une croix sur une croix déjà existante. Tous les tuples sont stockées dans une liste de listes Tem.
Pour extraire un tuple, il faut disposer des coordonnées du point : ligne li, colonne co :
Une liste par ligne...
a,b=Tem[li][co]
Avant tout tracé, je teste si 5 points consécutifs existent bien dans le tracé choisi.
Mais tout réside dans le b.
Pourquoi 256 ? parce que 256 s'écrit 100000000 en base 2.
Python via le mot clé bin, me donne : bin(256)="0b100000000", une chaîne...
Le témoin utilisable sera donc bin(256)[3:]="00000000"...
Chaque bit de cet octet représentera un déplacement :
J'ai opté pour, dans l'ordre, NS, SN, OE, EO, NE, SO, NO, SE
Supposons que je veuille joindre 5 croix consécutives verticalement (donc de H en B)
De la 1ere à la 4e croix, je dois tester si un trait ne part pas déjà de cette croix vers le bas :
ce sera le cas si le 8e bit vaut 1.
De la 2e à la 5e croix, je dois tester si un trait n'arrive pas déjà sur cette croix depuis le haut :
ce sera le cas si le 7e bit vaut 1.

Supposons qu'il s'agisse du début du jeu vierge de tout trait : tous les bits sont à 0...
1ere croix, j'ajoute 128 à son témoin qui positionne le 8e bit à 1 (valeur du b : 384)
Je laisse le 7e bit à 0 (puis mon tracé ne vient pas du dessus)
2e, 3e et 4e croix j'ajoute à 256 : 128+64 (valeur du b : 448). En effet le tracé provient de la croix supérieure, et part vers la croix inférieure.
5e croix : j'ajoute 64 à 256 : le tracé arrive de la croix supérieure mais n'en repart pas...
Pour chaque tracé j'examine donc 2 bits du témoin associé :
NS, SN  ---  OE, EO  ---  NE, SO --- NO, SE
et selon les cas, j'ajoute au témoin associé à chaque croix :
128, 64 --- 32, 16  --- 8, 4  ---  2, 1
Si un point accueille les 8 directions possible son témoin vaut son b vaut 511 :
bin(511)[3:]="11111111"
Alors pourquoi 256 ?
J'étais parti sur 0, mais la présentation binaire de 0 est "0" et non "00000000", alors que celle de 256 est "100000000"
Tout ça parce que même si je sais qu'on peut extraire un bit donné d'un octet, le modifier, le remettre en place : j'ai bien cherché et sur tout ce que j'ai pu lire rien n'a fonctionné !
Je vais insister...
Un point de "détail" : l'option command des boutons n'admet pas de paramètre : command=fonction. Orn j'en avais besoin, donc sur un site en anglais, j'ai trouvé quelqu'un qui était dans le même cas et à qui on a conseillé de passer par une fonction lambda laquelle appellera la fonction en question en lui passant un paramètre.

Explications supplémentaires à la demande.

Voici le code


#!/usr/bin/python
# -*- coding: utf-8 -*-

from tkinter import *
from tkinter.messagebox import showinfo
from tkinter.simpledialog import askinteger
from os import getcwd,sep,mkdir,path

sc,bn,flag,nomfich=0,0,0,"Morpecr"

def init_jeu(cas):
    global bn,sc,flag,xx,yy
    global Tem,curseur,nomfich
    tracer.delete("all")
    xx,yy,Tem=318,204,[]
    constructeur()
    curseur=tracer.create_polygon(xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3,fill="red")
    if cas==0:
        sc,bn,flag=0,0,0
    sco.set(str(sc).zfill(3))
    bns.set(str(bn).zfill(3))

def Sauver():
    global nomfich, bn,sc,flag,xx,yy
    global Tem,curseur,rep
    if nomfich=="Morpecr":
        SauverSous()
    else:
        sauve=rep+sep+nomfich
        with open(sauve, 'w') as mrp:
            mrp.write(str(sc)+" "+str(bn)+" "+str(flag)+"\n")
            for j in range(34):
                for i in range(35):
                    a,b=Tem[j][i]
                    mrp.write(str(a)+" "+str(b)+"\n")
        mrp.close()

def SauverSous():
    global nomfich,rep
    rep=getcwd()+sep+"Sauvegardes"
    try:
        mkdir(rep)
    except OSError:
        pass
    no=askinteger("Enregistrer sous","Choisissez un n° de fichier", minvalue=1,maxvalue=50)
    nomfich="Morpecr"+str(no)+".txt"
    Sauver()

def charger():
    global nomfich, bn,sc,flag,xx,yy
    global Tem,curseur,rep
    rep=getcwd()
    no=askinteger("Ouvrir un fichier","Choisissez un n° de fichier", minvalue=1,maxvalue=50)
    nomfich="Morpecr"+str(no)+".txt"
    if path.exists(rep):
        rep+=sep+"Sauvegardes"+sep+nomfich
        if path.exists(rep):
            charg=rep
            with open(rep,'r') as mrp:
                L=(mrp.readline().strip()).split()
                sc,bn,flag=int(L[0]),int(L[1]),int(L[2])
                init_jeu(1)
                sco.set(str(sc).zfill(3))
                bns.set(str(bn).zfill(3))
                for li in range(34):
                    for co in range(35):
                        L=(mrp.readline().strip()).split()
                        Tem[li][co]=(int(L[0]),int(L[1]))
            mrp.close()
            traite_chrg()
        else:
            Msg(10,"")
    else:
        Msg(11,"")

def traite_chrg():
    global nomfich, bn,sc,flag,xx,yy
    global Tem,curseur,Croix
    decale=[(0,18),(18,0),(18,18),(-18,18)]
    for li in range(34):
        for co in range(35):
            a,b=Tem[li][co]
    for li in range(34):
        for co in range(35):
            a,b=Tem[li][co]
            xx,yy=48+co*18,60+li*18
            if a==1:
                coul=["blue","black"][(li,co) in Croix]
                tracer.create_line(xx-4,yy,xx+5,yy,fill=coul,width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill=coul,width=1)
                temoin=bin(b)[3:]
                for bt in range(0,8,2):
                    bit=temoin[bt]
                    if bit=="1":
                        dx,dy=decale[bt//2]
                        tracer.create_line(xx,yy,xx+dx,yy+dy,fill="blue",width=1)
    xx,yy=318,258
    tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)  

       
def place_croix():
    global xx,yy,flag,bn
    co,li=(xx-48)//18,(yy-60)//18
    a,b=Tem[li][co]
    if a==1 :
        Msg(0,"")
    else:
        flag+=1
        if flag>2:
            flag=1
            Msg(5,"")
        else:
            if flag==2:
                if bn==0:
                    flag=1
                    Msg(6,"")    
                else:
                    bn-=1
                    Tem[li][co]=(1,b)
                    tracer.create_line(xx-4,yy,xx+5,yy,fill='blue',width=1)
                    tracer.create_line(xx,yy-4,xx,yy+5,fill='blue',width=1)
                    bns.set(str(bn).zfill(3))
            elif flag==1:
                Tem[li][co]=(1,b)
                tracer.create_line(xx-4,yy,xx+5,yy,fill='blue',width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill='blue',width=1)

def efface_croix():
    global flag
    co, li=(xx-48)//18,(yy-60)//18
    a,p=Tem[li][co]
    if a==0:
        Msg(7,"")
    else:
        if p>256:
            Msg(8,"")
        else:
            if flag==0:
                Msg(9,"")
            else:
                flag-=1
                Tem[li][co]=(0,256)
                tracer.create_line(xx-4,yy,xx+5,yy,fill='white',width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill='white',width=1)
                tracer.create_line(xx-1,yy,xx+2,yy,fill='blue',width=1)
                tracer.create_line(xx,yy-1,xx,yy+2,fill='blue',width=1)
                tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)
                if flag==1:
                    bn+=1
                    bn.set(str(bn).zfill(3))
       
def trace_curseur(dx,dy):
    global xx,yy
    xx+=dx
    yy+=dy
    if xx==30:
        xx=660
    elif xx==678:
        xx=48
    if yy==42:
        yy=654
    elif yy==672:
        yy=60
    tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)
   
def nord():  
    trace_curseur(0,-18)

def nordw():  
    trace_curseur(-18,-18)
   
def norde():  
    trace_curseur(18,-18)

def est():  
    trace_curseur(18,0)

def sude():  
    trace_curseur(18,18)

def sud():  
    trace_curseur(0,18)

def sudw():  
    trace_curseur(-18,18)

def west():
    trace_curseur(-18,0)


def HB():
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break
        p_bin=bin(p)[3:5]
        rg8,rg7=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg8=="1":
                ok=0
                Msg[2,""]
                break        
        elif j in [1,2,3]:
            if rg8=="1" or rg7=="1":
                ok=0
                no=["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg7=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        tracer.create_line(xx,yy,xx,yy+72,fill='blue',width=1)
        score()
        for j in range(5):
            a,p=Tem[li+j][co]
            if j==0:
                Tem[li+j][co]=(a,p+128)
            elif j in[1,2,3]:
                Tem[li+j][co]=(a,p+192)
            else:
                Tem[li+j][co]=(a,p+64)

def GD():
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li][co+j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[5:7]
        rg6,rg5=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg6=="1":
                ok=0
                Msg(2,"")
                break        
        elif j in [1,2,3]:
            if rg6=="1" or rg5=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg5=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        tracer.create_line(xx,yy,xx+72,yy,fill='blue',width=1)
        score()
        for j in range(5):
            a,p=Tem[li][co+j]
            if j ==0:
                Tem[li][co+j]=(a,p+32)
            elif j in[1,2,3]:
                Tem[li][co+j]=(a,p+48)
            else:
                Tem[li][co+j]=(a,p+16)
       
def HBE():
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co+j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[7:9]
        rg4,rg3=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg4=="1":
                Msg(2,"")
                ok=0
                break        
        elif j in [1,2,3]:
            if rg4=="1" or rg3=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg3=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        tracer.create_line(xx,yy,xx+72,yy+72,fill='blue',width=1)
        score()
        for j in range(5):
            a,p=Tem[li+j][co+j]
            if j==0:
                Tem[li+j][co+j]=(a,p+8)
            elif j in[1,2,3]:
                Tem[li+j][co+j]=(a,p+12)
            else:
                Tem[li+j][co+j]=(a,p+4)

def HBO():
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co-j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[9:11]
        rg2,rg1=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg2=="1":
                ok=0
                Msg(2,"")
                break        
        elif j in [1,2,3]:
            if rg2=="1" or rg1=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg1=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        tracer.create_line(xx,yy,xx-72,yy+72,fill='blue',width=1)
        score()
        for j in range(5):
            a,p=Tem[li+j][co-j]
            if j==0:
                Tem[li+j][co-j]=(a,p+2)
            elif j in[1,2,3]:
                Tem[li+j][co-j]=(a,p+3)
            else:
                Tem[li+j][co-j]=(a,p+1)

def Msg(m,no):
    Fenetre.bell()
    if m==0:
        showinfo('Erreur', "Cette croix existe déjà")
    elif m==1:
        showinfo('Erreur', "Il manque la "+no+" croix dans la direction choisie")      
    elif m==2:
        showinfo('Erreur', "Un trait part déjà de la 1ere croix dans cette direction")
    elif m==3:
        showinfo('Erreur', "Un trait passe déjà par la "+no+" dans cette direction")
    elif m==4:
        showinfo('Erreur', "Un trait arrive déjà sur la 5e croix dans cette direction")
    elif m==5:
        showinfo('Erreur', "Il est interdit de poser plus de 2 croix consécutives")
    elif m==6:
        showinfo('Erreur', "Bonus nul. Vous ne pouvez poser une 2e croix consécutive")
    elif m==7:
        showinfo('Erreur', "Il n'y a pas de croix à cet emplacement")
    elif m==8:
        showinfo('Erreur', "Suppression impossible : cette croix est déjà utilisée")
    elif m==9:
        showinfo('Erreur', "Suppression impossible : cette croix est d'origine")
    elif m==10:
        showinfo('Erreur', "Ce fichier n'existe pas !")
    else:
        showinfo('Erreur', "Le dossier Sauvegardes n'existe pas !")


def score():
    global sc,bn,flag
    sc+=1
    sco.set(str(sc).zfill(3))
    if flag==0:
        bn+=1
        bns.set(str(bn).zfill(3))
    flag=0

   
def constructeur():
    global Tem,Croix
    Tem,B=[],[]
    Croix=[(9,15),(9,16),(9,17),(9,18),(10,15),(10,18),(11,15),(11,18),(12,12),\
           (12,13),(12,14),(12,15),(12,18),(12,19),(12,20),(12,21),(13,12),(13,21),\
           (14,12),(14,21),(15,12),(15,13),(15,14),(15,15),(15,18),(15,19),(15,20),\
           (15,21),(16,15),(16,18),(17,15),(17,18),(18,15),(18,16),(18,17),(18,18)]

    for y in range(60,667,18):      #placement des repères
        for x in range(48,661,18):
            tracer.create_line(x-1,y,x+2,y,fill='blue',width=1)
            tracer.create_line(x,y-1,x,y+2,fill='blue',width=1)
            B.append((0,256))
        Tem.append(B)
        B=[]

    for li,co in Croix:             #placement des croix initiales et initialisation
        Tem[li][co]=(1,256)
        y,x=li*18+60,co*18+48
        tracer.create_line(x-4,y,x+5,y,fill='black',width=1)
        tracer.create_line(x,y-4,x,y+5,fill='black',width=1)


   
Fenetre=Tk()
Fenetre.title("Morpion solitaire")
Fenetre.geometry("1000x740")
Fenetre.resizable(height=False, width=False)

boutonmenu = Menubutton(Fenetre, text='Menu',font=("Arial",10,"bold"),relief="raised")
boutonmenu.grid(row=0,column=0,sticky="w")
boutonmenu.menu = Menu(boutonmenu, tearoff=0)
boutonmenu['menu'] = boutonmenu.menu
boutonmenu.menu.add_command(label='Effacer croix',command=efface_croix)
boutonmenu.menu.add_separator()
boutonmenu.menu.add_command(label='Nouvelle partie',command=lambda: init_jeu(0))
boutonmenu.menu.add_command(label='Enregistrer',command=Sauver)
boutonmenu.menu.add_command(label='Enregistrer sous',command=SauverSous)
boutonmenu.menu.add_command(label='Charger',command=charger)
boutonmenu.menu.add_command(label='Quitter',command=Fenetre.destroy)

tracer = Canvas(Fenetre,width=800,height=700,bg='white',bd=1,relief="groove")
tracer.grid(column=0,row=2, rowspan=100)
label = Label(Fenetre, text="Déplacements",font=("Arial",14,"bold"))
label.grid(column=2,columnspan=3, row=0)
label1 = Label(Fenetre, text="Tracés des traits",font=("Arial",14,"bold"))
label1.grid(column=2,columnspan=3, row=20)
label2 = Label(Fenetre, text = "Score", font=("Arial",10,"bold"),fg="blue")
label2.grid(column=2, row=40)
label3 = Label(Fenetre, text = "Bonus", font=("Arial",10,"bold"),fg="#02CC1C")
label3.grid(column=2, row=41)
sco=StringVar()
sco.set(str(sc).zfill(3))
labelscore = Label(Fenetre, textvariable=sco)
labelscore.config(bg="white",fg='blue')
labelscore.grid(column=3,row=40)
bns=StringVar()
bns.set(str(bn).zfill(3))
labelbonus = Label(Fenetre, textvariable=bns)
labelbonus.config(bg="white",fg='#02CC1C')
labelbonus.grid(column=3,row=41)      

Button(Fenetre,text='Nord-Ouest',command=nordw,fg="red").grid(column=2, row=7)
Button(Fenetre,text='Nord',command=nord,fg="red").grid(column=3, row=7)
Button(Fenetre,text='Nord-Est',command=norde,fg="red").grid(column=4, row=7)

Button(Fenetre,text='Ouest',command=west,fg="red").grid(column=2, row=8)
Button(Fenetre,text='+',font=("Arial",14,"bold"),fg='blue',command=place_croix).grid(column=3, row=8)
Button(Fenetre,text='Est',command=est,fg="red").grid(column=4, row=8)

Button(Fenetre,text='Sud-Ouest',command=sudw,fg="red").grid(column=2, row=9)
Button(Fenetre,text='Sud-Est',command=sude,fg="red").grid(column=4, row=9)
Button(Fenetre,text='Sud',command=sud,fg="red").grid(column=3, row=9)

Button(Fenetre,text='Horriz. -->',command=GD,fg="blue").grid(column=2, row=24)
Button(Fenetre,text='Vertic. |',command=HB,fg="blue").grid(column=4, row=24)
Button(Fenetre,text='HtGa-BsDr \\',command=HBE,fg="blue").grid(column=2, row=26)
Button(Fenetre,text='HtDr-BsGa /',command=HBO,fg="blue").grid(column=4, row=26)

init_jeu(0)
Fenetre.mainloop()
 

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#2 08-08-2015 19:36:24

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 13 774

Re : [Python]Jeu du Morpion solitaire

Bonsoir

2e version avec nouveau menu...
Dans Edition, on retrouve Effacer croix, mais aussi Effacer dernier trait (nouveau)
Nouvelle méthode de chargement et d'Enregistrement.
Enregistrement en donnant le nom de son choix, plus un n°...
Chargement, via la boîte de dialogue de l'OS, pour moi Windows...
Je crois avoir trouvé un bug lorsqu'on efface le dernier trait (calcul du bonus éventuel)...
Le temps de vérifier cela demain et je posterai le nouveau code...
En attendant, voici une copie d'écran :
150808092947331194.jpg

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#3 09-08-2015 17:48:16

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 13 774

Re : [Python]Jeu du Morpion solitaire

Salut,

Ma copie d'écran donne des traits pâteux qui rendent mal.
Lorsqu'un tracé en diagonale coupait un autre tracé, la suppression supprimait un point du tracé existant.
Ce problème n'apparaît plus, traité par la procédure repare().
De même, j'ai empêché qu'on puisse effacer plus d'un trait à la fois...

#!/usr/bin/python
# -*- coding: utf-8 -*-

from tkinter import *
from tkinter.messagebox import showinfo
from tkinter.simpledialog import askstring
from tkinter.filedialog import askopenfilename
from os import getcwd,sep,mkdir,path


##############################
##                          ##
## Morpion solitaire v. 2.0 ##
##                          ##
##############################


sc,bn,flag,eff,nomfich=0,0,0,0,""

def init_jeu(cas):
    global bn,sc,flag,xx,yy
    global Tem,curseur,nomfich
    tracer.delete("all")
    xx,yy,Tem=318,204,[]
    constructeur()
    curseur=tracer.create_polygon(xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3,fill="red")
    if cas==0:
        sc,bn,flag=0,0,0
    sco.set(str(sc).zfill(3))
    bns.set(str(bn).zfill(3))

def Sauver():
    global nomfich, bn,sc,flag,xx,yy
    global Tem,curseur,rep
    if nomfich=="":
        SauverSous()
    else:
        sauve=rep+sep+nomfich
        with open(sauve, 'w') as mrp:
            mrp.write(str(sc)+" "+str(bn)+" "+str(flag)+"\n")
            for j in range(34):
                for i in range(35):
                    a,b=Tem[j][i]
                    mrp.write(str(a)+" "+str(b)+"\n")
        mrp.close()

def SauverSous():
    global nomfich,rep
    rep=getcwd()+sep+"Sauvegardes"
    try:
        mkdir(rep)
    except OSError:
        pass
    nomfich=askstring("Enregistrer sous","Choisissez un nom de fichier")
    nomfich+=".txt"
    Sauver()


def charger():
    global sc,bn,flag,Tem,nomfich
    rep=getcwd()+sep+"Sauvegardes"
    if path.exists(rep):
        nomfich=(askopenfilename(initialdir=rep)).replace('/','\\')
        with open(nomfich,'r') as mrp:
            L=(mrp.readline().strip()).split()
            sc,bn,flag=int(L[0]),int(L[1]),int(L[2])
            init_jeu(1)
            sco.set(str(sc).zfill(3))
            bns.set(str(bn).zfill(3))
            for li in range(34):
                for co in range(35):
                    L=(mrp.readline().strip()).split()
                    Tem[li][co]=(int(L[0]),int(L[1]))
        mrp.close()
        traite_chrg()
    else:
        Msg(11,"_")


def traite_chrg():
    global bn,sc,flag,xx,yy
    global Tem,curseur,Croix
    decale=[(0,18),(18,0),(18,18),(-18,18)]
    for li in range(34):
        for co in range(35):
            a,b=Tem[li][co]
    for li in range(34):
        for co in range(35):
            a,b=Tem[li][co]
            xx,yy=48+co*18,60+li*18
            if a==1:
                coul=["blue","black"][(li,co) in Croix]
                tracer.create_line(xx-4,yy,xx+5,yy,fill=coul,width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill=coul,width=1)
                temoin=bin(b)[3:]
                for bt in range(0,8,2):
                    bit=temoin[bt]
                    if bit=="1":
                        dx,dy=decale[bt//2]
                        tracer.create_line(xx,yy,xx+dx,yy+dy,fill="blue",width=1)
    xx,yy=318,258
    tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)  

       
def place_croix():
    global xx,yy,flag,bn
    co,li=(xx-48)//18,(yy-60)//18
    a,b=Tem[li][co]
    if a==1 :
        Msg(0,"_")
    else:
        flag+=1
        if flag>2:
            flag=1
            Msg(5,"_")
        else:
            if flag==2:
                if bn==0:
                    flag=1
                    Msg(6,"_")    
                else:
                    bn-=1
                    Tem[li][co]=(1,b)
                    tracer.create_line(xx-4,yy,xx+5,yy,fill='blue',width=1)
                    tracer.create_line(xx,yy-4,xx,yy+5,fill='blue',width=1)
                    bns.set(str(bn).zfill(3))
            elif flag==1:
                Tem[li][co]=(1,b)
                tracer.create_line(xx-4,yy,xx+5,yy,fill='blue',width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill='blue',width=1)

def efface_croix():
    global flag,Croix,bn
    co, li=(xx-48)//18,(yy-60)//18
    a,p=Tem[li][co]
    if a==0:
        Msg(7,"_")
    else:
        if p>256:
            Msg(8,"_")
        else:
            if flag==0:
                if (li,co) in Croix:
                    Msg(7,"_")
                else:
                    Msg(9,"_")
            else:
                flag-=1
                Tem[li][co]=(0,256)
                tracer.create_line(xx-4,yy,xx+5,yy,fill='white',width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill='white',width=1)
                tracer.create_line(xx-1,yy,xx+2,yy,fill='blue',width=1)
                tracer.create_line(xx,yy-1,xx,yy+2,fill='blue',width=1)
                tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)
                if flag==1:
                    bn+=1
                    bns.set(str(bn).zfill(3))
                   
def efface_dernier_trait():
    global Croix,Donnees_trace,Coords_trace,flag,xx,yy,eff
    if eff==0:
        Msg(10,"_")
        return
    T=Tem[:]
    sc,bn=Donnees_trace[0]
    flag,nul=Donnees_trace[1]
    sy,sx=Donnees_trace[2]
    for i in range(3,8):
        a,p=Donnees_trace[i]
        li,co=Coords_trace[i-3]
        Tem[li][co]=a,p
    tracer.create_line(xx,yy,xx+sx*72,yy+sy*72,fill='white',width=1)
    bns.set(str(bn).zfill(3))
    sco.set(str(sc).zfill(3))
    for li,co in Coords_trace:
        y,x=60+18*li,48+18*co
        if (li,co)in Croix :
            coul="black"
        else :
            coul="blue"
        tracer.create_line(x-4,y,x+5,y,fill=coul,width=1)
        tracer.create_line(x,y-4,x,y+5,fill=coul,width=1)
    tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)
    if sx*sy!=0:
        repare(Coords_trace,T,sx)
    eff=0

def repare(Ct,T,s):
    for i in range(4):
        li,co=Ct[i]
        a,p=T[li][co+s]
        temoin=bin(p)[8+s]
        if temoin=="1":
            x,y=(co+s)*18+48,li*18+60
            tracer.create_line(x,y,x-s*18,y+18,fill='blue',width=1)
        print()
   
       
def trace_curseur(dx,dy):
    global xx,yy
    xx+=dx
    yy+=dy
    if xx==30:
        xx=660
    elif xx==678:
        xx=48
    if yy==42:
        yy=654
    elif yy==672:
        yy=60
    tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)
   
def nord():  
    trace_curseur(0,-18)

def nordw():  
    trace_curseur(-18,-18)
   
def norde():  
    trace_curseur(18,-18)

def est():  
    trace_curseur(18,0)

def sude():  
    trace_curseur(18,18)

def sud():  
    trace_curseur(0,18)

def sudw():  
    trace_curseur(-18,18)

def west():
    trace_curseur(-18,0)


def HB():
    global Donnees_trace,Coords_trace,eff
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break
        p_bin=bin(p)[3:5]
        rg8,rg7=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg8=="1":
                ok=0
                Msg(2,"_")
                break        
        elif j in [1,2,3]:
            if rg8=="1" or rg7=="1":
                ok=0
                no=["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg7=="1":
               ok=0
               Msg(4,"_")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(1,0)],[],1  
        tracer.create_line(xx,yy,xx,yy+72,fill='blue',width=1)
        score()
        for j in range(5):
            a,p=Tem[li+j][co]
            Donnees_trace.append((a,p))
            Coords_trace.append((li+j,co))
            if j==0:
                Tem[li+j][co]=(a,p+128)
            elif j in[1,2,3]:
                Tem[li+j][co]=(a,p+192)
            else:
                Tem[li+j][co]=(a,p+64)

def GD():
    global Donnees_trace,Coords_trace,eff
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li][co+j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[5:7]
        rg6,rg5=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg6=="1":
                ok=0
                Msg(2,"")
                break        
        elif j in [1,2,3]:
            if rg6=="1" or rg5=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg5=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(0,1)],[],1  
        tracer.create_line(xx,yy,xx+72,yy,fill='blue',width=1)      
        score()
        for j in range(5):
            a,p=Tem[li][co+j]
            Donnees_trace.append((a,p))
            Coords_trace.append((li,co+j))
            if j ==0:
                Tem[li][co+j]=(a,p+32)
            elif j in[1,2,3]:
                Tem[li][co+j]=(a,p+48)
            else:
                Tem[li][co+j]=(a,p+16)
       
def HBE():
    global Donnees_trace,Coords_trace,eff
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co+j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[7:9]
        rg4,rg3=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg4=="1":
                Msg(2,"")
                ok=0
                break        
        elif j in [1,2,3]:
            if rg4=="1" or rg3=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg3=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(1,1)],[],1  
        tracer.create_line(xx,yy,xx+72,yy+72,fill='blue',width=1)
        score()
        for j in range(5):
            a,p=Tem[li+j][co+j]
            Donnees_trace.append((a,p))
            Coords_trace.append((li+j,co+j))
            if j==0:
                Tem[li+j][co+j]=(a,p+8)
            elif j in[1,2,3]:
                Tem[li+j][co+j]=(a,p+12)
            else:
                Tem[li+j][co+j]=(a,p+4)
               

def HBO():
    global Donnees_trace,Coords_trace,eff
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co-j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[9:11]
        rg2,rg1=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg2=="1":
                ok=0
                Msg(2,"_")
                break        
        elif j in [1,2,3]:
            if rg2=="1" or rg1=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg1=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(1,-1)],[],1
        tracer.create_line(xx,yy,xx-72,yy+72,fill='blue',width=1)
        score()
        for j in range(5):
            a,p=Tem[li+j][co-j]
            Donnees_trace.append((a,p))
            Coords_trace.append((li+j,co-j))
            if j==0:
                Tem[li+j][co-j]=(a,p+2)
            elif j in[1,2,3]:
                Tem[li+j][co-j]=(a,p+3)
            else:
                Tem[li+j][co-j]=(a,p+1)

def Msg(m,no):
    Fenetre.bell()
    if m==0:
        showinfo('Erreur', "Cette croix existe déjà")
    elif m==1:
        showinfo('Erreur', "Il manque la "+no+" croix dans la direction choisie")      
    elif m==2:
        showinfo('Erreur', "Un trait part déjà de la 1ere croix dans cette direction")
    elif m==3:
        showinfo('Erreur', "Un trait passe déjà par la "+no+" dans cette direction")
    elif m==4:
        showinfo('Erreur', "Un trait arrive déjà sur la 5e croix dans cette direction")
    elif m==5:
        showinfo('Erreur', "Il est interdit de poser plus de 2 croix consécutives")
    elif m==6:
        showinfo('Erreur', "Bonus nul. Vous ne pouvez poser une 2e croix consécutive")
    elif m==7:
        showinfo('Erreur', "Il n'y a pas de croix à cet emplacement")
    elif m==8:
        showinfo('Erreur', "Suppression impossible : cette croix est déjà utilisée")
    elif m==9:
        showinfo('Erreur', "Suppression impossible : cette croix est d'origine")
    elif m==10:
        showinfo('Erreur', "Suppression non autorisée !")
    else:
        showinfo('Erreur', "Le dossier Sauvegardes n'existe pas !")


def score():
    global sc,bn,flag
    sc+=1
    sco.set(str(sc).zfill(3))
    if flag==0:
        bn+=1
        bns.set(str(bn).zfill(3))
    flag=0

   
def constructeur():
    global Tem,Croix,eff
    Tem,B,eff=[],[],0
    Croix=[(9,15),(9,16),(9,17),(9,18),(10,15),(10,18),(11,15),(11,18),(12,12),\
           (12,13),(12,14),(12,15),(12,18),(12,19),(12,20),(12,21),(13,12),(13,21),\
           (14,12),(14,21),(15,12),(15,13),(15,14),(15,15),(15,18),(15,19),(15,20),\
           (15,21),(16,15),(16,18),(17,15),(17,18),(18,15),(18,16),(18,17),(18,18)]

    for y in range(60,667,18):      #placement des repères
        for x in range(48,661,18):
            tracer.create_line(x-1,y,x+2,y,fill='blue',width=1)
            tracer.create_line(x,y-1,x,y+2,fill='blue',width=1)
            B.append((0,256))
        Tem.append(B)
        B=[]

    for li,co in Croix:             #placement des croix initiales et initialisation
        Tem[li][co]=(1,256)
        y,x=li*18+60,co*18+48
        tracer.create_line(x-4,y,x+5,y,fill='black',width=1)
        tracer.create_line(x,y-4,x,y+5,fill='black',width=1)


   
Fenetre=Tk()
Fenetre.title("Morpion solitaire")
Fenetre.geometry("1000x740")
Fenetre.resizable(height=False, width=False)
menubar = Menu(Fenetre)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Fichier", menu=filemenu)
filemenu.add_command(label="Nouvelle partie",command=lambda: init_jeu(0))
filemenu.add_command(label="Charger fichier",command=charger)
filemenu.add_command(label="Enregistrer",command=Sauver)
filemenu.add_command(label="Enregistrer sous",command=SauverSous)
filemenu.add_separator()
filemenu.add_command(label="Quitter",command=Fenetre.destroy)

editmenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Edition", menu=editmenu)
editmenu.add_command(label='Effacer croix',command=efface_croix)
editmenu.add_command(label="Effacer dernier trait",command=efface_dernier_trait)
Fenetre.config(menu=menubar)


tracer = Canvas(Fenetre,width=800,height=700,bg='white',bd=1,relief="groove")
tracer.grid(column=0,row=2, rowspan=100)
label = Label(Fenetre, text="Déplacements",font=("Arial",14,"bold"))
label.grid(column=2,columnspan=3, row=0)
label1 = Label(Fenetre, text="Tracés des traits",font=("Arial",14,"bold"))
label1.grid(column=2,columnspan=3, row=20)
label2 = Label(Fenetre, text = "Score", font=("Arial",10,"bold"),fg="blue")
label2.grid(column=2, row=40)
label3 = Label(Fenetre, text = "Bonus", font=("Arial",10,"bold"),fg="#02CC1C")
label3.grid(column=2, row=41)
sco=StringVar()
sco.set(str(sc).zfill(3))
labelscore = Label(Fenetre, textvariable=sco)
labelscore.config(bg="white",fg='blue')
labelscore.grid(column=3,row=40)
bns=StringVar()
bns.set(str(bn).zfill(3))
labelbonus = Label(Fenetre, textvariable=bns)
labelbonus.config(bg="white",fg='#02CC1C')
labelbonus.grid(column=3,row=41)      

Button(Fenetre,text='Nord-Ouest',command=nordw,fg="red").grid(column=2, row=7)
Button(Fenetre,text='Nord',command=nord,fg="red").grid(column=3, row=7)
Button(Fenetre,text='Nord-Est',command=norde,fg="red").grid(column=4, row=7)

Button(Fenetre,text='Ouest',command=west,fg="red").grid(column=2, row=8)
Button(Fenetre,text='+',font=("Arial",14,"bold"),fg='blue',command=place_croix).grid(column=3, row=8)
Button(Fenetre,text='Est',command=est,fg="red").grid(column=4, row=8)

Button(Fenetre,text='Sud-Ouest',command=sudw,fg="red").grid(column=2, row=9)
Button(Fenetre,text='Sud-Est',command=sude,fg="red").grid(column=4, row=9)
Button(Fenetre,text='Sud',command=sud,fg="red").grid(column=3, row=9)

Button(Fenetre,text='Horriz. -->',command=GD,fg="blue").grid(column=2, row=24)
Button(Fenetre,text='Vertic. |',command=HB,fg="blue").grid(column=4, row=24)
Button(Fenetre,text='HtGa-BsDr \\',command=HBE,fg="blue").grid(column=2, row=26)
Button(Fenetre,text='HtDr-BsGa /',command=HBO,fg="blue").grid(column=4, row=26)

init_jeu(0)
Fenetre.mainloop() # Lancement de la boucle du programme, en attente d'événements (clavier, souris,...)

Réponses à vos interrogations éventuelles sur demande...
Pensez à signaler les bugs éventuels, merci.

@+

[EDIT]
Correction de  Ms(g2,"') dans GD() en Msg(2,"") - ligne 298
Donnees_trace au lieu de Données_trace -  ligne 160

Dernière modification par yoshi (11-08-2015 10:09:46)


Arx Tarpeia Capitoli proxima...

Hors ligne

#4 21-08-2015 12:47:16

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 13 774

Re : [Python]Jeu du Morpion solitaire

Bonjour,

Je vous livre ma dernière évolution.
Correction de bugs (mineurs) résiduels qui permettaient de "tricher".
Affichage en haut et à gauche du nom de la partie en cours.
Modification de la méthode d'enregistrement des fichiers, je fais appel à asksaveasfilename.
Modification du nom de l'extension, le contenu du fichier restant le même.
Modification de la méthode de suppression du dernier trait tracé ou du nom de la partie en cours :
dans mon canvas nommé tracé, je peux effacer un objet quelconque via la méthode .delete(objet) pourvu que lors de la création dudit objet, on lui ait affecté un nom avec l'option tag="nom"...

J'ai créé 4 images .gif (extension obligatoire en standard) de 27x27 pixels de flèches bleues
horizontales de G à D
verticales de B en H
oblique descendante de G à D
oblique descendante de D à G
Et j'ai inclus ces images sur les boutons, les commandes sont précédées de #, j'ai laissé ici le texte sur les boutons.
J'ai passé la valeur par défaut de l'élément a du couple (a,b) associé à chaque point à 2 pour les croix initiales, et à 1 pour les croix créées par nous : il arrivait qu'un message d'erreur, à la suppression d'une croix) fasse référence – à tort – à l'interdiction d'effacer une croix d'origine alors que ce n'était pas le cas.
Au lieu de tester l'existence du sous-dossier Sauvegardes à chaque enregistrement ou chargement d'un fichier, il est testé à chaque première utilisation du programme seulement.

Tout a l'air de fonctionner correctement après plus d'une centaine d'essais, si ce n'est un bug que je n'arrive pas à reproduire à volonté et que j'ai rencontré deux fois : après effacement du dernier trait, il y a eu impossibilité d'effacement de croix (qui avait servi) et impossibilité de tracer dans quelque sens (pourtant correct) que ce soit : un trait étant déclaré comme passant déjà par un des points du tracé sélectionné...

Dans ces conditions, difficile de le corriger... Je ne l'ai pas rencontrer pour un moment.
Un regret, l'utilisation d'une douzaine de variables globales en tout, je n'aime pas ça, mais pour l'instant je ne sais pas faire autrement.

Je suis preneur de toute suggestion...

#!/usr/bin/python
# -*- coding: utf-8 -*-

from tkinter import *
from tkinter.messagebox import showinfo
from tkinter.simpledialog import askstring
from tkinter.filedialog import askopenfilename,asksaveasfilename
from os import getcwd,sep,mkdir,path


##############################
##                          ##
## Morpion solitaire v. 3.0 ##
##                          ##
##############################


sc,bn,flag,eff,nmf=0,0,0,0,""

def init_jeu(cas):
    global bn,sc,flag,xx,yy
    global Tem,curseur
    tracer.delete("all")    
    xx,yy,Tem=318,204,[]
    constructeur()
    curseur=tracer.create_polygon(xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3,fill="red")
    if cas==0:
        sc,bn,flag=0,0,0
    sco.set(str(sc).zfill(3))
    bns.set(str(bn).zfill(3))

def Sauver():
    global nmf,nomfich, bn,sc,flag,xx,yy
    global Tem,curseur,rep
    if nmf=="":
        SauverSous()
    else:
        lt,ld=len(nmf)-4,len(rep)+1
        nomfich=nmf[ld:lt]
        NomPartie(nomfich)    
        with open(nmf, 'w') as mrp:
            mrp.write(str(sc)+" "+str(bn)+" "+str(flag)+"\n")
            for li in range(34):
                for co in range(35):
                    a,b=Tem[li][co]
                    mrp.write(str(a)+" "+str(b)+"\n")
        mrp.close()

def SauverSous():
    global nmf,rep
    rep=getcwd()+sep+"Sauvegardes"
    nmf=asksaveasfilename(initialdir=rep,defaultextension='.mrs',).replace('/','\\')
    Sauver()


def charger():
    global sc,bn,flag,Tem,nomfich,nmf
    rep=getcwd()+sep+"Sauvegardes"
    if path.exists(rep):
        nmf=(askopenfilename(initialdir=rep)).replace('/','\\')
        with open(nmf,'r') as mrp:
            L=(mrp.readline().strip()).split()
            sc,bn,flag=int(L[0]),int(L[1]),int(L[2])
            init_jeu(1)
            sco.set(str(sc).zfill(3))
            bns.set(str(bn).zfill(3))
            for li in range(34):
                for co in range(35):
                    L=(mrp.readline().strip()).split()
                    Tem[li][co]=(int(L[0]),int(L[1]))
        mrp.close()
        lt,ld=len(nmf)-4,len(rep)+1
        nomfich=nmf[ld:lt]
        NomPartie(nomfich)
        traite_chrg()
    else:
        Msg(11,"_")

def traite_chrg():
    global bn,sc,flag,xx,yy
    global Tem,curseur,Croix
    decale=[(0,18),(18,0),(18,18),(-18,18)]
    for li in range(34):
        for co in range(35):
            a,b=Tem[li][co]
    for li in range(34):
        for co in range(35):
            a,b=Tem[li][co]
            xx,yy=48+co*18,60+li*18
            if a>=1:
                coul=["blue","black"][(li,co) in Croix]
                tracer.create_line(xx-4,yy,xx+5,yy,fill=coul,width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill=coul,width=1)
                temoin=bin(b)[3:]
                for bt in range(0,8,2):
                    bit=temoin[bt]
                    if bit=="1":
                        dx,dy=decale[bt//2]
                        tracer.create_line(xx,yy,xx+dx,yy+dy,fill="blue",width=1)
    xx,yy=318,258
    tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)  

def NomPartie(nom):
    if tracer.find_withtag('titre'):
        tracer.delete('titre')
    tracer.create_text(10,5,text=nom,font=("Arial",10,"italic"),fill="blue",tag="titre",anchor="nw")

     
def place_croix():
    global xx,yy,flag,bn
    co,li=(xx-48)//18,(yy-60)//18
    a,b=Tem[li][co]
    if a>=1 :
        Msg(0,"_")
    else:
        flag+=1
        if flag>2:
            flag=1
            Msg(5,"_")
        else:
            if flag==2:
                if bn==0:
                    flag=1
                    Msg(6,"_")    
                else:
                    bn-=1
                    Tem[li][co]=(1,b)
                    tracer.create_line(xx-4,yy,xx+5,yy,fill='blue',width=1)
                    tracer.create_line(xx,yy-4,xx,yy+5,fill='blue',width=1)
                    bns.set(str(bn).zfill(3))
            elif flag==1:
                Tem[li][co]=(1,b)
                tracer.create_line(xx-4,yy,xx+5,yy,fill='blue',width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill='blue',width=1)

def efface_croix():
    global flag,bn
    co, li=(xx-48)//18,(yy-60)//18
    a,p=Tem[li][co]
    if a==0:
        Msg(7,"_")
    elif a==2:
        Msg(9,"_")
    else:
        if p>256:
            Msg(8,"_")
        else:
            if flag!=0:
                flag-=1
                Tem[li][co]=(0,256)
                tracer.create_line(xx-4,yy,xx+5,yy,fill='white',width=1)
                tracer.create_line(xx,yy-4,xx,yy+5,fill='white',width=1)
                tracer.create_line(xx-1,yy,xx+2,yy,fill='blue',width=1)
                tracer.create_line(xx,yy-1,xx,yy+2,fill='blue',width=1)
                tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)
                if flag==1:
                    bn+=1
                    bns.set(str(bn).zfill(3))

def efface(trait):
    global Croix,Donnees_trace,Coords_trace,flag,xx,yy,eff,sc,bn
    if eff==0:
        Msg(10,"_")
        return
    T=Tem[:]
    sc,bn=Donnees_trace[0]
    flag,nul=Donnees_trace[1]
    sy,sx=Donnees_trace[2]
    for i in range(3,8):
        a,p=Donnees_trace[i]
        li,co=Coords_trace[i-3]
        Tem[li][co]=a,p
    tracer.delete(trait)
    eff=0
       
def trace_curseur(dx,dy):
    global xx,yy
    xx+=dx
    yy+=dy
    if xx==30:
        xx=660
    elif xx==678:
        xx=48
    if yy==42:
        yy=654
    elif yy==672:
        yy=60
    tracer.coords(curseur,xx-3,yy-3,xx+4,yy+4,xx+4,yy-3,xx-3,yy+4,xx-3,yy-3)
   
def nord():  
    trace_curseur(0,-18)

def nordw():  
    trace_curseur(-18,-18)
   
def norde():  
    trace_curseur(18,-18)

def est():  
    trace_curseur(18,0)

def sude():  
    trace_curseur(18,18)

def sud():  
    trace_curseur(0,18)

def sudw():  
    trace_curseur(-18,18)

def west():
    trace_curseur(-18,0)


def HB():
    global Donnees_trace,Coords_trace,eff,sc,trait
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break
        p_bin=bin(p)[3:5]
        rg8,rg7=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg8=="1":
                ok=0
                Msg(2,"_")
                break        
        elif j in [1,2,3]:
            if rg8=="1" or rg7=="1":
                ok=0
                no=["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg7=="1":
               ok=0
               Msg(4,"_")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(1,0)],[],1
        trait="Trait"+str(sc)
        tracer.create_line(xx,yy,xx,yy+72,fill='blue',width=1,tag=trait)
        score()
        for j in range(5):
            a,p=Tem[li+j][co]
            Donnees_trace.append((a,p))
            Coords_trace.append((li+j,co))
            if j==0:
                Tem[li+j][co]=(a,p+128)
            elif j in[1,2,3]:
                Tem[li+j][co]=(a,p+192)
            else:
                Tem[li+j][co]=(a,p+64)

def GD():
    global Donnees_trace,Coords_trace,eff,sc,trait
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li][co+j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[5:7]
        rg6,rg5=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg6=="1":
                ok=0
                Msg(2,"")
                break        
        elif j in [1,2,3]:
            if rg6=="1" or rg5=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg5=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(0,1)],[],1
        trait="Trait"+str(sc)
        tracer.create_line(xx,yy,xx+72,yy,fill='blue',width=1,tag=trait)      
        score()
        for j in range(5):
            a,p=Tem[li][co+j]
            Donnees_trace.append((a,p))
            Coords_trace.append((li,co+j))
            if j ==0:
                Tem[li][co+j]=(a,p+32)
            elif j in[1,2,3]:
                Tem[li][co+j]=(a,p+48)
            else:
                Tem[li][co+j]=(a,p+16)
       
def HBE():
    global Donnees_trace,Coords_trace,eff,sc,trait
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co+j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[7:9]
        rg4,rg3=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg4=="1":
                Msg(2,"")
                ok=0
                break        
        elif j in [1,2,3]:
            if rg4=="1" or rg3=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg3=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(1,1)],[],1
        trait="Trait"+str(sc)      
        tracer.create_line(xx,yy,xx+72,yy+72,fill='blue',width=1,tag=trait)
        score()
        for j in range(5):
            a,p=Tem[li+j][co+j]
            Donnees_trace.append((a,p))
            Coords_trace.append((li+j,co+j))
            if j==0:
                Tem[li+j][co+j]=(a,p+8)
            elif j in[1,2,3]:
                Tem[li+j][co+j]=(a,p+12)
            else:
                Tem[li+j][co+j]=(a,p+4)
               

def HBO():
    global Donnees_trace,Coords_trace,eff,sc,trait
    co,li=(xx-48)//18,(yy-60)//18
    ok=1
    for j in range(5):
        a,p=Tem[li+j][co-j]
        if a==0:
            ok,no=0,["1ere","2e","3e","4e","5e"][j]
            Msg(1,no)
            break                                  
        p_bin=bin(p)[9:11]
        rg2,rg1=p_bin[0:1],p_bin[1:2]
        if j==0:
            if rg2=="1":
                ok=0
                Msg(2,"_")
                break        
        elif j in [1,2,3]:
            if rg2=="1" or rg1=="1":
                ok,no=0,["2e","3e","4e"][j-1]
                Msg(3,no)
                break
        else:
           if rg1=="1":
               ok=0
               Msg(4,"")
               break        
        if not ok:
            break
    if ok:
        Donnees_trace,Coords_trace,eff=[(sc,bn),(flag,0),(1,-1)],[],1
        trait="Trait"+str(sc)
        tracer.create_line(xx,yy,xx-72,yy+72,fill='blue',width=1,tag=trait)
        score()
        for j in range(5):
            a,p=Tem[li+j][co-j]
            Donnees_trace.append((a,p))
            Coords_trace.append((li+j,co-j))
            if j==0:
                Tem[li+j][co-j]=(a,p+2)
            elif j in[1,2,3]:
                Tem[li+j][co-j]=(a,p+3)
            else:
                Tem[li+j][co-j]=(a,p+1)

def Msg(m,no):
    Fenetre.bell()
    if m==0:
        showinfo('Erreur', "Cette croix existe déjà")
    elif m==1:
        showinfo('Erreur', "Il manque la "+no+" croix dans la direction choisie")      
    elif m==2:
        showinfo('Erreur', "Un trait part déjà de la 1ere croix dans cette direction")
    elif m==3:
        showinfo('Erreur', "Un trait passe déjà par la "+no+" dans cette direction")
    elif m==4:
        showinfo('Erreur', "Un trait arrive déjà sur la 5e croix dans cette direction")
    elif m==5:
        showinfo('Erreur', "Il est interdit de poser plus de 2 croix consécutives")
    elif m==6:
        showinfo('Erreur', "Bonus nul. Vous ne pouvez poser une 2e croix consécutive")
    elif m==7:
        showinfo('Erreur', "Il n'y a pas de croix à cet emplacement")
    elif m==8:
        showinfo('Erreur', "Suppression impossible : cette croix est déjà utilisée")
    elif m==9:
        showinfo('Erreur', "Suppression impossible : cette croix est d'origine")
    elif m==10:
        showinfo('Erreur', "Suppression non autorisée !")
    else:
        showinfo('Erreur', "Le dossier Sauvegardes n'existe pas !")


def score():
    global sc,bn,flag
    sc+=1
    sco.set(str(sc).zfill(3))
    if flag==0:
        bn+=1
        bns.set(str(bn).zfill(3))
    flag=0

   
def constructeur():
    global Tem,Croix,eff
    Tem,B,eff=[],[],0
    Croix=[(9,15),(9,16),(9,17),(9,18),(10,15),(10,18),(11,15),(11,18),(12,12),\
           (12,13),(12,14),(12,15),(12,18),(12,19),(12,20),(12,21),(13,12),(13,21),\
           (14,12),(14,21),(15,12),(15,13),(15,14),(15,15),(15,18),(15,19),(15,20),\
           (15,21),(16,15),(16,18),(17,15),(17,18),(18,15),(18,16),(18,17),(18,18)]

    for y in range(60,667,18):      #placement des "points" de repère
        for x in range(48,661,18):
            tracer.create_line(x-1,y,x+2,y,fill='blue',width=1)
            tracer.create_line(x,y-1,x,y+2,fill='blue',width=1)
            B.append((0,256))
        Tem.append(B)
        B=[]

    for li,co in Croix:             #placement des croix initiales et initialisation
        Tem[li][co]=(2,256)
        y,x=li*18+60,co*18+48
        tracer.create_line(x-4,y,x+5,y,fill='black',width=1)
        tracer.create_line(x,y-4,x,y+5,fill='black',width=1)


try:
    mkdir(getcwd()+sep+"Sauvegardes")
except OSError:
    pass
Fenetre=Tk()
Fenetre.title("Morpion solitaire")
Fenetre.geometry("1000x740")
Fenetre.resizable(height=False, width=False)
#V=PhotoImage(file='Vert.gif')
#H=PhotoImage(file='GD.gif')
#G=PhotoImage(file='HBE.gif')
#D=PhotoImage(file='HBO.gif')
menubar = Menu(Fenetre)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Fichier", menu=filemenu)
filemenu.add_command(label="Nouvelle partie",command=lambda: init_jeu(0))
filemenu.add_command(label="Charger fichier",command=charger)
filemenu.add_command(label="Enregistrer",command=Sauver)
filemenu.add_command(label="Enregistrer sous",command=SauverSous)
filemenu.add_separator()
filemenu.add_command(label="Quitter",command=Fenetre.destroy)

editmenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Edition", menu=editmenu)
editmenu.add_command(label='Effacer croix',command=efface_croix)
editmenu.add_command(label="Effacer dernier trait",command=lambda: efface(trait))
Fenetre.config(menu=menubar)


tracer = Canvas(Fenetre,width=800,height=700,bg='white',bd=1,relief="groove")
tracer.grid(column=0,row=2, rowspan=100)
label = Label(Fenetre, text="Déplacements",font=("Arial",14,"bold"))
label.grid(column=2,columnspan=3, row=0)
label1 = Label(Fenetre, text="Tracés des traits",font=("Arial",14,"bold"))
label1.grid(column=2,columnspan=3, row=20)
label2 = Label(Fenetre, text = "Score", font=("Arial",10,"bold"),fg="blue")
label2.grid(column=2, row=40)
label3 = Label(Fenetre, text = "Bonus", font=("Arial",10,"bold"),fg="#02CC1C")
label3.grid(column=2, row=41)
sco=StringVar()
sco.set(str(sc).zfill(3))
labelscore = Label(Fenetre, textvariable=sco)
labelscore.config(bg="white",fg='blue')
labelscore.grid(column=3,row=40)
bns=StringVar()
bns.set(str(bn).zfill(3))
labelbonus = Label(Fenetre, textvariable=bns)
labelbonus.config(bg="white",fg='#02CC1C')
labelbonus.grid(column=3,row=41)      

Button(Fenetre,text='Nord-Ouest',command=nordw,fg="red").grid(column=2, row=7)
Button(Fenetre,text='Nord',command=nord,fg="red").grid(column=3, row=7)
Button(Fenetre,text='Nord-Est',command=norde,fg="red").grid(column=4, row=7)

Button(Fenetre,text='Ouest',command=west,fg="red").grid(column=2, row=8)
Button(Fenetre,text='+',font=("Arial",14,"bold"),fg='blue',command=place_croix).grid(column=3, row=8)

Button(Fenetre,text='Est',command=est,fg="red").grid(column=4, row=8)
Button(Fenetre,text='Sud-Ouest',command=sudw,fg="red").grid(column=2, row=9)
Button(Fenetre,text='Sud-Est',command=sude,fg="red").grid(column=4, row=9)
Button(Fenetre,text='Sud',command=sud,fg="red").grid(column=3, row=9)

Button(Fenetre,text='→',font=("Arial",14,"bold"),command=GD,fg="blue").grid(column=2, row=24)
Button(Fenetre,text='↓',font=("Arial",14,"bold"),command=HB,fg="blue").grid(column=4, row=24)
Button(Fenetre,text='\\',font=("Arial",14,"bold"),command=HBE,fg="blue").grid(column=2, row=26)
Button(Fenetre,text='/',font=("Arial",14,"bold"),command=HBO,fg="blue").grid(column=4, row=26)
#Button(Fenetre,image=H,command=GD).grid(column=2, row=24)
#Button(Fenetre,image=V,command=HB).grid(column=4, row=24)
#Button(Fenetre,image=G,command=HBE).grid(column=2, row=26)
#Button(Fenetre,image=D,command=HBO).grid(column=4, row=26)

init_jeu(0)
NomPartie("NouvellePartie")
Fenetre.mainloop()

@+

[EDIT] Merci Tercès !
Ligne 527 corrigée

Dernière modification par yoshi (05-10-2015 17:15:21)


Arx Tarpeia Capitoli proxima...

Hors ligne

#5 04-10-2015 19:31:23

Terces
Membre
Inscription : 16-07-2015
Messages : 464

Re : [Python]Jeu du Morpion solitaire

Salut, c'est bon j'ai testé ton programme^^ je le trouves bien fait bien que je ne sois pas fan du jeu en lui même.
Voila une version que j'avais fait il y a 2 ans environ:


from tkinter import *
def cercle(x, y, r, coul ='black'):
    "tracé d'un cercle de centre (x,y) et de rayon r"
    while r>1:
        cadre.create_oval(x-r, y-r, x+r, y+r, outline=coul)
        r-=3
def pion1(event):
    cercle(int(((event.x)//50+1)*50-25),int(((event.y)//50+1)*50-25),24,'blue')
    X1=int(((event.x)//50+1)*50-25)
    Y1=int(((event.y)//50+1)*50-25)
    global X2,Y2
    if X1==X2:
        cercle(X1,(Y1+Y2)/2,24,'light blue')
    if Y1==Y2:
        cercle(((X1+X2)/2),Y1,24,'light blue')
       
def pion2(event):
    cercle(int(((event.x)//50+1)*50-25),int(((event.y)//50+1)*50-25),24,'light blue')
    X2=int(((event.x)//50+1)*50-25)
    Y2=int(((event.y)//50+1)*50-25)
    global X2,Y2


fen=Tk()
cadre = Canvas(fen, width =350, height =350, bg ='light blue')
for a in range(100,300,50):
    cadre.create_line(0, a, 350, a, fill ='dark blue')
    cadre.create_line(a, 0, a, 350, fill ='dark blue')
cadre.create_line(50,100,50,250,fill='dark blue')
cadre.create_line(300,100,300,250,fill='dark blue')
cadre.create_line(100,50,250,50,fill='dark blue')
cadre.create_line(100,300,250,300,fill='dark blue')
cadre.create_line(100,350,250,350,fill='dark blue')
cadre.create_line(100,2,250,2,fill='dark blue')
cadre.create_line(2,100,2,250,fill='dark blue')
cadre.create_line(350,100,350,250,fill='dark blue')
def recommencer():
    for xx in range(0,400,50):
        for yy in range(100,250,50):
            cercle(xx-25,yy+25,24,'blue')
    for xx in range(100,250,50):
        for yy in range(0,400,50):
            cercle(xx+25,yy+25,24,'blue')
    cercle(175,175,24,'light blue')
recommencer()
bouton=Button(fen,text="recommencer",command=recommencer)
cadre.bind("<Button-1>", pion1)
cadre.bind("<Button-3>", pion2)
bouton.pack()
cadre.pack()
chaine = Label(fen)
chaine.pack()

fen.mainloop()


Alors, c'est à la confiance du joueur... clic droit pour lever un pion et clic gauche pour le poser, je sais pas si tu connais les règles mais les voici:
http://omegalima.free.fr/solitaire/regles.html

PS: petite erreur dans ton programme ligne 527.


La somme des inverses de la suite de Sylvester converge vers 1 plus vite que toute autre série somme infinie d'inverses d'entiers convergeant vers 1.

Hors ligne

#6 04-10-2015 19:52:30

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 13 774

Re : [Python]Jeu du Morpion solitaire

Re,

Oui, je connais...
Quelle erreur ?
ligne 527 du programme lui-même ou ligne 527 du code posté ?
Moi, je n'ai pas d'erreur, que ce soit sur mon portable en win 7 ou mon fixe en XP.
Je te concède que le jeu n'est pas passionnant : je l'avais écrit en Basic, il y a 30 ans...
Il ne vaut que par l'algorithme de gestion des traits :
tracé et interdictions de tracé...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#7 05-10-2015 16:06:11

Terces
Membre
Inscription : 16-07-2015
Messages : 464

Re : [Python]Jeu du Morpion solitaire

Re,
tu écrits ca dans ta dernière version ce qui provoque une erreur:

#Button(Fenetre,image=V,command=HB).grid(column=4, row=24)
#Button(Fenetre,image=G,command=HBE).grid(column=2, row=26)
B#utton(Fenetre,image=D,command=HBO).grid(column=4, row=26)

init_jeu(0)


La somme des inverses de la suite de Sylvester converge vers 1 plus vite que toute autre série somme infinie d'inverses d'entiers convergeant vers 1.

Hors ligne

#8 05-10-2015 19:02:18

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 13 774

Re : [Python]Jeu du Morpion solitaire

Salut,

Merci. Corrigé !
En fait chez moi, j'ai la version graphique : pas de # et les lignes avec texte supprimées...
Je posterai mes flèches et une version graphique propre...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

Réponse rapide

Veuillez composer votre message et l'envoyer
Nom (obligatoire)

E-mail (obligatoire)

Message (obligatoire)

Programme anti-spam : Afin de lutter contre le spam, nous vous demandons de bien vouloir répondre à la question suivante. Après inscription sur le site, vous n'aurez plus à répondre à ces questions.

Quel est le résultat de l'opération suivante (donner le résultat en chiffres)?
soixante deux moins quaranteneuf
Système anti-bot

Faites glisser le curseur de gauche à droite pour activer le bouton de confirmation.

Attention : Vous devez activer Javascript dans votre navigateur pour utiliser le système anti-bot.

Pied de page des forums