See also: Eight Queens Problem
WDB:
package require Tcl 8.5
package require Tk
bind Tk <Destroy> exit
wm resizable . no no
apply {canvas {
destroy $canvas
pack [canvas $canvas -width 320 -height 320]
foreach i {0 1 2 3 4 5 6 7} {
foreach j {0 1 2 3 4 5 6 7} {
set o [expr {($i+$j)%2 ? "odd" : "even"}]
set coords [list [* $i 40] [* $j 40]\
[* [+ $i 1] 40] [* [+ $j 1] 40]]
$canvas create rectangle $coords\
-tags [list f $o r$j c$i]
$canvas create text\
[+ [* $i 40] 20] [+ [* $j 40] 20]\
-tags [list q r$j c$i]
$canvas bind r$j&&c$i <1> "check $j $i"
}
}
foreach c {-8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7} {
set col $c
foreach row {0 1 2 3 4 5 6 7} {
$canvas addtag d[+ $c 7] withtag r$row&&c$col
incr col
}
}
foreach c {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
set col $c
foreach row {0 1 2 3 4 5 6 7} {
$canvas addtag e$c withtag r$row&&c$col
incr col -1
}
}
$canvas itemconfigure odd\
-fill grey\
-outline ""
$canvas itemconfigure even\
-fill #ffffcc\
-outline ""
$canvas itemconfigure q\
-fill navy\
-font {Times 20 bold italic}
bind $canvas <ButtonRelease>\
"$canvas itemconfigure q -fill navy"
} ::tcl::mathop} .c
proc check {row col} {
set txt [.c itemcget q&&r$row&&c$col -text]
if {$txt ne ""} then {
.c itemconfigure q&&r$row&&c$col -text ""
} else {
setQueen $row $col
}
}
proc setQueen {row col} {
foreach tag [.c gettags q&&r$row&&c$col] {
regexp d(.+) $tag - d
regexp e(.+) $tag - e
}
set pat q&&(r$row||c$col||d$d||e$e)
set success true
set els [.c find withtag $pat]
foreach el $els {
if {[.c itemcget $el -text] ne ""} then {
set success false
}
}
if {$success} then {
.c itemconfigure q&&r$row&&c$col -text Q
} else {
.c itemconfigure $pat -fill white
}
}
if false {
# the "aggressive" variant:
proc setQueen {row col} {
foreach tag [.c gettags q&&r$row&&c$col] {
regexp d(.+) $tag - d
regexp e(.+) $tag - e
}
.c itemconfigure q&&(r$row||c$col||d$d||e$e) -text ""
.c itemconfigure q&&r$row&&c$col -text Q
}
}
Beware How Minimalistic can you go?
proc r {l} {
global solutions
if {[llength $l]==8} {lappend solutions $l; return $l}
foreach g [remove $l] {
set n [concat $l $g]
if {[valid $n]} {
r $n
}
}
}
proc valid {l} {
set len [llength $l]
for {set j 0} {$j<$len} {incr j} {
set n [lindex $l $j]
for {set i 0} {$i<$len} {incr i} {
if {$i==$j} {continue}
set t [lindex $l $i]
if {[expr ($t-$n) - ($i-$j)]==0} {return 0}
if {[expr ($n-$t) - ($i-$j)]==0} {return 0}
}
}
return 1
}
proc remove {l} {
set ret [list]
foreach n [list 0 1 2 3 4 5 6 7] {
if {[lsearch $l $n]==-1} {lappend ret $n}
}
return $ret
}
set solutions [list]
proc go {} {
global solutions
set solutions [list]
foreach h [list 0 1 2 3 4 5 6 7] {
r $h
}
#puts [join $solutions \n]
#puts "[llength $solutions] Solutions..."
}
set index -1
proc forward {} {
global index
if {$index>90} {return}
incr index
display
}
proc back {} {
global index
if {$index<1} {return}
incr index -1
display
}
proc display {} {
global solutions display index
set sol [lindex $solutions $index]
set r ""
#set e "================\n"
set e ""
foreach l $sol {
if {$l==0} {append r "Q| | | | | | | \n$e"}
if {$l==1} {append r " |Q| | | | | | \n$e"}
if {$l==2} {append r " | |Q| | | | | \n$e"}
if {$l==3} {append r " | | |Q| | | | \n$e"}
if {$l==4} {append r " | | | |Q| | | \n$e"}
if {$l==5} {append r " | | | | |Q| | \n$e"}
if {$l==6} {append r " | | | | | |Q| \n$e"}
if {$l==7} {append r " | | | | | | |Q\n$e"}
}
set display $r
}
pack [label .l -textvariable display -width 16 -height 10 -font {Courier 12 bold}]
frame .b
button .b.b -text < -command back
button .b.f -text > -command forward
pack .b.b .b.f -in .b -side left
pack .b
set display "Searching\nfor\nsolutions"
go
forward