Version 17 of HiLo

Updated 2007-01-25 19:18:05 by LV

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.


 #! /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: http://wiki.tcl.tk/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

HJG It looks like the biggest problem with this program is the simple gets for reading from the user. Even the FAQ at http://www.tcl.tk/man/tcl8.4/TclCmd/gets.htm and the tutorial at http://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html 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. 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.

A version of HiLo with a full GUI is at HiLo2, and an international version at HiLo-international


Category Games