#!/usr/local/bin/wish # Create the two control buttons Reset and Restart # Reset starts puzzle anew; restart goes back to the original # configuration of the puzzle. button .reset -text "Reset" -command Reset button .restart -text "Restart" -command Restart # Set the number of colors nc to 3 (in other versions of the puzzle # this number can be changed by the user but not in this one). set nc 3 # Put the button in place grid .reset -row 0 -column 0 -columnspan 1 grid .restart -row 0 -column 1 -columnspan 1 # Set the number h of buttons to 6. set h 6 # Set the list of allowable colors set colors {"white" "red" "blue" "green" "yellow"} # Give the vertical and horizontal coordinates of the location of the # buttons set vert {2 1 1 2 3 3} set horiz {4 3 1 0 1 3 } # Set moves to a list whose i-th item is itself a list with the effect # on the colors of all buttons when clicking i-th button. I.e. moves # is really the matrix A describing the puzzle written as a list of # its columns c_1, c_2, ..., c_h. set moves {{0 1 0 0 0 1} {1 0 1 0 0 0} {0 1 0 1 0 0} {0 0 1 0 1 0} {0 0 0 1 0 1} {1 0 0 0 1 0}} # The procedure Set will display the buttons in place with color # given by the function v. proc Set {} { global h v colors vert horiz # First destroy buttons... for {set i 1} {$i <= h} {incr i} { if {[winfo exists .b$i]} { destroy .b$i } } # and then create them again. for {set i 1} {$i <= $h} {incr i} { set color [lindex $colors $v($i)] # Associate the command Do($i) to the i-th button. button .b$i -height 5 -width 10 -relief raised -background $color -activebackground $color -command "Do $i" grid .b$i -row [lindex $vert [expr $i -1]] -column [lindex $horiz [expr $i -1]] } } # The process Do{i} is attached to the i-th button. In effect does the # linear algebra move v |---> v + c_i mod nc. proc Do {i} { global v moves nc h for {set j 1} {$j <= $h} {incr j} { set v($j) [expr ([lindex [lindex $moves [expr $i -1]] [expr $j -1]]+$v($j))%$nc] } # After changing the colors we need to redisplay the buttons. Set } # Go back to original (random) configuration. proc Restart {} { global h w v colors vert horiz nc # Destroy buttons for {set i 1} {$i <= 20} {incr i} { if {[winfo exists .b$i]} { destroy .b$i } } # Recover original colors stored in function w. for {set i 1} {$i <= $h} {incr i} { set v($i) $w($i) # Redisplay new button colors. Set } } # Start puzzle from scratch picking random colors. proc Reset {} { global h w v colors vert horiz nc # Destroy buttons for {set i 1} {$i <= 20} {incr i} { if {[winfo exists .b$i]} { destroy .b$i } } # Get new colors. for {set i 1} {$i <= $h} {incr i} { # Get a random color for the $i-th cell set v($i) [expr {round($nc*rand()-.5)}] # Store original position in w to use by function Restart. set w($i) $v($i) } # Redisplay buttons. Set } # Once all declarations are done we need to start the puzzle the first # time around. Reset