[Tutor] 15 puzzle

Michael P. Reilly arcege@speakeasy.net
Tue, 8 May 2001 15:58:40 -0400 (EDT)


Maritza Rodriguez wrote
> 
> This is what I have so far.  The program now exits the program by pressing 
> the "DONE" button, which is great.  But, what I also want that button to do 
> is tell you whether or not you have a solution to the puzzle, just before it 
> exits.  Of course, first I have to figure out how to scramble the buttons in 
> order to have an actual game going.  Any suggestions?
> 
> Maritza
> 
> import sys
> from Tkinter import *
> 
> def die(event=0):
>     sys.exit(0)
> 
> class Puzzle:
>     def __init__(self,w):
>         names=["1","2","3","4","5","6","7","8","9","10","11","12","13","14",
>         "15"," "]
>         n = 0
>         for i in range(4):
>             for j in range(4):
>                 item1=Button(w,text=names[n])
>                 item1.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item2=Button(w,text=names[n])
>                 item2.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item3=Button(w,text=names[n])
>                 item3.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item4=Button(w,text=names[n])
>                 item4.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item5=Button(w,text=names[n])
>                 item5.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item6=Button(w,text=names[n])
>                 item6.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item7=Button(w,text=names[n])
>                 item7.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item8=Button(w,text=names[n])
>                 item8.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item9=Button(w,text=names[n])
>                 item9.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item10=Button(w,text=names[n])
>                 item10.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item11=Button(w,text=names[n])
>                 item11.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item12=Button(w,text=names[n])
>                 item12.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item13=Button(w,text=names[n])
>                 item13.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item14=Button(w,text=names[n])
>                 item14.grid(row=i,column=j,sticky=E+W+N+S)
> 
>                 item15=Button(w,text=names[n])
>                 item15.grid(row=i,column=j,sticky=E+W+N+S)
>                 n = n+1
> 
> 
> 	f = Frame(w)
>         b1=Button(f,text="SCRAMBLE")
>         b2=Button(f,text="DONE")
>         if "DONE":
>             b2["command"] = die
>         b1.pack(side=LEFT)
>         b2.pack(side=RIGHT)
>         f.grid(row=4,column=0,columnspan=4)

Add a new method to check the table against the "solution".

    solution = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
      "12", "13", "14", "15", " "]
    # I would even make 'self.names = self.solution[:]' in __init__

    def solved(self):
        return self.names == self.solution

Then make a method to handle the button presses:
    def is_it_really_solved(self):
        import Dialog
        if self.solved:
          Dialog.Dialog(self, {'title': 'Congratulations',
                         'text': 'You solved the puzzle!',
                         'bitmap': Dialog.DIALOG_ICON,
                         'default': 0,
                         'strings': ('Ok',))
          self.quit()  # stop Tkinter
        else:
          Dialog.Dialog(self, {'title': 'Sorry',
                               'text': 'Keep trying',
                               'bitmap': Dialog.DIALOG_ICON,
                               'default': 0,
                               'strings': ('Ok',))
[There are better dialog widgets, but this is one I remember without much
reference material right now... and it works]

Then for the blocks, you just need to keep track of the buttons, and
make commands for them:
    def makebuttons(self, w):
        self.buttons = [None] * 16
        for i in range(4):
            for j in range(4):
                pos = i + j * 4
                name = self.names[pos]
                b = Button(w, text=name,
                    command=lambda self=self, pos=(i, j): self.buttonpress)
                self.buttons[pos] = b

    def buttonpress(self, position):
        (i, j) = pos
        # find which surrounding button is "blank" and change around
        # self.names and the text label for the proper buttons in
        # self.buttons
        # [Leave this as an exercise for you :)]

> 
> root=Tk()
> 
> 
> gr=Toplevel(root)
> gr.title("15-PUZZLE")
> grc = Puzzle (gr)
> 
> 
> root.withdraw()
> root.mainloop()
> 
> 
> _________________________________________________________________
> Get your FREE download of MSN Explorer at http://explorer.msn.com
> 
> 
> _______________________________________________
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
> 


-- 
+----------------------------------+-----------------------------------+
| Michael P. Reilly                | arcege@speakeasy.net              |