if 0 { <> ---- **Introduction** [HJG] 2016-02-16: There is a 15-puzzle in the Tk-demo. It uses [button]s for the tiles and [place] to move the buttons around. Other variants here on the wiki are [The Classic 15 Puzzle] and [N-puzzle], but they are quite lengthy. <
> Both programs use numbers - it would be nice to have a variant that can use other symbols and/or a sliced-up picture. Currently, there is a draft-task for the 15-puzzle at http://rosettacode.org/wiki/15_Puzzle_Game%|%rosettacode%|%, so to fill in an entry for tcl, <
> I wanted a fairly short and simple version of that puzzle. Starting with the layout from [A small calculator], I'm using a [grid] of buttons here, <
> and moving around the text on the buttons. <
> Also, there is only a limited number of canned puzzles (as in "1" :). } ---- **Code** ======tcl # 15puzzle_05.tcl - HaJo Gurt - 2016-02-16 # http://wiki.tcl.tk/14403 # 15-Puzzle - with grid, buttons and colors package require Tk set progVersion "15-Puzzle v0.15"; # 2016-02-17 global msg Moves set msg " " set Moves 0 set Keys { 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44 } set Goa1 { A B C D E F G H I K L M N O P _ }; # Rows LTR / 1:E : 108 set Goa2 { A E I N B F K O C G L P D H M _ }; # Cols forw. / 1:M : 114 #set Goa3 { A M L K B N _ I C O P H D E F G }; # Spiral CCW / 0 : 121 #set Goa4 { A B C D M N O E L _ P F K I H G }; # Spiral CW1 / 0 : 154 set Puz1 { A B C D E F G H I K L M N O P _ }; # solved set Puz2 { C A F B E G P N D L H I O K M _ }; # from Tk-demo set PuzT { T h e F i f t e e n P u z z l e }; # Title set GoaT { x x x F i f t e e n x x x x x x }; # title-highlight set Puzz $PuzT set Goal $GoaT #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+--- proc Move {k} { # find key with the empty space: set e -1 foreach p $::Keys { set t [.key$p cget -text] if { $t eq "_" } { set e $p } } if {$e < 0} {return 0}; # no empty tile found set t [.key$k cget -text] .key$e config -text $t #-state active #-state normal #-relief raised .key$k config -text "_"; # -background gray return 1 } proc Check {} { set ok 0 set i 0 foreach k $::Keys { set t [.key$k cget -text] set g [lindex $::Goal $i] incr i .key$k config -background white if { $t eq $g } { .key$k config -background lightgreen; incr ok } #lime : only in Tcl/Tk 8.6 if { $t eq "_" } { .key$k config -background gray } #-relief sunken -state disabled } update if { $ok > 15 && $::Moves > 0} { foreach k $::Keys { .key$k flash; bell; } } } proc Click {k} { set ::msg "" set val [.key$k cget -text] set ok [Move $k] incr ::Moves $ok wm title . "$::Moves moves" Check } proc New15 {P} { if { $P == 1} { set ::Puzz $::Puz1 set ::Goal $::Goa1 } else { set ::Puzz $::Puz2 set ::Goal $::Goa1 } if { $P == 0} { set ::Puzz $::PuzT set ::Goal $::GoaT } set ::Moves 0 set i 0 foreach k $::Keys { set t [lindex $::Puzz $i] incr i .key$k config -text $t -background white; # white } set ::msg "New game" wm title . $::msg Check } #button .quit -text "Off" -fg red -command exit button .newB -text "Reset" -fg blue -command {New15 1} button .newA -text "New Game" -fg red -command {New15 2} foreach k $::Keys { button .key$k -text "$k" -width 4 -command "Click $k" } grid .newB x .newA -sticky nsew grid .key11 .key12 .key13 .key14 -sticky nsew -padx 2 -pady 2 grid .key21 .key22 .key23 .key24 -sticky nsew -padx 2 -pady 2 grid .key31 .key32 .key33 .key34 -sticky nsew -padx 2 -pady 2 grid .key41 .key42 .key43 .key44 -sticky nsew -padx 2 -pady 2 grid configure .newA -columnspan 2 -padx 4 grid configure .newB -columnspan 2 -padx 4 New15 0 wm title . $progVersion focus -force . #wm resizable . 0 0 ====== ---- **Comments** [HJG] The game is working, but there is no check yet if the clicked button is next to the empty tile. I wanted to take care of that with '-state disabled' / '-state normal', but doing that resulted in some strange effects... Also, the buttons for new game etc. are not final. ---- '''See also:''' * [The Classic 15 Puzzle] - [N-puzzle] * http://migo.sixbit.org/puzzles/fifteen%|%Fifteen puzzle online%|% (JavaScript) * ... <> Application | Games | GUI