Menu

Slide puzzle

- - Dernière réponse :  Florine - 12 mai 2019 à 17:28
Bonjour,
Pour le bac, je dois programmer un slide puzzle et je souhaiterais l'intégrer à une frame déjà programmée sur un autre programme. Mais je n'y arrive pas...
#Création d'une huitième frame pour le puzzle
pagepuzzle=Frame(main,width=600,height=480,bg="dark slate gray")
pagepuzzle.forget()


De plus, après plusieurs essais, le programme ne semble pas fonctionner correctement car il semblerait que deux pièces du puzzle se soient inversée, et que sa résolution serait donc impossible. Or, je ne trouve pas où est le problème.
Pourriez-vous m'aider s'il vous plait? Je vous joint ci-dessous le programme du puzzle:

import random
import tkinter as tk
import tkinter.messagebox
from PIL import Image, ImageTk
from optparse import OptionParser


MAX_BOARD_SIZE = 550

class Application(self):

    def __init__(self, image, board_grid=4):

        pagepuzzle=tk.Frame.__init__(self)
        self.grid()
        self.board_grid = board_grid if board_grid > 2 else 3
        self.load_image(image)
        self.steps = 0
        self.create_widgets()
        self.create_events()
        self.create_board()
        self.show()

    def load_image(self, image):

        image = Image.open(image)
        board_size =min(image.size)
        
        if image.size[0] != image.size[1]:
            image = image.crop((0, 0, board_size,board_size))

        if board_size > MAX_BOARD_SIZE:
            board_size = MAX_BOARD_SIZE
            image = image.resize(board_size,board_size), Image.ANTIALIAS
        self.image = image
        self.board_size = board_size
        self.piece_size = self.board_size / self.board_grid

    def create_widgets(self):

        args = dict(width=self.board_size, height=self.board_size)
        self.canvas = tk.Canvas(self, **args)
        self.canvas.grid()

    #Définition permettant de faire bouger les pièces de puzzle
    def create_events(self):
        #Permet de coulisser vers le haut
        self.canvas.bind_all('<KeyPress-Up>', self.slide)
        #Permet de coulisser vers le bas
        self.canvas.bind_all('<KeyPress-Down>', self.slide)
        #Permet de coulisser vers la gauche
        self.canvas.bind_all('<KeyPress-Left>', self.slide)
        #Permet de coulisser vers la droite
        self.canvas.bind_all('<KeyPress-Right>', self.slide)
        #Permet de montrer à quoi le puzzle est sensé ressembler en cas de besoin d'aide
        self.canvas.bind_all('<KeyPress-H>', self.help)

    #Définition permettant de montrer à quoi le puzzle est sensé ressembler en cas de besoin d'aide
    def help(self, event):
        if getattr(self, '_img_help_id', None) is None:
            self._img_help = ImageTk.PhotoImage(self.image)
            self._img_help_id = self.canvas.create_image(0, 0,image=self._img_help, anchor=tk.NW)
        else:
            state = self.canvas.itemcget(self._img_help_id, 'state')
            state = 'hidden' if state == '' else ''
            self.canvas.itemconfigure(self._img_help_id, state=state)


    #Définition permettan de faire coulisser les pièces de puzzle en fonction de l'action du joueur
    def slide(self, event):
        pieces = self.get_pieces_around()

        if event.keysym in ('Up') and pieces['bottom']:
            self._slide(pieces['bottom'], pieces['center'],(0, -self.piece_size))

        if event.keysym in ('Down') and pieces['top']:
            self._slide(pieces['top'], pieces['center'],(0, self.piece_size))

        if event.keysym in ('Left') and pieces['right']:
            self._slide(pieces['right'], pieces['center'],(-self.piece_size, 0))

        if event.keysym in ('Right') and pieces['left']:
            self._slide(pieces['left'], pieces['center'],(self.piece_size, 0))

        self.check_status()


    def _slide(self,from_,to,coord):
        self.canvas.move(from_['id'], *coord)
        to['pos_a'], from_['pos_a'] = from_['pos_a'], to['pos_a']
        self.steps += 1

    def get_pieces_around(self):
        pieces = {'center': None,'right' : None,'left'  : None,'top'   : None,'bottom': None}

        for piece in self.board:
            if not piece['visible']:
                pieces['center'] = piece
                break
        x0, y0 = pieces['center']['pos_a']
        
        for piece in self.board:
            x1, y1 = piece['pos_a']

            if y0 == y1 and x1 == x0 + 1:
                pieces['right'] = piece

            if y0 == y1 and x1 == x0 - 1:
                pieces['left'] = piece

            if x0 == x1 and y1 == y0 - 1:
                pieces['top'] = piece

            if x0 == x1 and y1 == y0 + 1:
                pieces['bottom'] = piece
        return pieces


    def create_board(self):
        self.board = []

        for x in range(self.board_grid):
            for y in range(self.board_grid):
                x0 = x * self.piece_size
                y0 = y * self.piece_size
                x1 = x0 + self.piece_size
                y1 = y0 + self.piece_size
                image = ImageTk.PhotoImage(self.image.crop((x0, y0, x1, y1)))
                piece = {'id': None,'image': image,'pos_o': (x, y),'pos_a': None,'visible': True}
                self.board.append(piece)
        self.board[-1]['visible'] = False

    #Définition permettant de vérifier que le puzzle est réussi et afficher un message
    def check_status(self):
        for piece in self.board:
            if piece['pos_a'] != piece['pos_o']:
                return
                title = 'Bravo!'
                message = 'tu as résolu en %nbr de mvmnts!' % self.steps
                tkMessageBox.showinfo(title, message)

    
    def show(self):
        random.shuffle(self.board)
        index = 0

        for x in range(self.board_grid):
            for y in range(self.board_grid):
                self.board[index]['pos_a'] = (x, y)
                if self.board[index]['visible']:
                    x1 = x * self.piece_size
                    y1 = y * self.piece_size
                    image = self.board[index]['image']
                    id = self.canvas.create_image(x1, y1, image=image, anchor=tk.NW)
                    self.board[index]['id'] = id
                index += 1

if __name__ == '__main__':
    parser = OptionParser(description="Sliding puzzle")
    parser.add_option('-g', '--board-grid', type=int, default=4,help="(the minimum value is 3)")
    parser.add_option('-i', '--image', type=str, default='puzzlecarré.png',help="path to image")
    args, _ = parser.parse_args()

    if args.board_grid < 3:
        args.board_grid = 3
        print ("Warning: using 3 for board-grid")


    app = Application(args.image, args.board_grid)
    app.mainloop()

Afficher la suite 

Votre réponse

1 réponse

Messages postés
326
Date d'inscription
vendredi 25 septembre 2015
Statut
Membre
Dernière intervention
6 mai 2019
74
0
Merci
Bonjour,
pour mélanger le puzzle, vous faites simplement
random.shuffle(self.board)
donc c'est normal que le puzzle soit irrésoluble 1 fois sur 2.
Pour corriger le problème je vois 2 solutions :
1) Partir de la solution puis effectués plusieurs fois des mouvements valides aléatoires
2) Mélanger aléatoirement comme vous le faite déjà puis vérifier avec un algo que la position peut être résolue. Si ce n'est pas le cas, inversez 2 cases aléatoirement.

La deuxième solution a plusieurs avantages mais elle est surement plus compliquée.
Et comment puis-je faire la meilleure solution ? Je débute et je ne vois pas du tout comment faire...
quent217
Messages postés
326
Date d'inscription
vendredi 25 septembre 2015
Statut
Membre
Dernière intervention
6 mai 2019
74 -
La méthode pour savoir si la position peut être résolue est expliquée sur la page wikipédia du jeu de taquin.
J'ai étudier la page wikipedia du jeu taquin ainsi que d'autres sites et je ne parviens toujours pas à créer un algorithme vérifiant la possibilité de résolution du puzzle...
Vous pourriez m'aider ? Je doit rendre mon projet dans pas longtemps et ce puzzle est très important dans mon jeu...
Commenter la réponse de quent217