#!/usr/bin/wish #---------------------------------------------------------------------- # CRings puzzle. # Robert Hailey # Computer Sciences # # Based on code from: # # 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 cring.tcl # or # ./cring.tcl # if it is made executable! #---------------------------------------------------------------------- # n is the number of buttons on the puzzle, set to 5 by default. set n 5 set oldn 5 # colors is the list of colors the buttons can have (in an arbitrary but fixed # cyclic ordering) set colors {"black" "white"} # 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 oldn colors for {set i 1} {$i <= $n} {incr i} { # 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 black in color (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 black -activebackground black -command "Do $i" grid .b$i -row 0 -column [expr {$i - 1}] } for {set i [expr $n + 1]} {$i <= $oldn} {incr i} { if {[winfo exists .b$i]} { destroy .b$i } } set oldn $n } #---------------------------------------------------------------------- # Process Do that is bound to the colored buttons. proc Do {i} { global n colors # First answer is yes unless we need to change it later. # The post condition is that it is true iff rings $i+2..$n # are all OFF. set test 1 # Check whether $j-th button with j < n is OFF the iron, the first # one that we find disqualifies us from continuing for {set j [expr $i+2]} {$j <= $n} {incr j} { if {[.b$j cget -background] == "black"} { set test 0 } } # If first answer test is yes proceed further otherwise do nothing. if {$test} { # Set second answer test1 defaults to FALSE, and that is if the # ring to the right of the ring being changed is infact ON the # iron. set test1 0 # Pick next color in the list and call it ncolor. set cindex [lsearch $colors [.b$i cget -background]] set ncolor [lindex $colors [expr {($cindex+1)%2}]] # 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...) set j [expr $i+1] if { $j <= $n } { if {[.b$j cget -background] == "black"} { set test1 1 } } #We can always change the first ring if { $i == $n } { set test1 1 } # 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 } } } #---------------------------------------------------------------------- # Initialize puzzle. Reset