5
\$\begingroup\$

I'm a hobbyist programmer(just having fun) created a small script that takes a photo and resizes it, then cuts it up into 24 pieces. The chunks are transposed and made into buttons. Your task is to get it back to it's original state without out going negative on points. My questions are: was it fun? Could you play it on windows or iso platforms?

from PIL.ImageTk import Image, PhotoImage
from PIL import ImageChops
from tkinter import (Canvas,Tk,Frame,Button,YES,BOTH,filedialog,
                     Toplevel,IntVar,Label)
from tkinter.messagebox import showinfo, showerror
import logging
from random import  choice
from functools import partial

#logging.basicConfig(level= logging.DEBUG)
logging.disable(logging.CRITICAL)

class Puzzle_One(Frame):
    """Grab a picture, then cuts it up into 24 pieces and transpose,
       make them into buttons. Repeatedly pressing the buttons to it's
       origional state before getting a negative score."""
    def __init__(self, parent=None):
        self.parent= parent
        Frame.__init__(self, self.parent)
        self.pack(expand=YES, fill=BOTH)
        
        self.canvas= Canvas(self)
        self.canvas.config(width= 800, height= 700, bg='gray90')
        self.canvas.pack(expand=YES, fill=BOTH)
        
        self.puzzle_points= IntVar()
        self.lbl_1= Label(self.canvas, textvariable=self.puzzle_points,
                          font=('arial',50,'bold'))
        self.lbl_1.place(x=500,y=30)
        self.puzzle_points.set(2500)
        
        
        self.btn= Button(self.canvas, text='find image',
                         command= self.get_image)
        self.btn.place(x=400,y=600)       
        
        self.buttons= []
        self.image_ref= []
        
        self.transitions= [ Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM,
                            Image.ROTATE_180, Image.ROTATE_270,
                            Image.ROTATE_90]
        self.t_count=0
        self.t_pics=[]
        self.buttons= []
        self.image_compare= []
        self.mydict= {}
        
        
        
    def get_image(self):
        """Find your photo, it will be displayed on the canvas as a reference.
           A new button will be made to create the puzzle"""
        self.btn.config(state='disabled')
        self.file= filedialog.askopenfilename(filetypes=[('PNG','.png'),
                                                         ('JPG','.jpg'),
                                                         ('GIF','.gif'),
                                                         ]
                                              )
        self.image= Image.open(self.file)
        self.im= self.image.resize((600,400))
        image= PhotoImage(self.im)
        
        self.canvas.create_image(360,320,image=image,tag='my_image')
        
        self.t_pics.append(image)
        self.btn2= Button(self.canvas,text='make puzzle',
                          command=self.make_puzzle)
        self.btn2.place(x=200,y=600)   
      

    def rotate_btn(self,pic_name, index):
        """Reapeatedly pressing the image buttons scrolls through a list of
           image transitions. Find the correct position"""
        if self.t_count >4:
            self.t_count =0        
        
        img= pic_name.transpose(self.transitions[self.t_count])
        self.mydict[index]= img
        image= PhotoImage(image=img)
        
        self.buttons[index].config(image=image)
        
        self.t_pics.append(image)
        self.t_count +=1
    def compare(self):
        """Compares the puzzle button with the original. Numbering starts
           in the upper left corner with 0, lower right corner is 23.
           Need a better way to indicate which buttons image is incorrect.
           Updating the score
           """
        points= self.puzzle_points.get()
        res= []
        for num in range(0,24):
            image_1= self.image_compare[num]
            image_2= self.mydict.get(num, '')
            diff= ImageChops.difference(image_1,image_2)
            
            if diff.getbbox():
                pts= points- 500
                if pts < 0:
                    self.puzzle_points.set(pts)
                    self.buttons[num].config(borderwidth=10)
                    
                    txt= 'Your total points is {}'.format(pts)
                    showinfo('Loss',txt)
                    
                    self.buttons[num].config(borderwidth=2)
                    self.btn3.config(state='disabled')
                    break
                else:
                    self.puzzle_points.set(pts)
                    self.buttons[num].config(borderwidth=10)
                    
                    text_= "There's an error {}".format(num)                
                    showerror('No bueno', text_)
                    
                    self.buttons[num].config(borderwidth=2)
                    
                    break
            
            else:
                res.append(num)
        
        if len(res) == 24:
            total= self.puzzle_points.get()
            text='Winner your total points are {}'.format(total)
            showinfo('Win', text)
            self.btn3.config(state='disabled')
        
        
    def make_puzzle(self):
        """A popup window containing 24 buttons. x1,y1,x2,y2 are the position of the cut pieces
           of the image. A reference of each region is transposed and converted to a Tk image,
           then saved to a list to prevent being garbage collected. Passing the region of each
           image and the index as an argument for each button. The buttons are in a list so they
           can be accessed by the index."""
        self.btn3= Button(self.canvas, text='I solved it!',
                          command=self.compare)
        self.btn3.place(x=600,y=600)
        self.btn2.config(state='disabled')
        self.top= Toplevel()
        x1=0
        y1=0
        x2=100
        y2=100
        count=0
        b_count=0
        for r in range(1,5):
            for c in range(1,7):               
                box= x1,y1,x2,y2
                reg= self.im.crop(box)
                self.image_compare.append(reg)
                tran= choice(self.transitions)
                reg= reg.transpose(tran)
                self.mydict[b_count]= reg
                image= PhotoImage(reg)
                self.buttons.append(Button(self.top,image=image,
                                           command=partial(self.rotate_btn,reg,b_count))
                                    )
                
                self.buttons[-1].grid(row=r,column=c,padx=0.5,pady=0.5)
                self.image_ref.append(image)
                if count == 5:
                    count= 0
                    b_count +=1
                    x1 = 0
                    y1 += 100
                    x2= 100
                    y2 += 100
                else:
                    x1 +=100
                    x2 +=100
                    count +=1
                    b_count +=1
                    
                
if __name__ == '__main__':
    root= Tk()
    Puzzle_One(root)
    root.mainloop()
\$\endgroup\$
0
\$\begingroup\$

Nice game and great work, my daughter likes it!

It worked running on Windows. On completing the puzzle I was unable to select another picture and play again. I think this can be easily implemented by adding a method play_game(self) that takes the overall control of the game and will have a quit button.

A follow up puzzle would be to hustle the picture elements where you have to put them in the right order.

Then a suggestion, you can try to implement the same game in PyQt5. Personally I like this GUI better than tkinter.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.