HiLo

Summary

HJG HiLo is a simple number-guessing game: for each guess, you get the answer "too high" or "too low", until you guess right.

With this game, you can explain how binary seaching works.

Code


 #! /usr/bin/tclsh

 # HiLo.tcl - HaJo Gurt - 2005-06-20
 # Simple Guess-the-number - game
 #
 # !! Run this in tclsh84 - wish has a bug with "gets" !!
 # See also: https://wiki.tcl-lang.org/10794 - [gets workaround]

  proc input1 {prompt} {
  #: Get input from user
    puts -nonewline $prompt
    set n [gets stdin]   ;# implicit return
  }

  proc input {prompt} {
  #: Get input from user, accept only numbers
    set ok 0
    while {$ok==0} {
      puts -nonewline $prompt
      set n [gets stdin]
      set ok [string is integer -strict $n] 
      if {$ok==0} { puts "'$n' is invalid !\a" }  ;# "\a": bell
    }
    return $n
  }

  proc inputA {prompt} {
  #: Test: "Automatic" input, simulates user
    puts -nonewline $prompt
    incr ::x             ;# Global variable x
  }

  proc random { {range 100} } {
  #: Return a number in the range 0 .. $range-1
    return [expr {int(rand()*$range)}]
  }

 #########.#########=#########^#########+#########*#########_#########$#####

  proc HiLo { {Max 100} } {
  #: Play the game
   #set Secret 11   ;# Test
    set Secret [expr {[random $Max] +1 }]

    puts "Guess my number (1 .. $Max)"
    set Try  0
    while 1 {
      incr Try
      set Guess [ input "Your guess #$Try: " ]     ;# Test: Replace "input" with "inputA"
      if {$Guess <  $Secret} { puts "$Guess is too low"  }
      if {$Guess >  $Secret} { puts "$Guess is too high" }
      if {$Guess == $Secret} { puts "$Guess is correct - You needed $Try guesses."; break }
      if {$Try >= 12}        { puts "You won't guess it..."; break }   ;# Emergency-break
    }
    puts "Bye!"
  }
 #########.#########=#########^#########+#########*#########_#########$#####

  set x 0               ;# Test: starting value for inputA
  catch {console show}  ;# when running in wish: open console-window

 #HiLo 1024
  HiLo                  ;# default: 100

Comments

A version of HiLo with a full GUI is at HiLo2, and an international version (using msgcat) at HiLo-international.

HJG It looks like the biggest problem with this program is the simple gets for reading from the user.
Even the FAQ at https://www.tcl-lang.org/man/tcl8.4/TclCmd/gets.htm and the tutorial at tcltutorial doesn't have useful information about this...

Is there a simpler way for "input" than gets workaround, e.g. without a gui ?

MG If you're using wish / Tk and have a GUI, you could have an entry widget where it can entered, and print the messages to a (deactivated, so it can't be altered) text widget. The entry widget would also allow for easy validation of the input - in the above, for instance, you could enter text or other non-numeric data, which would still work as being greater/less than the number in question.

HJG I'm not sure what you mean, concerning gets. In tclsh84 gets works fine, but in wish gets returns an empty string.

LV What operating system and version of Tcl are you using? My guess is that you are using Windows (or you are launching the Tk application from a menu or launch button where no stdin is available), because I've used gets and Tk together on Solaris and they worked okay if the user started the application up from a console that had stdin and stdout set up. I do remember reading about issues with stdin and stdout on Windows, and needing to ensure that a console was open for the user to see the information. I just tried the following:

# in a cygwin ksh xterm
$ cat tst.tk
#! wish
package require Tk

console show

puts "This is a test"
set ans gets stdin
puts $ans

button .e -text Exit -command {exit 0;}
$ wish tst.tk
This is a test
testing
testing

On the screen is a Tk console as well as a button . I press the button and the application terminates. So I see the stdout, I type in the stdin and the application sees it. And I see the Tk button. So it all seems to work on this Windows XP system, using ActiveTcl 8.4.10.1.

So I would like this behavior of gets under wish fixed, preferably with something simpler than the gets workaround from RS, because GUI-elements in a text-environment look somewhat strange. - RS One should always use tclsh these days, and package require Tk where needed. This way, stdin should remain available...

HJG I tried that, but then scripts which use Tk keep their console window - that does not look good. I cannot get rid of it with "console hide", and "wm withdraw ." hides the Tk-window. On the page tclsh vs. wish I could not find advice about this, and it looks like most scripts here in the wiki use wish without "package require Tk".

LV If you are writing a graphical user interface, then don't use gets to get input from the user - use an entry widget or a text widget.