de: Das ist das Haus vom Ni- ko- lausIn other languages, these phrases might be used:
en: This is the house of San- ta Claus fr: C'est la mai-son de Saint Ni- cole it: La ca- sa di San Ni- co- la nl: Dat is het huis van Sin- ter- klaas zh: Sheng Ni- gu- la di xiao fang-ziLES has never heard of it, but suggests a Brazilian version:
pt-BR: Ca-si-nha do Pa-pai No-el}
package require Tk#-- A usage message is a good start (and will be used on "?")
set about {House of Santa Claus Powered by Tcl/Tk! Richard Suchenwirth 2005 Draw the outlined house in one continuous move by clicking on the edge circles. Click "C" to reset. Click "<-" to undo the last move. Click "!" for a hint. }#-- Build the UI
proc main {} { global g array set g { edges {AB AC AD BC BD CD CE DE} A {60 240} B {220 240} C {220 120} D {60 120} E {140 40} } pack [canvas .c -width 240 -height 260] .c create window 20 20 -window [button .c.? -width 2 -text ? \ -command {tk_messageBox -message $::about}] .c create window 20 50 -window [button .c.c -width 2 -text C \ -command {reset .c}] .c create window 20 80 -window [button .c.<- -width 2 -text <- \ -command {undo .c}] .c create window 20 110 -window [button .c.! -width 2 -text ! \ -command {hint .c}] foreach edge $g(edges) { foreach {from to} [split $edge ""] break .c create line [concat $g($from) $g($to)] -width 2 -fill white } foreach node [array names g ?] { node .c $node $g($node) } .c bind node <1> {clicknode .c} reset .c }#-- Back to square one :)
proc reset w { global g foreach i [array names g incides,?] {unset g($i)} foreach edge $g(edges) { foreach {from to} [split $edge ""] break lappend g(incides,$from) $to lappend g(incides,$to) $from } $w delete line $w itemconfig node -fill yellow set g(stack) {} catch {unset g(last)} foreach event [after info] {after cancel $event} }#-- Draw a node as circle, with label
proc node {w name pos} { foreach {x y} $pos break $w create oval [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5] \ -outline black -tag [list node $name] set tx [expr {$x<140? $x-12: $x>140? $x+12: $x}] set ty [expr {$y<120? $y-12: $y>120? $y+12: $y}] $w create text $tx $ty -text $name }#-- Called when a node is selected, by user or [hint]
proc clicknode {w {node -}} { global g set id [$w find withtag [expr {$node eq "-"? "current": $node}]] set name [lindex [$w gettags $id] 1] if [info exists g(last)] { set last $g(last) if {$last eq "" || $last eq $name} {return 0} if {[lsearch $g(incides,$last) $name]>=0} { $w create line [concat $g($last) $g($name)] -width 5 \ -tag [list line $last$name] lappend g(stack) $last$name $name set g(last) $name $w itemconfig $last -fill yellow $w itemconfig $name -fill blue $w raise node lremove g(incides,$last) $name lremove g(incides,$name) $last if [done?] { tk_messageBox -message "Made it!" reset $w return 1 } } } else { set g(last) $name $w itemconfig $name -fill blue } return 0 }#-- Undo the last move
proc undo w { global g $w itemconfig [lindex $g(stack) end] -fill yellow set g(last) [lindex $g(stack) end-2] $w itemconfig $g(last) -fill blue set lastedge [lindex $g(stack) end-1] $w delete $lastedge foreach {from to} [split $lastedge ""] break lappend g(incides,$from) $to lappend g(incides,$to) $from set g(stack) [lrange $g(stack) 0 end-2] if {[llength $g(stack)]==0} {unset g(last)} }#-- See if the puzzle is completed
proc done? {} { foreach i [array names ::g incides,*] { if {[llength $::g($i)]} {return 0} } return 1 }#-- Demonstrate a possible solution
proc hint w { reset $w set node [lpick {A B}] while {![done?]} { if [clicknode $w $node] break update idletasks after 1000 set node [lpick $::g(incides,$node)] if {$node eq ""} {after idle hint $w; break} } }#-- Generally useful routines:
proc lremove {_list element} { upvar 1 $_list list set pos [lsearch $list $element] set list [lreplace $list $pos $pos] } proc lpick list { lindex $list [expr int(rand()*[llength $list])] }#-- Let the show begin!
main#-- Debugging helpers:
bind . <Escape> {exec wish $argv0 &; exit} bind . <F1> {console show}if 0 {
Category Toys | Arts and crafts of Tcl-Tk programming}