wdb Presumably the 994,378th clone of Bill Gatesʼ ingenious game “Mine Sweeper” which was that one reason why Windows became that famous. (Is it true that he has invented this game? Himself? Whoa.)
Ok. As minimalist I prefer the core of games, not the bell and whistles. Call me a purist. My personal version of “mine”. No timer, no hall of fame. Just number of tiles left to be seen in window title. Licence OLL.
Usage:
mine.tcl mine.tcl child mine.tcl teenie mine.tcl custom (cols) (rows) (mines)
Have fun!
#!/usr/bin/wish package require Tk bind [winfo class .] <Destroy> exit # debug proc -- args # proc echo args {puts $args} proc aloud args { puts $args uplevel $args } namespace path "::tcl::mathop ::tcl::mathfunc" # mine, 30 cols 16 rows 99 mines # here to customize # lassign "30 16 99" cols rows mines # lassign "8 8 8" cols rows mines switch [lindex $argv 0] { child {lassign {8 8 10} cols rows mines} teenie {lassign {16 16 40} cols rows mines} custom { lassign $argv - cols rows mines if {$cols eq ""} then { set cols 16 } if {$rows eq ""} then { set rows $cols } if {$mines eq ""} then { set mines [int [sqrt [* $cols $rows 4]]] } } default {lassign {30 16 99} cols rows mines} } pack [canvas .c\ -width [- [* 25 $cols] 2]\ -height [- [* 25 $rows] 2]\ -background grey70] -expand yes -fill both wm title . Minesweeper wm resizable . 0 0 # # game states # variable pressed false variable init true set bombChar \u2688 set flagChar \u2691 set flagCharHollow \u2690 proc tile {col row {canvas .c}} { global bombChar flagChar set w 25 set h 3 set x [* $col $w] set y [* $row $w] set tags "col$col row$row" $canvas create text [+ $x 12] [+ $y 12]\ -text ""\ -anchor center\ -font "Helvetica 16 bold"\ -tags "$tags text" $canvas create polygon\ [+ $x 1] [+ $y 1] [+ $x $w -1] [+ $y 1] [+ $x 1] [+ $y $w -1]\ -fill grey85 -tags "$tags topleft" $canvas create polygon\ [+ $x 1] [+ $y $w -1] [+ $x $w -1] [+ $y $w -1] [+ $x $w -1] [+ $y 1]\ -fill grey15 -tags "$tags bottomright" $canvas create rectangle [+ $x $h] [+ $y $h] [+ $x $w -$h] [+ $y $w -$h]\ -fill grey70 -tags "$tags surface" -outline "" $canvas create text [+ $x 11] [+ $y 11]\ -text ""\ -anchor center\ -font "Helvetica 16 bold"\ -fill white\ -tags "$tags flag" # $canvas bind col$col&&row$row&&surface <1> "press $col $row" $canvas bind col$col&&row$row&&surface <3> "flag $col $row" $canvas bind col$col&&row$row&&flag <3> "flag $col $row" $canvas bind col$col&&row$row&&surface\ <Leave> "release $col $row" $canvas bind col$col&&row$row&&surface\ <ButtonRelease> " if {\$pressed} then { if {\$init} then { init $col $row } else { check $col $row } } release $col $row " } proc flag {col row {canvas .c}} { global flagChar if {[$canvas itemcget col$col&&row$row&&flag -text] eq $flagChar} then { $canvas itemconfigure col$col&&row$row&&flag -text "" } else { $canvas itemconfigure col$col&&row$row&&flag -text $flagChar } } proc press {col row {canvas .c}} { if {[$canvas itemcget row$row&&col$col&&flag -text] eq ""} then { variable pressed true $canvas itemconfigure col$col&&row$row&&topleft -fill grey15 $canvas itemconfigure col$col&&row$row&&bottomright -fill grey85 $canvas itemconfigure col$col&&row$row&&surface -fill grey65 } } proc release {col row {canvas .c}} { variable pressed false $canvas itemconfigure col$col&&row$row&&topleft -fill grey85 $canvas itemconfigure col$col&&row$row&&bottomright -fill grey15 $canvas itemconfigure col$col&&row$row&&surface -fill grey70 } proc takeNfromList {n liste} { if {$n > 0} then { set i [expr {int(rand()*[llength $liste])}] list [lindex $liste $i] {*}[takeNfromList [- $n 1] [lreplace $liste $i $i]] } } proc init {col row {canvas .c}} { global rows cols mines global bombChar variable init if {!$init} then return set init false # hide 99 mines everywhere, but not at $col $row # first, collect fields for {set i 0} {$i < $cols} {incr i} { for {set j 0} {$j < $rows} {incr j} { if {$col != $i && $row != $j} then { lappend fields "$i $j" } } } # hide $mines mines set mineIndices [takeNfromList $mines $fields] foreach idx $mineIndices { lassign $idx x y $canvas itemconfigure col$x&&row$y&&text -text $bombChar } # write num of neighboured mines for {set i 0} {$i < $cols} {incr i} { for {set j 0} {$j < $rows} {incr j} { set tags col$i&&row$j&&text if {[$canvas itemcget $tags -text] ne $bombChar} then { set count 0 foreach di {-1 0 1} { foreach dj {-1 0 1} { if {[$canvas itemcget col[+ $i $di]&&row[+ $j $dj]&&text -text] eq $bombChar} then { incr count } } } if {$count > 0} then { $canvas itemconfigure col$i&&row$j&&text\ -text $count\ -fill [lindex {black blue4 green4 red4 grey25 blue4 green4 red4 grey25} $count] } } } } after idle [list check $col $row] } proc check {col row {canvas .c}} { global bombChar rows cols mines if {[$canvas itemcget col$col&&row$row&&flag -text] eq ""} then { if {[$canvas itemcget col$col&&row$row&&text -text] eq $bombChar} then { bumm $col $row $canvas } elseif {[$canvas find withtag row$row&&col$col&&surface] ne ""} then { $canvas delete row$row&&col$col&&!text if {[$canvas itemcget col$col&&row$row&&text -text] eq ""} then { check [- $col 1] [- $row 1] $canvas check [- $col 1] $row $canvas check [- $col 1] [+ $row 1] $canvas # check $col [- $row 1] $canvas check $col [+ $row 1] $canvas # check [+ $col 1] [- $row 1] $canvas check [+ $col 1] $row $canvas check [+ $col 1] [+ $row 1] $canvas } } set freeTiles [- [llength [$canvas find withtag surface]] $mines] if {$freeTiles > 0} then { wm title [winfo toplevel $canvas] "Minesweeper - $freeTiles tiles left" } else { wm title [winfo toplevel $canvas] Success! } update } } proc bumm {col row {canvas .c}} { global rows cols flagCharHollow bombChar after idle "wm title [winfo toplevel $canvas] Bumm!" for {set i 0} {$i < $cols} {incr i} { for {set j 0} {$j < $rows} {incr j} { $canvas bind col$i&&row$j&&surface <1> "" $canvas bind col$i&&row$j&&surface <3> "" $canvas bind col$i&&row$j&&flag <3> "" $canvas bind col$i&&row$j&&surface <Leave> "" $canvas bind col$i&&row$j&&surface <ButtonRelease> "" if {$i == $col && $j == $row} then { # hit the mine, sorry ... $canvas delete col$i&&row$j&&!text $canvas itemconfigure col$i&&row$j&&text -fill red } elseif {[$canvas itemcget col$i&&row$j&&flag -text] ne ""} then { # flag set if {[$canvas itemcget col$i&&row$j&&text -text] ne $bombChar} then { # but no mine under it $canvas itemconfigure col$i&&row$j&&flag\ -text $flagCharHollow\ -font "Helvetica 16 bold overstrike"\ -fill black } } elseif {[$canvas itemcget col$i&&row$j&&text -text] eq $bombChar} then { $canvas delete col$i&&row$j&&!text } } } } apply { {cols rows} { .c del all for {set i 0} {$i < $cols} {incr i} { for {set j 0} {$j < $rows} {incr j} { tile $i $j } } } } $cols $rows
Survived dead, because of an error in source:
wdb strange behaviour, couldnʼt reproduce it – bumm should be visible ... nonetheless, changed the sequence. Try again!
(Later) problem appearently solved