--- newsudoku.txt 2010-01-05 12:57:02.000000000 -0800 +++ sudoku-procs-final.txt 2010-01-07 11:12:12.000000000 -0800 @@ -31,40 +31,66 @@ # use nested lists like 2 dimensional arrays -proc buildAssociations {} { +namespace eval ::sud { - global rows cols squares - - set rows [ list \ - {0 1 2 3 4 5 6 7 8} \ - {9 10 11 12 13 14 15 16 17} \ - {18 19 20 21 22 23 24 25 26} \ - {27 28 29 30 31 32 33 34 35} \ - {36 37 38 39 40 41 42 43 44} \ - {45 46 47 48 49 50 51 52 53} \ - {54 55 56 57 58 59 60 61 62} \ - {63 64 65 66 67 68 69 70 71} \ - {72 73 74 75 76 77 78 79 80} ] - - set cols [ list \ - {0 9 18 27 36 45 54 63 72} \ - {1 10 19 28 37 46 55 64 73} \ - {2 11 20 29 38 47 56 65 74} \ - {3 12 21 30 39 48 57 66 75} \ - {4 13 22 31 40 49 58 67 76} \ - {5 14 23 32 41 50 59 68 77} \ - {6 15 24 33 42 51 60 69 78} \ - {7 16 25 34 43 52 61 70 79} \ - {8 17 26 35 44 53 62 71 80} ] - - set squares [ list \ - {0 1 2 9 10 11 18 19 20} \ - {3 4 5 12 13 14 21 22 23} \ - {6 7 8 15 16 17 24 25 26} \ - {27 28 29 36 37 38 45 46 47} \ - {30 31 32 39 40 41 48 49 50} \ - {33 34 35 42 43 44 51 52 53} \ - {54 55 56 63 64 65 72 73 74} \ - {57 58 59 66 67 68 75 76 77} \ - {60 61 62 69 70 71 78 79 80} ] + variable rows + variable cols + variable squares + + variable arabicmode + variable duplicatesfound + variable invalidfound + variable kanji1to9 + + variable cellbgcolorA + variable cellbgcolorB + variable cellerrorcolor + variable celldupcolor + variable cellchangedcolor + variable checkcolor + + variable arabicarray + variable cellarray + variable cellbgcolorarray + variable kanjiarray + variable possarray +} + +proc ::sud::buildAssociations {} { + + variable rows { + {0 1 2 3 4 5 6 7 8} + {9 10 11 12 13 14 15 16 17} + {18 19 20 21 22 23 24 25 26} + {27 28 29 30 31 32 33 34 35} + {36 37 38 39 40 41 42 43 44} + {45 46 47 48 49 50 51 52 53} + {54 55 56 57 58 59 60 61 62} + {63 64 65 66 67 68 69 70 71} + {72 73 74 75 76 77 78 79 80} + } + + variable cols { + {0 9 18 27 36 45 54 63 72} + {1 10 19 28 37 46 55 64 73} + {2 11 20 29 38 47 56 65 74} + {3 12 21 30 39 48 57 66 75} + {4 13 22 31 40 49 58 67 76} + {5 14 23 32 41 50 59 68 77} + {6 15 24 33 42 51 60 69 78} + {7 16 25 34 43 52 61 70 79} + {8 17 26 35 44 53 62 71 80} + } + + variable squares { + {0 1 2 9 10 11 18 19 20} + {3 4 5 12 13 14 21 22 23} + {6 7 8 15 16 17 24 25 26} + {27 28 29 36 37 38 45 46 47} + {30 31 32 39 40 41 48 49 50} + {33 34 35 42 43 44 51 52 53} + {54 55 56 63 64 65 72 73 74} + {57 58 59 66 67 68 75 76 77} + {60 61 62 69 70 71 78 79 80} + } } @@ -73,16 +99,18 @@ # and the list of 9 kanji digits equivalent to 1-9 -proc buildTranslations {} { +proc ::sud::buildTranslations {} { - global kanjiarray arabicarray global kanji1to9 + variable kanjiarray + variable arabicarray + variable kanji1to9 - array set kanjiarray {1 \u4e00 2 \u4e8c 3 \u4e09 4 \u56db \ + array set kanjiarray {1 \u4e00 2 \u4e8c 3 \u4e09 4 \u56db 5 \u4e94 6 \u516d 7 \u4e03 8 \u516b 9 \u4e5c} - array set arabicarray {\u4e00 1 \u4e8c 2 \u4e09 3 \u56db 4 \ + array set arabicarray {\u4e00 1 \u4e8c 2 \u4e09 3 \u56db 4 \u4e94 5 \u516d 6 \u4e03 7 \u516b 8 \u4e5c 9} - set kanji1to9 [list \u4e00 \u4e8c \u4e09 \u56db \u4e94 \ - \u516d \u4e03 \u516b \u4e5c] + set kanji1to9 {\u4e00 \u4e8c \u4e09 \u56db \u4e94 + \u516d \u4e03 \u516b \u4e5c} } @@ -91,5 +119,5 @@ # pop up a warning message inside the main window -proc popMessage {message color} { +proc ::sud::popMessage {message color} { # don't allow multiple window creations if called more than once @@ -110,5 +138,5 @@ # set the color of the CHECK button -proc setCheckButtonColor {color} { +proc ::sud::setCheckButtonColor {color} { .sudoku.buttons.checkButton configure -bg $color @@ -118,18 +146,18 @@ # build the board -proc buildGrid {} { +proc ::sud::buildGrid {} { - global cellarray + variable cellarray - for {set rowind 0} {$rowind < 9} {incr rowind} { + for {set row 0} {$row < 9} {incr row} { set gridlist "" - for {set colind 0} {$colind < 9} {incr colind} { - set cellind [expr $rowind * 9 + $colind] - entry .sudoku.board.cellentry$cellind -textvariable cellarray($cellind) \ + for {set col 0} {$col < 9} {incr col} { + set cell [expr $row * 9 + $col] + entry .sudoku.board.cellentry$cell -textvariable ::sud::cellarray($cell) \ -width 2 -font {courrier 20} -justify center - bind .sudoku.board.cellentry$cellind \ - [list validEntryKey %W $cellind] - lappend gridlist .sudoku.board.cellentry$cellind + bind .sudoku.board.cellentry$cell \ + [list ::sud::validEntryKey %W $cell] + lappend gridlist .sudoku.board.cellentry$cell } eval grid $gridlist @@ -141,22 +169,23 @@ # holds the default colors for future reference -proc setBackgroundColors {} { +proc ::sud::setBackgroundColors {} { - global cellbgcolorarray - global cellbgcolorA cellbgcolorB + variable cellbgcolorarray + variable cellbgcolorA + variable cellbgcolorB - for {set rowind 0} {$rowind < 9} {incr rowind} { + for {set row 0} {$row < 9} {incr row} { set gridlist "" - for {set colind 0} {$colind < 9} {incr colind} { - set cellind [expr $rowind * 9 + $colind] + for {set col 0} {$col < 9} {incr col} { + set cell [expr $row * 9 + $col] # set cell color (row = 3 or 4 or 5) exor (col = 3 or 4 or 5) # THE PATTERN MUST COME BEFORE THE STRING OR WISH GETS CONFUSED!!!! - if {[string match {[3-5]} $colind] ^ [string match {[345]} $rowind]} { + if {[string match {[3-5]} $col] ^ [string match {[345]} $row]} { set cellbg $cellbgcolorA } else { set cellbg $cellbgcolorB } - .sudoku.board.cellentry$cellind configure -bg $cellbg - set cellbgcolorarray($cellind) $cellbg + .sudoku.board.cellentry$cell configure -bg $cellbg + set cellbgcolorarray($cell) $cellbg } } @@ -168,12 +197,12 @@ # get reduced until only one remains (hopefully) in a given element -proc buildPossible {} { +proc ::sud::buildPossible {} { - global possarray + variable possarray set possibles [list 1 2 3 4 5 6 7 8 9] - for {set index 0} {$index < 81} {incr index} { - set possarray($index) $possibles + for {set cell 0} {$cell < 81} {incr cell} { + set possarray($cell) $possibles } } @@ -184,11 +213,11 @@ # statement so just fold it into calling code??? -proc clearPossibleElementAll {index} { +proc ::sud::clearPossibleElementAll {cell} { - global possarray + variable possarray # make sure it remains a list - but empty - set possarray($index) [list] + set possarray($cell) [list] } @@ -198,10 +227,10 @@ # statement so just fold it into calling code??? -proc clearPossibleElementValue {index value} { +proc ::sud::clearPossibleElementValue {cell value} { - global possarray + variable possarray - set possarray($index) \ - [lsearch -all -inline -not -exact $possarray($index) $value] + set possarray($cell) \ + [lsearch -all -inline -not -exact $possarray($cell) $value] } @@ -212,11 +241,11 @@ # the entire list (as must happen if cell already occupied) -proc clearPossiblesPerEntry {} { +proc ::sud::clearPossiblesPerEntry {} { - global cellarray + variable cellarray - for {set index 0} {$index < 81} {incr index} { - if {[nineCheck $cellarray($index)]} { - clearPossibleElementAll $index + for {set cell 0} {$cell < 81} {incr cell} { + if {[nineCheck $cellarray($cell)]} { + clearPossibleElementAll $cell } } @@ -228,10 +257,10 @@ # returns found value if == 1, else returns 0 -proc checkPossibleForOne {index} { +proc ::sud::checkPossibleForOne {cell} { - global possarray + variable possarray - if {[llength $possarray($index)] == 1} { - return $possarray($index) + if {[llength $possarray($cell)] == 1} { + return $possarray($cell) } return 0 @@ -243,19 +272,20 @@ # set bg color to ?something? if new entry -proc updateBoard {} { +proc ::sud::updateBoard {} { - global cellarray possarray - global cellchangedcolor - global arabicmode - - for {set index 0} {$index < 81} {incr index} { - set singlevalue [checkPossibleForOne $index] - if {$singlevalue != 0} { + variable cellarray + variable possarray + variable cellchangedcolor + variable arabicmode + + for {set cell 0} {$cell < 81} {incr cell} { + set singlevalue [checkPossibleForOne $cell] + if {$singlevalue} { if {!$arabicmode} { # convert to kanji first set singlevalue [toKanji $singlevalue] } - set cellarray($index) $singlevalue - .sudoku.board.cellentry$index configure \ + set cellarray($cell) $singlevalue + .sudoku.board.cellentry$i configure \ -bg $cellchangedcolor } @@ -270,13 +300,16 @@ # in a possible element, which is done elsewhere -proc scanEntityForOne { entitytype } { +proc ::sud::scanEntityForOne { entitytype } { - global rows cols squares - global cellarray possarray - global cellchangedcolor - global arabicmode + variable rows + variable cols + variable squares + variable cellarray + variable possarray + variable cellchangedcolor + variable arabicmode - foreach entity [subst $$entitytype] { - for {set numeral 1} {$numeral < 10} {incr numeral} { + foreach entities [set $entitytype] { + for {set i 1} {$i < 10} {incr i} { # for each entity, count number of each numeral # if count == 1 set the board cell that matches @@ -284,21 +317,22 @@ set count 0 set indexmaybe 0 - foreach index $entity { - if {[lsearch $possarray($index) $numeral] != -1} { + foreach entity $entities { + if {[lsearch $possarray($entity) $i] > -1} { incr count - set indexmaybe $index + set indexmaybe $entity } } if {$count == 1} { - set newmeral $numeral + set newmeral $i if {!$arabicmode} { # convert to kanji first - set newmeral [toKanji $numeral] + set newmeral [toKanji $i] } # sanity check - if {[nineCheck $cellarray($indexmaybe)] \ - && ($cellarray($indexmaybe) != $newmeral)} { + if {[nineCheck $cellarray($indexmaybe)] + && ($cellarray($indexmaybe) != $newmeral) + } { popMessage "Code failure! trying to change existing entry!" red } @@ -315,7 +349,5 @@ # given numeral and if found updates board in that location -proc scanAllEntitiesForOne {} { - - global rows cols squares +proc ::sud::scanAllEntitiesForOne {} { scanEntityForOne rows @@ -329,9 +361,12 @@ # in the associated entity type - row, column, or square -proc prunePossiblesPerEntity {entitytype} { +proc ::sud::prunePossiblesPerEntity {entitytype} { - global cellarray possarray - global rows cols squares - global arabicmode + variable cellarray + variable possarray + variable rows + variable cols + variable squares + variable arabicmode # each entity is a sub-list of 9 board cell index values @@ -341,13 +376,13 @@ # possible array, not the board array - foreach entity [subst $$entitytype] { - for {set index 0} {$index < 9} {incr index} { + foreach entities [set $entitytype] { + for {set i 0} {$i < 9} {incr i} { # cellindex points to board entry to test - set cellindex [lindex $entity $index] + set cellindex [lindex $entities $i] set cellvalue $cellarray($cellindex) if {[nineCheck $cellvalue]} { - # delete that value from each element of entity - for {set undex 0} {$undex < 9} {incr undex} { - set possindex [lindex $entity $undex] + # delete that value from each element of entities + for {set j 0} {$j < 9} {incr j} { + set possindex [lindex $entities $j] set smellvalue $cellvalue if {!$arabicmode} { @@ -368,7 +403,5 @@ # an existing board numeral in it's subsuming entities -proc pruneAllPossibles {} { - - global rows cols squares +proc ::sud::pruneAllPossibles {} { clearPossiblesPerEntry @@ -381,7 +414,7 @@ # ckeck for space or null -proc checkSpaceOrNull {x} { +proc ::sud::checkSpaceOrNull {x} { - return [expr {[string equal $x " "] || [string equal $x {}]}] + expr { $x eq " " || $x eq "" } } @@ -390,10 +423,10 @@ # kanji 0-9, space, null all OK -proc kanjiAllCheck {x} { +proc ::sud::kanjiAllCheck {x} { - global kanji1to9 + variable kanji1to9 - return [expr {([lsearch -exact -inline $kanji1to9 $x] != {}) \ - || [checkSpaceOrNull $x]}] + expr {([lsearch -exact -inline $kanji1to9 $x] != {}) + || [checkSpaceOrNull $x]} } @@ -402,8 +435,8 @@ # 0-9, space, null all OK -proc arabicAllCheck {x} { +proc ::sud::arabicAllCheck {x} { - return [expr {(([string is int -strict $x] && ($x >=0) && ($x<=9)) \ - || [checkSpaceOrNull $x])}] + expr {(([string is int -strict $x] && ($x >=0) && ($x<=9)) + || [checkSpaceOrNull $x])} } @@ -412,7 +445,7 @@ # kanji or arabic numeral based on flag -proc allCheck {x} { +proc ::sud::allCheck {x} { - global arabicmode + variable arabicmode if {$arabicmode} { @@ -426,7 +459,7 @@ # check for arabic 1-9 -proc arabicNineCheck {x} { +proc ::sud::arabicNineCheck {x} { - return [expr {[string is int -strict $x] && ($x >= 1) && ($x <= 9)}] + expr {[string is int -strict $x] && ($x >= 1) && ($x <= 9)} } @@ -434,9 +467,9 @@ # check for kanji 1-9 -proc kanjiNineCheck {x} { +proc ::sud::kanjiNineCheck {x} { - global kanji1to9 + variable kanji1to9 - return [expr {[lsearch -exact -inline $kanji1to9 $x] != {}}] + expr {[lsearch -exact $kanji1to9 $x] > -1} } @@ -444,7 +477,7 @@ # check for a numeral - arabic or kanji depending on flag -proc nineCheck {x} { +proc ::sud::nineCheck {x} { - global arabicmode + variable arabicmode if {$arabicmode} { @@ -453,6 +486,4 @@ return [kanjiNineCheck $x] } - -# return [expr {[string is int -strict $x] && ($x >= 1) && ($x <= 9)}] } @@ -461,7 +492,7 @@ # return question mark if invalid input -proc toKanji {arabic} { +proc ::sud::toKanji {arabic} { - global kanjiarray + variable kanjiarray if {[arabicNineCheck $arabic]} { @@ -477,7 +508,7 @@ -proc toArabic {kanji} { +proc ::sud::toArabic {kanji} { - global arabicarray + variable arabicarray if {[kanjiNineCheck $kanji]} { @@ -499,8 +530,8 @@ # and maybe don't change the original if "?" -proc allKanji {} { +proc ::sud::allKanji {} { - global cellarray - global arabicmode + variable cellarray + variable arabicmode if {!$arabicmode} { @@ -512,17 +543,15 @@ .sudoku.buttons.kanjiButton configure -relief sunken - for {set index 0} {$index < 81} {incr index} { - set cellarray($index) [toKanji $cellarray($index)] + for {set cell 0} {$cell < 81} {incr cell} { + set cellarray($cell) [toKanji $cellarray($cell)] } } -proc allArabic {} { +proc ::sud::allArabic {} { - global cellarray - global arabicmode + variable cellarray + variable arabicmode - if {$arabicmode} { - return - } + if {!$arabicmode} { set arabicmode TRUE @@ -530,6 +559,7 @@ .sudoku.buttons.kanjiButton configure -relief raised - for {set index 0} {$index < 81} {incr index} { - set cellarray($index) [toArabic $cellarray($index)] + for {set cell 0} {$cell < 81} {incr cell} { + set cellarray($cell) [toArabic $cellarray($cell)] + } } } @@ -538,11 +568,11 @@ # count the number of non-zero board entries UNUSED SO FAR -proc countEntries {} { +proc ::sud::countEntries {} { - global cellarray + variable cellarray set count 0 - for {set index 0} {$index < 81} {incr index} { - if {[nineCheck $cellarray($index)]} { + for {set cell 0} {$cell < 81} {incr cell} { + if {[nineCheck $cellarray($cell)]} { incr count } @@ -557,7 +587,7 @@ # validation routine checks textvariable contents, not key -proc validEntryKey {win index} { +proc ::sud::validEntryKey {win cell} { - global checkcolor + variable checkcolor # set CHECK button color to *something* since entry @@ -569,5 +599,5 @@ # "key" means we are calling validEntry due to keystroke(s) - after 0 validEntry "key" $win $index + after 0 ::sud::validEntry "key" $win $cell } @@ -586,5 +616,5 @@ # set error flag -# win is widget, key is key code, index is textvariable +# win is widget, key is key code, cell is textvariable # array index (some of this could be calculated) # why is "key" for keystroke(s) or "" @@ -594,19 +624,22 @@ # conversion FIRST -proc validEntry {why win index} { +proc ::sud::validEntry {why win cell} { - global cellbgcolorarray cellerrorcolor checkcolor - global invalidfound - global cellarray - global arabicmode + variable cellbgcolorarray + variable cellerrorcolor + variable cellarray - if {[string equal $why "key"] && !$arabicmode && \ - [arabicNineCheck $cellarray($index)]} { + variable invalidfound + variable arabicmode - set cellarray($index) [toKanji $cellarray($index)] + if {($why eq "key") + && !$arabicmode + && [arabicNineCheck $cellarray($cell)] + } { + set cellarray($cell) [toKanji $cellarray($cell)] } - if [allCheck $cellarray($index)] { - $win configure -bg $cellbgcolorarray($index) + if [allCheck $cellarray($cell)] { + $win configure -bg $cellbgcolorarray($cell) } else { $win configure -bg $cellerrorcolor @@ -620,8 +653,8 @@ # empty arg to validEntry means not due to keystroke(s) -proc validateAll {} { +proc ::sud::validateAll {} { - for {set index 0} {$index < 81} {incr index} { - validEntry "" .sudoku.board.cellentry$index $index + for {set cell 0} {$cell < 81} {incr cell} { + validEntry "" .sudoku.board.cellentry$cell $cell } } @@ -634,10 +667,13 @@ # use lindex at lowest level to avoid redundant checking -proc checkEntityType {entitytype} { +proc ::sud::checkEntityType {entitytype} { + + variable rows + variable cols + variable squares + variable cellarray - global celldupcolor - global cellarray - global rows cols squares - global duplicatesfound + variable celldupcolor + variable duplicatesfound # don't test non- 1-9 digit elements @@ -648,11 +684,11 @@ # element and other contain cell numbers under test - foreach entity [subst $$entitytype] { - for {set index 0} {$index < 8} {incr index} { - set element [lindex $entity $index] - for {set undex [expr $index + 1]} {$undex < 9} {incr undex} { - set other [lindex $entity $undex] + foreach entity [set $entitytype] { + for {set i 0} {$i < 8} {incr i} { + set element [lindex $entity $i] + for {set j [expr $i + 1]} {$j < 9} {incr j} { + set other [lindex $entity $j] if {[nineCheck $cellarray($element)] && [nineCheck $cellarray($other)]} { - if {[string equal $cellarray($element) $cellarray($other)] } { + if {$cellarray($element) eq $cellarray($other)} { .sudoku.board.cellentry$element configure -bg $celldupcolor .sudoku.board.cellentry$other configure -bg $celldupcolor @@ -668,8 +704,8 @@ # test all entities for duplicate entries -# if dupes found global duplicatesfound will be set TRUE +# if dupes found variable duplicatesfound will be set TRUE -proc checkAllEntityTypes {} { +proc ::sud::checkAllEntityTypes {} { checkEntityType rows @@ -683,10 +719,8 @@ # error flags set by called routines -proc checkAll {} { +proc ::sud::checkAll {} { - global duplicatesfound invalidfound - - set duplicatesfound FALSE - set invalidfound FALSE + variable duplicatesfound FALSE + variable invalidfound FALSE validateAll @@ -694,9 +728,11 @@ if {$duplicatesfound || $invalidfound} { - popMessage "Invalid or Duplicate Entry" red - setCheckButtonColor red - return + set color red + popMessage "Invalid or Duplicate Entry" $color + } else { + set color green } - setCheckButtonColor green + + setCheckButtonColor $color } @@ -704,9 +740,8 @@ # make sure we are in arabic mode at start -proc initArabicMode {} { +proc ::sud::initArabicMode {} { - global arabicmode + variable arabicmode TRUE - set arabicmode TRUE .sudoku.buttons.arabicButton configure -relief sunken .sudoku.buttons.kanjiButton configure -relief raised @@ -716,12 +751,12 @@ # initialize board -proc initBoard {} { +proc ::sud::initBoard {} { - global cellarray - global cellbgcolorarray + variable cellarray + variable cellbgcolorarray - for {set cellind 0} {$cellind < 81} {incr cellind} { - set cellarray($cellind) "" - set cellbgcolorarray($cellind) "" + for {set cell 0} {$cell < 81} {incr cell} { + set cellarray($cell) "" + set cellbgcolorarray($cell) "" } @@ -734,20 +769,21 @@ # create board # build display grid and initialize background color array -# build global textvariable and background color arrays here - -proc createBoard {} { +# build textvariable and background color arrays here - global cellarray cellbgcolorarray - global cellbgcolorA cellbgcolorB cellerrorcolor celldupcolor \ - cellchangedcolor checkcolor - - # background alternating colors, error colors - - set cellbgcolorA gray - set cellbgcolorB lightgray - set cellerrorcolor red - set celldupcolor orange - set cellchangedcolor white - set checkcolor yellow +proc ::sud::createBoard { + {bgColorA gray} + {bgColorB lightgray} + {errorColor red} + {dupColor orange} + {changedColor white} + {checkColor yellow} +} { + + variable cellbgcolorA $bgColorA + variable cellbgcolorB $bgColorB + variable cellerrorcolor $errorColor + variable celldupcolor $dupColor + variable cellchangedcolor $changedColor + variable checkcolor $checkColor buildGrid @@ -757,16 +793,16 @@ # add buttons to main window -proc createButtons {} { +proc ::sud::createButtons {} { button .sudoku.buttons.resetButton -text RESET -font {courrier 12} \ - -bg white -command initBoard + -bg white -command ::sud::initBoard button .sudoku.buttons.checkButton -text CHECK -font {courrier 12} \ - -bg white -command checkAll + -bg white -command ::sud::checkAll button .sudoku.buttons.stepButton -text SOLVE -font {courrier 12} \ - -bg white -command solveStep + -bg white -command ::sud::solveStep button .sudoku.buttons.arabicButton -text 123 -font {courrier 12} \ - -bg white -command allArabic + -bg white -command ::sud::allArabic button .sudoku.buttons.kanjiButton -text \u56db\u4e94\u516d -font {courrier 12} \ - -bg white -command allKanji + -bg white -command ::sud::allKanji set buttons [list .sudoku.buttons.resetButton .sudoku.buttons.checkButton \ @@ -784,5 +820,5 @@ # also runs check -proc solveStep {} { +proc ::sud::solveStep {} { setBackgroundColors @@ -817,12 +853,12 @@ # board array, set up the arabic <-> kanji translations -buildAssociations -buildTranslations +::sud::buildAssociations +::sud::buildTranslations # set up and initialize display grid and colors -createBoard -createButtons -initBoard +::sud::createBoard +::sud::createButtons +::sud::initBoard pack .sudoku.board .sudoku.buttons