Minesweeper on Tktable

This is a first attempt at doing something with Tktable by Steve Howarth (SMH).

It's yet another version of the old minesweeper game played on a 16 x 16 grid. I haven't implemented a timer yet. I won't add highscores as that might get into territories blocked by safe environments.

Oh yeah, and it probably requires at least TCL 8.x due to a) Tktable and b) string comparisons using 'eq' MG the 'eq' form of comparison requires Tk 8.4, I believe

HD: I added a timer and a sweep function which works the same way as Windows Minesweeper. Put the cursor on a clicked square where the number in the square is the same as the number of flagged neighboring squares, click the middle button (or both buttons at the same time on a two-button mouse) and it sweeps out the neighbors. I couldn't get the binding to work properly on Windows, so feel free to fix it if you see what's wrong.


See also tkmines.


package require Tk
package require Tktable
package require math
 
# Widget names/Commands
 
set rstBtn .f.b
set cntLbl .f.c
set timLbl .f.tm
set tbl .f.t
set initMines 40
set nMines    0
set gameOn    0
 
variable tab;    # tab($r,$c) contains revealed mine counts
variable map;    # map($r,$c) contains "M" or number of mines in adj. cells
variable cntVar; # Number of flags to place
variable timer;  # Elapsed time. Not used yet.
 
# table info
array set table {
    name .f.t cmd .f.t
    rows 16  cols 16  cellSize 18 
    xp -1 yp -1  x  -1 y -1
    offsets {-1 -1 -1 0 -1 1  
             0 -1       0 1  
             1 -1  1 0  1 1 } 
    valid 0
}
 
frame .f
pack .f -side top
 
set tbl $table(name)
table $tbl -rows $table(rows) -cols $table(cols) \
    -roworigin 0 -colorigin 0 -selectmode none \
    -colwidth -$table(cellSize) -rowheight -$table(cellSize) \
    -width 0 -height 0 \
    -variable tab \
    -flashmode off \
    -cursor top_left_arrow \
    -borderwidth 2 \
    -state disabled \
    -resizeborders none 
 
set f [font create -family "arial black" -size 15 ]
label $cntLbl -font $f -textvariable cntVar
label $timLbl -font $f -textvariable timer
button $rstBtn
 
grid $cntLbl  $rstBtn $timLbl
grid $tbl -columnspan 3
 
# set up tags for the various cell states:
#  NC    Not clicked yet
#  C0    Empty no neighbours 
#  C1..C8 Empty n neighbours
#  FLAG  Flag Symbol  
#  MINE  Mine 
#  NOMINE bad flag
#  BANG  exploded mine
 
set f [font create -family "arial black" -size 9 ]
$tbl tag configure NC -bg gray75 -relief raised -showtext 1
 
$tbl tag configure C0  -bg gray -relief flat
 
foreach {n c} {1 blue 2 "dark green" 3 red 4 "dark blue" 5 "dark red" 6 brown 7 black 8 navy } { 
    $tbl tag configure C$n  -bg gray -fg $c -relief flat -font $f
}
# $tbl tag configure FLAG / MINE / NOMINE / BOOM (tags with images, see later) 
 
# Win. All mines flagged. All other squares clicked at least once
proc checkWin {} {
    if { ! $::cntVar } { 
        if { ! [llength [$::tbl tag cell NC]]} {
            tk_messageBox -message "Woo hoo!" -type ok
            set ::gameOn 0
            after cancel [after info] ;# Stop the timer
        }
    }
}
 
# When placing a flag: if mine decrease remainder count. 
 
proc flag rc {
    $::tbl tag celltag FLAG $rc
    incr ::cntVar -1
}
 
proc isFlagged rc { $::tbl tag includes FLAG $rc }
 
proc isntClicked rc { $::tbl tag includes NC $rc }
 
# Remove a flag. If was correctly place, have one more to find again
proc deflag rc {
    incr ::cntVar
}
 
 
proc getCell {x y} {
     global table
     set c [expr ($x - 2) /$table(cellSize) ] 
     set r [expr ($y - 2) /$table(cellSize) ] 
     set table(col) $c;  set table(row) $r
     set table(rc) $r,$c
     puts "$x,$y"
}
 
proc showMines {} {
    global map tbl table
 
    for {set r 0} {$r < $table(rows)} {incr r} {
        for {set c 0} {$c < $table(cols)} {incr c} {
            set rc $r,$c
            if {[isFlagged $rc]} {
                if { $map($rc) ne "M" } { 
                    $tbl tag celltag NOMINE $rc        
                }
            }  elseif { $map($rc) eq "M"} {
                $tbl tag celltag MINE $rc
            } 
        }
    }
}
 
proc showZero {r c} {
    global tbl table map offsets tab
    lappend toDo $r $c
    set inList($r,$c) 1
    while {[llength $toDo] } {
        set r [lindex $toDo 0]
        set c [lindex $toDo 1]
        set rc $r,$c
 
        $tbl tag celltag C0 $rc
        set toDo [lreplace $toDo 0 1] 
         
        foreach cell [neighbors $r $c] {
            if {[isFlagged $cell]} {deflag $cell }
            if { ![info exists inList($cell)] } {
                if { $map($cell) eq "0" } {
                     foreach {nr nc} [split $cell ,] {}
                     lappend toDo $nr $nc
                     set inList($cell) 1
                } else {
                     set tab($cell) $map($cell)
                     $tbl tag celltag "C$map($cell)" $cell
                     $tbl tag celltag "C$map($rc)" $rc
                }
            }
        }    
    }
}
 
# Pressing down left button makes us worry
 
bind $tbl <ButtonPress-1> {
    if { $::gameOn } {  $::rstBtn configure -image $::images(worry) }
    break
}
 
# Releasing left button reveals our fate
 
bind $tbl <ButtonRelease-1> {
    getCell %x %y
    click $table(row),$table(col)
    break
}
 
proc click {rc} {
    global tbl table map images
    foreach {r c} [split $rc ,] {}
    
    if {$::gameOn && ! [isFlagged $rc]} {
        if { $map($rc) eq "M" } {

            showMines
            $::rstBtn configure -image $images(dead)
            $tbl tag celltag BOOM $rc
            set ::gameOn 0 
            after cancel [after info] ;# Stop the timer
            
        } elseif { $map($rc) > 0 } {

            set tab($rc) $map($rc)
            $tbl tag celltag "C$tab($rc)" $rc
            $::rstBtn configure -image $images(smiley)
        
        } else {
         
            showZero $table(row) $table(col) 
            $::rstBtn configure -image $images(smiley)
        }
        checkWin
    }
 
}

# Pressing right button, toggles NC<->FLAG

bind $tbl <3> {
    global tbl table tab
    if $::gameOn {
        getCell %x %y
        set rc $table(rc)
        if  {[isFlagged $rc ]} {
            deflag $rc
            $tbl tag celltag NC $rc
        } elseif { [isntClicked $rc ] } {
            flag $rc
        }
    }
    checkWin
    break ;# Avoid hiliting cell
}

# Middle button sweeps
 
bind $tbl <2> {
     getCell %x %y
     sweep $table(row) $table(col)
     break
}
 
proc sweep {r c} {
     global table map
     if {!$::gameOn || [isFlagged $r,$c] || [isntClicked $r,$c]} return
     set flags 0
     set notClicked [list]
     foreach cell [neighbors $r $c] {
         if {[isFlagged $cell]} {
             incr flags
         } elseif {[isntClicked $cell]} {
             lappend notClicked $cell
         }
     }
     if {$flags != $map($r,$c)} return
     foreach neighbor $notClicked {
         click $neighbor
     }
}
 
proc neighbors {r c} {
     global table
     set result [list]
     foreach {dr dc} $table(offsets) {
         set nr [expr $r + $dr]
         if  {$nr < 0 || $nr >= $table(rows) } continue
         set nc [expr $c + $dc]
         if  {$nc < 0 || $nc >= $table(cols) } continue
         lappend result $nr,$nc
     }
     return $result
}
 
proc getImage {tag imageData} {  
    if {[catch {image create photo [list gif $tag] -data $imageData} image]} return
    return $image  
}

set im [getImage FLAG {
R0lGODlhEAAQAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAKAgAMAg
AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAACAACCA
AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAGDAAIDA
AKDAAMDAAODAAADgACDgAEDgAGDgAIDgAKDgAMDgAODgAAAAQCAAQEAAQGAAQIAAQKAAQMAAQOAA
QAAgQCAgQEAgQGAgQIAgQKAgQMAgQOAgQABAQCBAQEBAQGBAQIBAQKBAQMBAQOBAQABgQCBgQEBg
QGBgQIBgQKBgQMBgQOBgQACAQCCAQECAQGCAQICAQKCAQMCAQOCAQACgQCCgQECgQGCgQICgQKCg
QMCgQOCgQADAQCDAQEDAQGDAQIDAQKDAQMDAQODAQADgQCDgQEDgQGDgQIDgQKDgQMDgQODgQAAA
gCAAgEAAgGAAgIAAgKAAgMAAgOAAgAAggCAggEAggGAggIAggKAggMAggOAggABAgCBAgEBAgGBA
gIBAgKBAgMBAgOBAgABggCBggEBggGBggIBggKBggMBggOBggACAgCCAgECAgGCAgICAgKCAgMCA
gOCAgACggCCggECggGCggICggKCggMCggOCggADAgCDAgEDAgGDAgIDAgKDAgMDAgODAgADggCDg
gEDggGDggIDggKDggMDggODggAAAwCAAwEAAwGAAwIAAwKAAwMAAwOAAwAAgwCAgwEAgwGAgwIAg
wKAgwMAgwOAgwABAwCBAwEBAwGBAwIBAwKBAwMBAwOBAwABgwCBgwEBgwGBgwIBgwKBgwMBgwOBg
wACAwCCAwECAwGCAwICAwKCAwMCAwOCAwACgwCCgwECgwGCgwICgwKCgwMCgwOCgwADAwCDAwEDA
wGDAwIDAwKDAwP/78KCgpICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAPkALAAAAAAQABAA
AAhBAAEIHEiwoMF/CBEaJJiw4UKB/yBKfBgRQMWKCxsmfGhR4UaKGjFmHCgyo0OOKBmWhLiyo0aO
Gz8WVHiwZUoAAQEAOw==}]

$tbl tag configure FLAG  -image $im 

set im [ getImage MINE {
R0lGODlhEAAQAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAKAgAMAg
AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAACAACCA
AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAGDAAIDA
AKDAAMDAAODAAADgACDgAEDgAGDgAIDgAKDgAMDgAODgAAAAQCAAQEAAQGAAQIAAQKAAQMAAQOAA
QAAgQCAgQEAgQGAgQIAgQKAgQMAgQOAgQABAQCBAQEBAQGBAQIBAQKBAQMBAQOBAQABgQCBgQEBg
QGBgQIBgQKBgQMBgQOBgQACAQCCAQECAQGCAQICAQKCAQMCAQOCAQACgQCCgQECgQGCgQICgQKCg
QMCgQOCgQADAQCDAQEDAQGDAQIDAQKDAQMDAQODAQADgQCDgQEDgQGDgQIDgQKDgQMDgQODgQAAA
gCAAgEAAgGAAgIAAgKAAgMAAgOAAgAAggCAggEAggGAggIAggKAggMAggOAggABAgCBAgEBAgGBA
gIBAgKBAgMBAgOBAgABggCBggEBggGBggIBggKBggMBggOBggACAgCCAgECAgGCAgICAgKCAgMCA
gOCAgACggCCggECggGCggICggKCggMCggOCggADAgCDAgEDAgGDAgIDAgKDAgMDAgODAgADggCDg
gEDggGDggIDggKDggMDggODggAAAwCAAwEAAwGAAwIAAwKAAwMAAwOAAwAAgwCAgwEAgwGAgwIAg
wKAgwMAgwOAgwABAwCBAwEBAwGBAwIBAwKBAwMBAwOBAwABgwCBgwEBgwGBgwIBgwKBgwMBgwOBg
wACAwCCAwECAwGCAwICAwKCAwMCAwOCAwACgwCCgwECgwGCgwICgwKCgwMCgwOCgwADAwCDAwEDA
wGDAwIDAwKDAwP/78KCgpICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAPkALAAAAAAQABAA
AAg9APMJHEiwoMGDCBMqXGgQgEKHAyEKlBgxH4CLFy0iBPAPY8aNHj8WDEnyIEmKI0uatOhR40iC
FFG+ZKgwIAA7}]

$tbl tag configure MINE  -image $im
$tbl tag configure BOOM  -image $im -bg red

set im [ getImage NOMINE {
R0lGODdhEAAQAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD/
/////4iIiIiIiIiIiIiIiIgIiICICICAiAgIAACIiIgAAACIiIgAAACAiAgAAACAiAgAAACAiAgA
AACAiAgAAA+IiIgAAACIiIgAAICAiAgIAIgIiICICIiIiIiIiIiIiIiIiP8AAAAAAB8ACwgBALXI
MCPzMAAAAAEEfgAAAAUEvoUADwAAAAAAAAAAAAAAAAAAEAAAEAAAAQAAEAAAAP///wAAAAAAEAAA
DwsBZv8QALXcACMBeAAAAAAA//8AAAAAAAAAAAAA//8AAAAAAAAAAP///////wAAAAAAAP//AAD/
/wAAAAAAAAAAAAAAAAAAAAAAAAAAAKcBWQAQALXcALUm2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAA
AAhOABEIHEiwoMGDBgEQBKBwYMOBCRIwnKgwosGIDyhGTJAw4kSLCRl69PjQ4UeSJQVqRBkSwEiJ
KVWiBHkR5smaFBkioImgpE6HCIMKPRgQADs=}]

$tbl tag configure NOMINE  -image $im

set images(smiley) [getImage SMILEY {
R0lGODlhIAAgAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAKAgAMAg
AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAACAACCA
AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAGDAAIDA
AKDAAMDAAODAAADgACDgAEDgAGDgAIDgAKDgAMDgAODgAAAAQCAAQEAAQGAAQIAAQKAAQMAAQOAA
QAAgQCAgQEAgQGAgQIAgQKAgQMAgQOAgQABAQCBAQEBAQGBAQIBAQKBAQMBAQOBAQABgQCBgQEBg
QGBgQIBgQKBgQMBgQOBgQACAQCCAQECAQGCAQICAQKCAQMCAQOCAQACgQCCgQECgQGCgQICgQKCg
QMCgQOCgQADAQCDAQEDAQGDAQIDAQKDAQMDAQODAQADgQCDgQEDgQGDgQIDgQKDgQMDgQODgQAAA
gCAAgEAAgGAAgIAAgKAAgMAAgOAAgAAggCAggEAggGAggIAggKAggMAggOAggABAgCBAgEBAgGBA
gIBAgKBAgMBAgOBAgABggCBggEBggGBggIBggKBggMBggOBggACAgCCAgECAgGCAgICAgKCAgMCA
gOCAgACggCCggECggGCggICggKCggMCggOCggADAgCDAgEDAgGDAgIDAgKDAgMDAgODAgADggCDg
gEDggGDggIDggKDggMDggODggAAAwCAAwEAAwGAAwIAAwKAAwMAAwOAAwAAgwCAgwEAgwGAgwIAg
wKAgwMAgwOAgwABAwCBAwEBAwGBAwIBAwKBAwMBAwOBAwABgwCBgwEBgwGBgwIBgwKBgwMBgwOBg
wACAwCCAwECAwGCAwICAwKCAwMCAwOCAwACgwCCgwECgwGCgwICgwKCgwMCgwOCgwADAwCDAwEDA
wGDAwIDAwKDAwP/78KCgpICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAPkALAAAAAAgACAA
AAiSAPMJHEiwoMGDCBMqXMiwocOHEAkCmEgxokGK+zJqrGgRgMaPIAFE9AiyZEaRDkmaNIlyocqV
LF3CnLmv5cGXNV9OjJkQ586NOE/2pEnTpkSiM40ODIp0I0KmTWsO3QjTp0KdVUNeDcmypNKCPlX+
/Pj1otexZFNCPQtxrdOOaE9OtAiW4ly6ePPq3cu3r9++AQEAOw==}]

set images(worry) [getImage WORRY {
R0lGODlhIAAgAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAKAgAMAg
AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAACAACCA
AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAGDAAIDA
AKDAAMDAAODAAADgACDgAEDgAGDgAIDgAKDgAMDgAODgAAAAQCAAQEAAQGAAQIAAQKAAQMAAQOAA
QAAgQCAgQEAgQGAgQIAgQKAgQMAgQOAgQABAQCBAQEBAQGBAQIBAQKBAQMBAQOBAQABgQCBgQEBg
QGBgQIBgQKBgQMBgQOBgQACAQCCAQECAQGCAQICAQKCAQMCAQOCAQACgQCCgQECgQGCgQICgQKCg
QMCgQOCgQADAQCDAQEDAQGDAQIDAQKDAQMDAQODAQADgQCDgQEDgQGDgQIDgQKDgQMDgQODgQAAA
gCAAgEAAgGAAgIAAgKAAgMAAgOAAgAAggCAggEAggGAggIAggKAggMAggOAggABAgCBAgEBAgGBA
gIBAgKBAgMBAgOBAgABggCBggEBggGBggIBggKBggMBggOBggACAgCCAgECAgGCAgICAgKCAgMCA
gOCAgACggCCggECggGCggICggKCggMCggOCggADAgCDAgEDAgGDAgIDAgKDAgMDAgODAgADggCDg
gEDggGDggIDggKDggMDggODggAAAwCAAwEAAwGAAwIAAwKAAwMAAwOAAwAAgwCAgwEAgwGAgwIAg
wKAgwMAgwOAgwABAwCBAwEBAwGBAwIBAwKBAwMBAwOBAwABgwCBgwEBgwGBgwIBgwKBgwMBgwOBg
wACAwCCAwECAwGCAwICAwKCAwMCAwOCAwACgwCCgwECgwGCgwICgwKCgwMCgwOCgwADAwCDAwEDA
wGDAwIDAwKDAwP/78KCgpICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAPkALAAAAAAgACAA
AAiPAPMJHEiwoMGDCBMqXMiwocOHEAkCmEgxokGK+zJqrGgRgMaPIAFE9AiyZEaRDkmaNIlyocp9
L0+WbInwZcyNMxWq9DjxY8+YNC+GtHkTZsKiK1nWTMp049KmTIMORAr15NGqSq9iDalzJsWvObtu
tcqQatayZn1KFRvVYj6MQ9dC/DrRrd27ePPq3cuXb0AAOw==
}]

set images(dead) [getImage DEAD {
R0lGODlhIAAgAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwMDcwKbK8EAgAGAgAIAgAKAgAMAg
AOAgAABAACBAAEBAAGBAAIBAAKBAAMBAAOBAAABgACBgAEBgAGBgAIBgAKBgAMBgAOBgAACAACCA
AECAAGCAAICAAKCAAMCAAOCAAACgACCgAECgAGCgAICgAKCgAMCgAOCgAADAACDAAEDAAGDAAIDA
AKDAAMDAAODAAADgACDgAEDgAGDgAIDgAKDgAMDgAODgAAAAQCAAQEAAQGAAQIAAQKAAQMAAQOAA
QAAgQCAgQEAgQGAgQIAgQKAgQMAgQOAgQABAQCBAQEBAQGBAQIBAQKBAQMBAQOBAQABgQCBgQEBg
QGBgQIBgQKBgQMBgQOBgQACAQCCAQECAQGCAQICAQKCAQMCAQOCAQACgQCCgQECgQGCgQICgQKCg
QMCgQOCgQADAQCDAQEDAQGDAQIDAQKDAQMDAQODAQADgQCDgQEDgQGDgQIDgQKDgQMDgQODgQAAA
gCAAgEAAgGAAgIAAgKAAgMAAgOAAgAAggCAggEAggGAggIAggKAggMAggOAggABAgCBAgEBAgGBA
gIBAgKBAgMBAgOBAgABggCBggEBggGBggIBggKBggMBggOBggACAgCCAgECAgGCAgICAgKCAgMCA
gOCAgACggCCggECggGCggICggKCggMCggOCggADAgCDAgEDAgGDAgIDAgKDAgMDAgODAgADggCDg
gEDggGDggIDggKDggMDggODggAAAwCAAwEAAwGAAwIAAwKAAwMAAwOAAwAAgwCAgwEAgwGAgwIAg
wKAgwMAgwOAgwABAwCBAwEBAwGBAwIBAwKBAwMBAwOBAwABgwCBgwEBgwGBgwIBgwKBgwMBgwOBg
wACAwCCAwECAwGCAwICAwKCAwMCAwOCAwACgwCCgwECgwGCgwICgwKCgwMCgwOCgwADAwCDAwEDA
wGDAwIDAwKDAwP/78KCgpICAgP8AAAD/AP//AAAA//8A/wD//////yH5BAEAAPkALAAAAAAgACAA
AAiVAPMJHEiwoMGDCBMqXMiwocOHEAkCmEgxokGK+zJqrGgRgMaPIAFE9AiyZEaRDkmaNIlyocqV
LF2G3KfS48uTCm/SnFmy5cGbNjfuDJlQJ8yYP48qpYnQ6NKNTZ/C9FnQKcaVVKv2rGk0q0SeYKHm
FIr1o9eLUnE2nCh1IkSnZi3mu2rWrdyBFDne3cu3r9+/gANDDAgAOw==
}]


proc initGame {} {
    global tbl images table map tab 
    array set map {}  
    set t $tbl

    # initialise mine array with extra 'guard' cells around entire area.

    for { set r -1 } { $r <= $table(rows) } { incr r } {
        for { set c -1 } { $c <= $table(cols) } { incr c } {
            set map($r,$c) "0"
            set tab($r,$c) ""
        }
    }

    set mxr [expr $table(rows) - 1]
    set mxc [expr $table(cols) - 1]
    set ::cntVar 0 
    while { $::cntVar < $::initMines } {
        set r [::math::random 0 $mxr ]
        set c [::math::random 0 $mxc  ]
        if { $map($r,$c) ne "M"} {  
            incr ::cntVar
            set map($r,$c) "M"
            # increase adj. mine count for all neighboring cells which don't contain mines
            foreach {dr dc} $table(offsets) {
                set nr [expr $r + $dr]
                set nc [expr $c + $dc]
                if { $map($nr,$nc) ne "M" } { incr map($nr,$nc)}
         }    
        }
    }

    # inititialize the array, titles, and celltags
    for {set r 0} {$r < $table(rows)} {incr r} {
        for {set c 0} {$c < $table(cols)} {incr c} {
            $tbl tag celltag NC $r,$c
            # set tab($r,$c) $map($r,$c); # Uncomment for cheat mode
                
        }
    }

    set ::gameOn 1
    set ::timer  0
    $::rstBtn configure -image $images(smiley) -command initGame
 
     after 1000 tick
}
 
proc tick {} {
     incr ::timer
     after 1000 tick
}


initGame