HJG HiLo is a simple number-guessing game: for each guess, you get the answer "too high" or "too low", until you guess right.
#!/bin/sh # Restart with tcl: -*- mode: tcl; tab-width: 4; -*- \ exec wish $0 ${1+"$@"} #: HiLo-international.tcl - HaJo Gurt - 2005-10-31 #: Simple number-guessing-game, international version with msgcat # # 2005-06-21 First release / PT: Portuguese messages # 2005-07-03 Text-highlights # 2005-10-31 IT: Italian messages #########1#########2#########3#########4#########5#########6#########7##### package require Tk package require msgcat namespace import msgcat::mc msgcat::mcset # Tcl 8.4 initializes the locale from ::env(LC_ALL) or ::env(LC_MESSAGES), # but on Windows these might not be set, so you have to select yourself: #msgcat::mclocale en msgcat::mclocale de ;# <=====<< Select language # Load messages from file: #msgcat::mcload [file join [file dirname [info script]] msgs] # EN (alternative wording): mcset en "You needed %d guesses." "Number of guesses: %d" # To avoid "You needed 1 guesses." # DE - German messages: mcset de "HiLo-international" "Zahlenraten-International" mcset de "New game" "Neues Spiel" mcset de "Guess" "Eingabe" mcset de "Guess my number" "Raten Sie meine Zahl" mcset de "%d is too low" "%d ist zu niedrig" mcset de "%d is too high" "%d ist zu hoch" mcset de "%d is correct." "%d ist richtig." #mcset de "You needed %d guesses." "Sie haben %d Versuche gebraucht." # ....+....1....+....2....+....3.. mcset de "You needed %d guesses." "Anzahl Rateversuche: %d" ;# shorter # IT - Italian messages: mcset it "HiLo-international" "Alto-Basso Internazionale" mcset it "New game" "Nuovo gioco" mcset it "Guess" "Indovina" mcset it "Guess my number" "Indovina il mio numero" mcset it "%d is too low" "%d troppo basso" mcset it "%d is too high" "%d troppo alto" mcset it "%d is correct." "%d giusto." mcset it "You needed %d guesses." "Numero di tentativi : %d" # PT - Portuguese messages: mcset pt "HiLo-international" "Adivinhe meu número" mcset pt "New game" "Novo jogo" mcset pt "Guess" "Palpite" mcset pt "Guess my number" "Adivinhe meu número" mcset pt "%d is too low" "%d é muito baixo" mcset pt "%d is too high" "%d é muito alto" mcset pt "%d is correct." "%d está correto" #mcset pt "You needed %d guesses." "Você precisou de %d tentativas." mcset pt "You needed %d guesses." "Você acertou em %d tentativas." #########1#########2#########3#########4#########5#########6#########7##### proc random { {range 100} } { #: Return a number in the range 0 .. $range-1 return [expr {int(rand()*$range)}] } proc Disp { {w .res1} {str ""} {tag ""} } { #: Output string to one of the text-widgets $w insert end "\n" $w insert end $str $tag $w see end ;# scroll to bottom } proc Disable {} { #: Disable entry-widget, highlight frame around Newgame-Button .f2a config -bg green .f2b config -bg grey .inp1 config -state readonly } proc NewGame {} { #: Start a new game, put GUI in start-position set ::nGuess 0 #set ::Secret 13 set ::Secret [expr {[random $::Max] +1 }] .f2a config -bg grey .f2b config -bg green .inp1 config -state normal .res1 delete 0.0 end .res2 delete 0.0 end Disp .res1 " [mc "Guess my number"]:\n" Hi Disp .res2 " (1 .. $::Max)\n" Hi } proc TestNum {str} { #: Validate input into entry-widget: Check if input is numeric set ok [string is integer $str] if {$ok==0} {bell} ;# alert: invalid input return $ok } #########1#########2#########3#########4#########5#########6#########7##### proc Update {} { #: Process input from entry-widget, update display global Secret Guess nGuess # Check input: if {$Guess eq ""} { bell ;# alert: empty input } else { incr nGuess if {$Guess < $Secret} { Disp .res1 [mc "%d is too low" $Guess] } if {$Guess > $Secret} { Disp .res2 [mc "%d is too high" $Guess] } if {$Guess == $Secret} { Disable Disp .res1 [mc "%d is correct." $Guess] Ok Disp .res1 [mc "You needed %d guesses." $nGuess]; } } set Guess "" ;# clear input-field } #########1#########2#########3#########4#########5#########6#########7##### proc Init {} { #: Initialize values, build GUI global Max Secret Guess nGuess set Max 100 frame .f1 frame .f2 -padx 2 -relief ridge -borderwidth 3 pack .f1 .f2 -padx 2 -pady 2 frame .f2a -borderwidth 3 frame .f2x ;# Frame for spacer frame .f2b -borderwidth 3 pack .f2a .f2x .f2b -in .f2 -side left -padx 2 -pady 2 -fill y text .res1 -width 25 -height 10 text .res2 -width 20 -height 10 pack .res1 .res2 -in .f1 -side left # Styles for text-highlights: .res1 tag configure "Hi" -background lightblue -underline 1 .res2 tag configure "Hi" -background lightblue -underline 0 .res1 tag configure "Ok" -background red -foreground white tk_optionMenu .opt1 Max 16 32 64 100 128 256 512 1000 1024 2048 4096 8192 button .but1 -text [mc "New game"] -command {NewGame} label .lx -text "" -anchor c -padx 4 -bg grey ;# Spacer label .lab1 -text "[mc "Guess"]:" entry .inp1 -width 5 -textvariable Guess -validate key -validatecommand {TestNum %P} pack .opt1 .but1 -in .f2a -side left -padx 2 -pady 2 pack .lx -in .f2x pack .lab1 .inp1 -in .f2b -side left -padx 2 -pady 2 bind .inp1 <Return> {Update} #wm title . "HiLo-international" wm title . [mc HiLo-international] focus -force .inp1 } Init NewGame
HJG Another small demo for using msgcat.
The GUI is done with frames, pack, entry, tk_optionMenu and two text-areas for output.
These are used to separate the "too low" and "too high"-results.
See also: HiLo (the Tcl / text-only-version) and HiLo2 (the simple GUI-version without msgcat).
gold 9/20/2020, added pix, # TCL source code above left unchanged.