Disparition blocs jeu de 2048 python

Résolu
Louis - 11 juin 2023 à 20:51
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 - 24 juin 2023 à 18:06

Bonjour,

Je suis en train de coder un jeu de 2048 en python, j'ai fini mon code sauf que quand je l’exécute, tout se passe bien jusqu'à que certains blocs disparaissent quand j'effectue un déplacement. Je ne comprends pas d'ou vient le problème, merci d'avance

Voici mon code :

from tkinter import *
from random import *
import copy

def droite(event):
    global temp,grille
    temp = copy.deepcopy(grille)
    for i in range(4):
        for j in range(-1,-5,-1):
            if grille[i][j] == 0: pass
            else:
                non_vide = grille[i][j]
                for k in range(j+5,4):
                    if grille[i][k] == 0:
                        grille[i][k] = non_vide
                        grille[i][k-1] = 0
                        widgets[str(i)+str(k)].config(text=non_vide,bg=couleurs[str(non_vide)],font=('Times New Roman',9))
                        widgets[str(i)+str(k-1)].config(text='',bg='white')
                    elif grille[i][k] == non_vide:
                        grille[i][k] = non_vide*2
                        grille[i][k-1] = 0
                        widgets[str(i)+str(k)].config(text=non_vide*2,bg=couleurs[str(non_vide*2)],font=('Times New Roman',9))
                        widgets[str(i)+str(k-1)].config(text='',bg='white')
    if temp != grille:
        generator()

def gauche(event):
    global temp,grille
    temp = copy.deepcopy(grille)
    for i in range(4):
        for j in range(4):
            if grille[i][j] == 0: pass
            else:
                non_vide = grille[i][j]
                for k in range(j-5,-5,-1):
                    if grille[i][k] == 0:
                        grille[i][k+4] = non_vide
                        grille[i][k+5] = 0
                        widgets[str(i)+str(k+4)].config(text=str(non_vide),bg=couleurs[str(non_vide)],font=('Times New Roman',9))
                        widgets[str(i)+str(k+5)].config(text='',bg='white')
                    elif grille[i][k] == non_vide:
                        grille[i][k+4] = non_vide*2
                        grille[i][k+5] = 0
                        widgets[str(i)+str(k+4)].config(text=str(non_vide*2),bg=couleurs[str(non_vide*2)],font=('Times New Roman',9))
                        widgets[str(i)+str(k+5)].config(text='',bg='white')
    if temp != grille:
        generator()

def haut(event):
    global temp,grille
    temp = copy.deepcopy(grille)
    for i in range(4):
        for j in range(4):
            if grille[i][j] == 0: pass
            else:
                non_vide= grille[i][j]
                for k in range(i-5,-5,-1):
                    if grille[k][j] == 0:
                        grille[k+4][j] = non_vide
                        grille[k+5][j] = 0
                        widgets[str(k+4)+str(j)].config(text=str(non_vide),bg=couleurs[str(non_vide)],font=('Times New Roman',9))
                        widgets[str(k+5)+str(j)].config(text='',bg='white')
                    elif grille[k][j] == non_vide:
                        grille[k][j] = non_vide*2
                        grille[k+1][j] = 0
                        widgets[str(k+4)+str(j)].config(text=str(non_vide*2),bg=couleurs[str(non_vide*2)],font=('Times New Roman',9))
                        widgets[str(k+5)+str(j)].config(text='',bg='white')
    if temp != grille:
        generator()

def bas(event):
    global temp,grille
    temp = copy.deepcopy(grille)
    for i in range(-1,-5,-1):
        for j in range(4):
            if grille[i][j] == 0: pass
            else:
                non_vide= grille[i][j]
                for k in range(i+5,4):
                    if grille[k][j] == 0:
                        grille[k][j] = non_vide
                        grille[k-1][j] = 0
                        widgets[str(k)+str(j)].config(text=str(non_vide),bg=couleurs[str(non_vide)],font=('Times New Roman',9))
                        widgets[str(k-1)+str(j)].config(text='',bg='white')
                    elif grille[k][j] == non_vide:
                        grille[k][j] = non_vide*2
                        grille[k-1][j] = 0
                        widgets[str(k)+str(j)].config(text=str(non_vide*2),bg=couleurs[str(non_vide*2)],font=('Times New Roman',9))
                        widgets[str(k-1)+str(j)].config(text='',bg='white')
    if temp != grille:
        generator()

def generator():
    while True:
        a,b = randint(0,3),randint(0,3)
        if grille[a][b] == 0:
            break
    num = choice([4,2,2,2,2])
    grille[a][b] = num
    widgets[str(a)+str(b)].config(text=num,bg=couleurs[str(num)])
    return

def retourfonction(event):
    global grille,temp
    grille = copy.deepcopy(temp)
    for ligne in range(3):
        for case in range(3):
            if grille[ligne][case] != 0:
                widgets[str(ligne)+str(case)].config(text=str(grille[ligne][case]),bg=couleurs[str(grille[ligne][case])],font=('Times New Roman',9))
            elif grille[ligne][case] == 0:
                widgets[str(ligne)+str(case)].config(text="",bg=couleurs[str(grille[ligne][case])],font=('Times New Roman',9)) 




widgets = {}

##Création des élements Tkinter
root = Tk()
case00=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case00.grid(row=1,column=0)
widgets["00"]=case00

case01=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case01.grid(row=1,column=1)
widgets["01"]=case01

case02=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case02.grid(row=1,column=2)
widgets["02"]=case02
 
case03=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case03.grid(row=1,column=3)
widgets["03"]=case03
 
case10=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case10.grid(row=2,column=0)
widgets["10"]=case10
 
case11=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case11.grid(row=2,column=1)
widgets["11"]=case11
 
case12=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case12.grid(row=2,column=2)
widgets["12"]=case12
 
case13=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case13.grid(row=2,column=3)
widgets["13"]=case13
 
case20=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case20.grid(row=3,column=0)
widgets["20"]=case20
 
case21=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case21.grid(row=3,column=1)
widgets["21"]=case21
 
case22=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case22.grid(row=3,column=2)
widgets["22"]=case22
 
case23=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case23.grid(row=3,column=3)
widgets["23"]=case23
 
case30=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case30.grid(row=4,column=0)
widgets["30"]=case30
 
case31=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case31.grid(row=4,column=1)
widgets["31"]=case31
 
case32=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case32.grid(row=4,column=2)
widgets["32"]=case32
 
case33=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
case33.grid(row=4,column=3)
widgets["33"]=case33

retour = Button(root,text="\u21b6",font=('Times New Roman',30))  #\u21ba fleche recomencer
retour.grid(column=2,row=0)

nom=Label(root,text="2048",font=('Times New Roman',50))
nom.grid(row=0,column=0)

root.bind("<Key-Left>",gauche)
root.bind("<Key-Right>",droite)
root.bind("<Key-Up>",haut)
root.bind("<Key-Down>",bas)
retour.bind("<Button-1>",retourfonction)

## Affectation des variables
couleurs = {"0":"#ffffff","2":"#eee4da","4":"#ede0c8","8":"#f2b179","16":"#f59563","32":"#f67c5f","64":"#f65e3b","128":"#eccf71","256":"#eecc62","512":"#edc950","1024":"#eec340","2048":"#edc12d","4096":"#ff3d3d"
            ,"8192":"#000000","16384":"#000000","32768":"#000000","65536":"#000000","131072":"#000000"}
grille = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]


## Génération de deux nombres sur la grille
num1 = choice([4,2,2,2,2])
a1,b1= randint(0,3),randint(0,3)
grille[a1][b1] = num1
widgets[str(a1)+str(b1)].config(text=num1,bg=couleurs[str(num1)])
while True:
    a,b = randint(0,3),randint(0,3)
    if grille[a][b] == 0:
        break
num = choice([4,2,2,2,2])
grille[a][b] = num
widgets[str(a)+str(b)].config(text=num,bg=couleurs[str(num)])
temp=grille

mainloop()


Windows / Firefox 114.0

A voir également:

6 réponses

Salut.

Ton code demande à être revu, notamment :

Utiliser une fonction générique pour les fonctions droite, gauche, haut, bas qui font sensiblement la même chose.

Utiliser une liste au lieu de n variables case00, ..., case32

Ne pas oublier que dans un range, le stop n'est pas un inclus, donc dans ta fonction retourfonction, le stop des range devraient être à 4, et non 3.

les

if grille[i][j] == 0: pass

ne servent strictement à rien, autant simplement faire

if grille[i][j]:
    # mettre le code du else

Pourquoi avoir utiliser un dict pour widgets au lieu d'un tableau de list comme pour grille ?
Cela éviterait tout ces transtypages inutiles.

Sans doute que ce que j'ai énuméré ne résout pas ton problème, mais en revoyant ton code et suivant ces conseils, peut aider à identifier d'où provient ton souci.

0

Je vais faire ça merci :)

Pour la fonction générique je ne vois pas comment faire étant donné que je parcours la liste différement en fonction du déplacement : de -1 à -4 pour droite, de 0 à 3 pour gauche...

"Utiliser une liste au lieu de n variables case00, ..., case32"

-> Pour la liste au lieu des variables je n'ai pas vraiment compris ce que tu voulais dire étant donné que c'est des labels tk

Et pour les range(3) je sais que le stop n'est pas inclus j'avais juste fait une erreur :/

Edit : J'ai trouvé le problème il suffisait de mettre cela :

def bas(event):
    global temp,grille
    temp = copy.deepcopy(grille)
    for i in range(-1,-5,-1):
        for j in range(4):
            if grille[i][j]:
                non_vide= grille[i][j]
                for k in range(i+5,4):
                    if grille[k][j] == 0:
                        grille[k][j] = non_vide
                        grille[k-1][j] = 0
                        widgets[str(k)+str(j)].config(text=str(non_vide),bg=couleurs[str(non_vide)],font=('Times New Roman',9))
                        widgets[str(k-1)+str(j)].config(text='',bg='white')
                    elif grille[k][j] == non_vide:
                        grille[k][j] = non_vide*2
                        grille[k-1][j] = 0
                        widgets[str(k)+str(j)].config(text=str(non_vide*2),bg=couleurs[str(non_vide*2)],font=('Times New Roman',9))
                        widgets[str(k-1)+str(j)].config(text='',bg='white')
                    else:
                        break
    if temp != grille:
        generator()

J'ai rajouté le else : break qui permet que le programme arrête de parcourir la ligne si le bloc à coté de lui n'est pas un 0 ou alors n'est pas le même chiffre

0
yg_be Messages postés 22731 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2024 1 477
Modifié le 12 juin 2023 à 11:42

bonjour,

voici un exemple que ton programme ne calcule pas correctement:

Si la grille contient

[[8, 4, 4, 4], [4, 8, 16, 8], [2, 0, 0, 2], [0, 4, 0, 0]]

et que l'utilisateur choisit de monter, ton programme calcule
 [[8, 8, 4, 4], [4, 0, 16, 8], [2, 4, 0, 2], [0, 0, 0, 2]]

ce qui est faux.

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 13 juin 2023 à 17:34

Bonjour,

Pour la liste au lieu des variables je n'ai pas vraiment compris ce que tu voulais dire étant donné que c'est des labels tk

En fait, tu aurais pu raccourcir ton code comme ceci:

widgets = {}
case = {}

for k in range(4):
    case[k]=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
    case[k].grid(row=1,column=k)
    widgets[k]=case[k]

Idem pour case10, case11, case12, case13, etc..

0
yg_be Messages postés 22731 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2024 1 477
13 juin 2023 à 19:28

Les variables case.. sont inutiles.

for j in range(4):
    for k in range(4):
        widgets[(k,j)]=Label(root,text="",relief=RAISED,borderwidth=1,width=23, height=11,bg='white',font=('Times New Roman',9))
        widgets[(k,j)].grid(row=k+1,column=j)
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178 > yg_be Messages postés 22731 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2024
14 juin 2023 à 10:09

Bonjour,

Oui,, en rédigeant ma réponse, je me demandais pour quoi cette variable widgets

alors que l'on a déjà le dictionnaire case ...

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178 > Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024
15 juin 2023 à 11:20

ca réduit considérablement la longueur du code, et de plus les lignes

widgets[str(k)+str(j)].config(......

s'écrivent plus simplement:

widgets[(k,j)].config(.....
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
24 juin 2023 à 08:47

Bonjour Louis,

Une version sans toute cette série de labels, mais avec un Canvas sur lequel on trace

une grille et des chiffres:

# -*- coding:Utf-8 -*-

import random
from tkinter import *
from tkinter import messagebox

def move_line(patterns_r, line):
    ''' Déplace tout '''

    line_pat = ''
    for k in range(SIZE):
        s = '0' if(line[k] == 0) else 'x'
        line_pat += s

    pattern = patterns_r[patterns.index(line_pat)]
    n_line = [0,0,0,0]
    n = -1
    for k in range(SIZE):
        if(pattern[k] != '0'):
            for j in range(SIZE):
                if(j > n and line[j] != 0):
                    n_line[k] = line[j]
                    n = j
                    break

    for k in range(SIZE): line[k] = n_line[k]

    return(line)

def add_figures(line):
    ''' Additionne les chiffres contigus identiques '''

    for k in range(SIZE-1):
        if(line[k] != 0):
            if(line[k+1] == line[k]):
                line[k+1] *= 2
                line[k] = 0

    return(line)

def move_all(evt, delta_r, delta_c, grid):
    ''' Déplace tout suivant la direction choisie '''

    if(delta_r > 0 or delta_c > 0):
        patterns_r = patterns_plus
    elif(delta_r < 0 or delta_c < 0):
        patterns_r = patterns_minus

    if(delta_c != 0): # déplacement horizontal
        for row in range(SIZE):
            line = []
            for col in range(SIZE): line.append(grid[row][col])
            if(0 in line): line = move_line(patterns_r, line)
            line = add_figures(line)
            if(0 in line): line = move_line(patterns_r, line)
            for k in range(SIZE): grid[row][k] = line[k]
    elif(delta_r != 0): # déplacement vertical
        for col in range(SIZE):
            line = []
            for row in range(SIZE): line.append(grid[row][col])
            if(0 in line): line = move_line(patterns_r, line)
            line = add_figures(line)
            if(0 in line): line = move_line(patterns_r, line)
            for k in range(SIZE): grid[k][col] = line[k]

    #Ajoute un 2 dans une case au hasard
    t = 99
    while(t != 0):
        r, c = random.randint(0, SIZE-1), random.randint(0, SIZE-1)
        t = grid[r][c]

    grid[r][c] = 2
    display_grid(grid)

def coords_from_row_col(row,col):
    ''' Retourne les coordonnées du centre de la case en fonction des no de colonne et de ligne '''

    x1,y1 = x0+SQUARE*col, y0+SQUARE*row
    x2,y2 = x1+SQUARE, y1+SQUARE
    xc,yc = x1+(x2-x1)/2, y1+(y2-y1)/2

    return(xc,yc)

def display_empty_grid():
    ''' Affiche la grille vide '''

    graph_area.delete('all')
    graph_area.create_rectangle(x0, y0, x0+SIZE*SQUARE, y0+SIZE*SQUARE, width = _width, outline = col)

    for k in range(1,SIZE):
        graph_area.create_line(x0+k*SQUARE, y0, x0+k*SQUARE, y0+SIZE*SQUARE, width = _width, fill = col)
        graph_area.create_line(x0, y0+k*SQUARE, x0+SIZE*SQUARE, y0+k*SQUARE, width = _width, fill = col)

def display_grid(grid):
    ''' Affiche la grille avec les chiffres '''

    display_empty_grid()
    for row in range(SIZE):
        for col in range(SIZE):
            xc,yc = coords_from_row_col(row, col)
            t = '' if(grid[row][col] == 0) else str(grid[row][col])
            graph_area.create_text(xc, yc, text = t, fill = 'chocolate1', font = ('bold'))

def init_grid(grid):
    ''' Initialise la grille avec 2 chiffres 2 au hasard '''

    r, c1 = random.randint(0, SIZE-1), random.randint(0, SIZE-1)
    grid[r][c1] = 2

    c2 = c1
    while(c2 == c1): c2 = random.randint(0, SIZE-1)
    grid[r][c2] = 2

WIDTH, HEIGHT = 330, 330
SIZE, SQUARE = 4,70
x0, y0 = 10,10
col, _width = 'green2', 5
grid = [[0 for j in range(SIZE)] for k in range(SIZE)]
patterns = ['xxxx','0000', 'x0xx', '0xxx', '00xx', '000x', 'xxx0', 'xx00', 'x000', 'x0x0', '0x0x', '0xx0', 'x00x', '00x0', '0x00', 'xx0x']
patterns_plus =  ['xxxx','0000', '0xxx', '0xxx', '00xx', '000x', '0xxx', '00xx', '000x', '00xx', '00xx', '00xx', '00xx', '000x', '000x', '0xxx']
patterns_minus = ['xxxx','0000', 'xxx0', 'xxx0', 'xx00', 'x000', 'xxx0', 'xx00', 'x000', 'xx00', 'xx00', 'xx00', 'xx00', 'x000', 'x000', 'xxx0']

main_win = Tk()
main_win.geometry(str(WIDTH)+'x'+str(HEIGHT)+'+600+50')
main_win.title('2048')
main_win.bind("<Key-Left>", lambda evt, r=0, c=-1, g=grid: move_all(evt, r, c, g))
main_win.bind("<Key-Right>", lambda evt, r=0, c=1, g=grid: move_all(evt, r, c, g))
main_win.bind("<Key-Up>", lambda evt, r=-1, c=0, g=grid: move_all(evt, r, c, g))
main_win.bind("<Key-Down>", lambda evt, r=1, c=0, g=grid: move_all(evt, r, c, g))

graph_area = Canvas(main_win, width = WIDTH-30, height = HEIGHT-30, bg = 'ivory')
graph_area.place(x=10, y = 10)

init_grid(grid)
display_grid(grid)

main_win.mainloop()
0
yg_be Messages postés 22731 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 27 avril 2024 1 477
24 juin 2023 à 09:09

Intéressant la généralisation du move, avec move_all(().

Dommage le programme n'applique pas les mêmes règles que le programme d'origine.  Vois les lignes 90 et 91 du programme d'origine.  Il ne faut ajouter une valeur (soit un 2, soit un 4) que si il y a eu un changement effectif.

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 24 juin 2023 à 11:23

Bonjour yg_be,

Oui, tu as raison, je connaissais le jeu mais je n'y avais jamais joué, et donc,

ce que tu vois ici, c'est ce que j'en ai compris (sans vraiment approfondir  :-)  :-) )

En tout cas, le principe est là

0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
24 juin 2023 à 18:06

J'ai donc ajouté ceci:

en début de fonction move_all()

    screenshot = copy.deepcopy(grid)

et en fin de fonction:

    if(screenshot != grid):
        possible_nb = [2,4]
        nb = random.choice(possible_nb)
        content = 99
        while(content != 0):
            r, c = random.randint(0, SIZE-1), random.randint(0, SIZE-1)
            content = grid[r][c]
	
        grid[r][c] = nb
0