Version 20 of Minesweeper on Tktable

Updated 2012-01-11 03:22:09 by AMG

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