#---------------------------------------------------------------------- # Hanoing puzzle. # Fernando Rodriguez Villegas. # Math, puzzles and computers, Spring 2003. # University of Texas at Austin. # # In a unix shell this program runs with the command # wish hanoing.tcl #---------------------------------------------------------------------- # n is the number of buttons on the puzzle, set to 5 by default. set n 5 # colors is the list of colors the buttons can have (in an arbitrary but fixed # cyclic ordering) set colors {"white" "red" "blue"} # This bit of code creates the frame on which the buttons are going to # be placed. frame .f grid .f -row 1 -column 0 -columnspan 8 #---------------------------------------------------------------------- # First we put in 3 buttons called e, r and d; e, contains the value # of n, which can be changed by the user (though at this point # decreasing n doesn't work very well); r, is bound to the command # Reset (defined below), which creates the colored buttons of the # puzzle; and d, simply quits the whole thing. entry .f.e -width 3 -textvariable n button .f.r -text "reset" -command Reset button .f.d -text "dismiss" -command "destroy ." # We now place these buttons on the frame. set i 0 foreach p {e r d} { grid .f.$p -row 1 -column [expr 2*$i] -columnspan 2 incr i } #---------------------------------------------------------------------- # The process Reset (re-)initializes the puzzle. proc Reset {} { global n colors for {set i 1} {$i <= $n} {incr i} { # We choose a random color from the list of colors. The whole # expression [expr {round(3*rand()-.5)}] simply returns a random # choice of number 0, 1 or 2 set color [lindex $colors [expr {round(3*rand()-.5)}]] # This kills the $i-th button if it exists; we need it to redefine the # button. if {[winfo exists .b$i]} { destroy .b$i } # We create the $i-th button of the color we picked above (both when # by itself and when the cursor is over it) and is bound to the # command Do $i; i.e. when the user clicks this button the process Do # runs with this value of $i. button .b$i -height 2 -width 2 -background $color -activebackground $color -command "Do $i" grid .b$i -row 0 -column [expr {$i - 1}] } } #---------------------------------------------------------------------- # Process Do that is bound to the colored buttons. proc Do {i} { global n colors # The tree questions are encoded in the 0/1 variables test, test1 and # test2 (in this order). # First answer is yes unless we need to change it later. set test 1 # ccolor is the current color of the $i-th button. set ccolor [.b$i cget -background] # Check whether $j-th button with j < i is of same color as current # one; if any is, change first answer test to 0. (Yes, we should # use a while loop...) for {set j 1} {$j < $i} {incr j} { if {[.b$j cget -background] == $ccolor} { set test 0 } } # If first answer test is yes proceed further otherwise do nothing. if {$test} { # Set second answer test1 to 1. set test1 1 # Pick next color in the list and call it ncolor. set cindex [lsearch $colors $ccolor] set ncolor [lindex $colors [expr {($cindex+1)%3}]] # Check whether $j-th button with j < i is of the same color as new # color; if any is, change second answer test1 to 0. (Yes again, we # should use a while loop...) for {set j 1} {$j < $i} {incr j} { if {[.b$j cget -background] == $ncolor} { set test1 0 } } # If second answer test1 is yes change color of button to new one # otherwise proceed to third question. if {$test1} { # Change color to $i-th button. .b$i configure -background $ncolor -activebackground $ncolor # Try third color. } else { # Third answer test2 is yes unless we change it later. set test2 1 # New color (again) called ncolor is 2 further down the list from current. set ncolor [lindex $colors [expr {($cindex+2)%3}]] # Check whether $j-th button with j < i is of the same color as new # color; if any is, change third answer test2 to 0. (Indeed, we # should...) for {set j 1} {$j < $i} {incr j} { if {[.b$j cget -background] == $ncolor} { set test2 0 } } # If third answer test2 is yes change color of button to new one # otherwise we are done. if {$test2} { .b$i configure -background $ncolor -activebackground $ncolor } } } } #---------------------------------------------------------------------- # Initialize puzzle. Reset