Guess the number/With feedback

From Rosetta Code
Task
Guess the number/With feedback
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to write a game that follows the following rules:

The computer will choose a number between given set limits and asks the player for repeated guesses until the player guesses the target number correctly. At each guess, the computer responds with whether the guess was higher than, equal to, or less than the target - or signals that the input was inappropriate.

C.f: Guess the number/With Feedback (Player)

Ada

<lang Ada>with Ada.Numerics.Discrete_Random; with Ada.Text_IO; procedure Guess_Number_Feedback is

  procedure Guess_Number (Lower_Limit : Integer; Upper_Limit : Integer) is
     subtype Number is Integer range Lower_Limit .. Upper_Limit;
     package Number_IO is new Ada.Text_IO.Integer_IO (Number);
     package Number_RNG is new Ada.Numerics.Discrete_Random (Number);
     Generator  : Number_RNG.Generator;
     My_Number  : Number;
     Your_Guess : Number;
  begin
     Number_RNG.Reset (Generator);
     My_Number := Number_RNG.Random (Generator);
     Ada.Text_IO.Put_Line ("Guess my number!");
     loop
        Ada.Text_IO.Put ("Your guess: ");
        Number_IO.Get (Your_Guess);
        exit when Your_Guess = My_Number;
        if Your_Guess > My_Number then
           Ada.Text_IO.Put_Line ("Wrong, too high!");
        else
           Ada.Text_IO.Put_Line ("Wrong, too low!");
        end if;
     end loop;
     Ada.Text_IO.Put_Line ("Well guessed!");
  end Guess_Number;
  package Int_IO is new Ada.Text_IO.Integer_IO (Integer);
  Lower_Limit : Integer;
  Upper_Limit : Integer;

begin

  loop
     Ada.Text_IO.Put ("Lower Limit: ");
     Int_IO.Get (Lower_Limit);
     Ada.Text_IO.Put ("Upper Limit: ");
     Int_IO.Get (Upper_Limit);
     exit when Lower_Limit < Upper_Limit;
     Ada.Text_IO.Put_Line ("Lower limit must be lower!");
  end loop;
  Guess_Number (Lower_Limit, Upper_Limit);

end Guess_Number_Feedback;</lang>

AutoHotkey

<lang AutoHotkey>MinNum = 1 MaxNum = 99999999999

Random, RandNum, %MinNum%, %MaxNum% Loop {

InputBox, Guess, Number Guessing, Please enter a number between %MinNum% and %MaxNum%:,, 350, 130,,,,, %Guess%
If ErrorLevel
 ExitApp
If Guess Is Not Integer
{
 MsgBox, 16, Error, Invalid guess.
 Continue
}
If Guess Not Between %MinNum% And %MaxNum%
{
 MsgBox, 16, Error, Guess must be a number between %MinNum% and %MaxNum%.
 Continue
}
If A_Index = 1
 TotalTime = %A_TickCount%
Tries = %A_Index%
If Guess = %RandNum%
 Break
If Guess < %RandNum%
 MsgBox, 64, Incorrect, The number guessed (%Guess%) was too low.
If Guess > %RandNum%
 MsgBox, 64, Incorrect, The number guessed (%Guess%) was too high.

} TotalTime := Round((A_TickCount - TotalTime) / 1000,1) MsgBox, 64, Correct, The number %RandNum% was guessed in %Tries% tries, which took %TotalTime% seconds.</lang>

Clojure

<lang clojure>(defn guess-run []

 (let [start 1

end 100 target (+ start (rand-int (- end start)))]

   (printf "Guess a number between %d and %d" start end)
   (loop [i 1]
     (printf "Your guess %d:\n" i)
     (let [ans (read)]

(if (cond (not (number? ans)) (println "Invalid format") (or (< ans start) (> ans end)) (println "Out of range") (< ans target) (println "too low") (> ans target) (println "too high") true true) (println "Correct") (recur (inc i)))))))</lang>

Common Lisp

<lang lisp>(defun guess-the-number-feedback (&optional (min 1) (max 100))

 (let ((num-guesses 0)

(num (+ (random (1+ (- max min))) min)) (guess nil))

   (format t "Try to guess a number from ~:d to ~:d!~%" min max)
   (loop do (format t "Guess? ")

(incf num-guesses) (setf guess (read)) (format t "Your guess is ~[not a number.~;too small.~;too large.~;correct!~]~%" (cond ((not (numberp guess)) 0) ((< guess num) 1) ((> guess num) 2) ((= guess num) 3))) until (and (numberp guess) (= guess num)))

   (format t "You got the number correct on the ~:r guess!~%" num-guesses)))

</lang> Output:

CL-USER> (guess-the-number-feedback 1 1024)
Try to guess a number from 1 to 1,024!
Guess? 512
Your guess is too small.
Guess? 768
Your guess is too small.
Guess? 896
Your guess is too large.
Guess? 832
Your guess is too small.
Guess? 864
Your guess is too large.
Guess? 848
Your guess is too large.
Guess? 840
Your guess is too large.
Guess? 836
Your guess is correct!
You got the number correct on the eighth guess!

Fortran

Works with: Fortran version 95 and later

<lang fortran>program Guess_a_number

 implicit none
 
 integer, parameter :: limit = 100
 integer :: guess, number
 real :: rnum
 
 write(*, "(a, i0, a)") "I have chosen a number bewteen 1 and ", limit, &
                        " and you have to try to guess it." 
 write(*, "(a/)")  "I will score your guess by indicating whether it is higher, lower or the same as that number"

 call random_seed
 call random_number(rnum)
 number = rnum * limit + 1
 do
   write(*, "(a)", advance="no") "Enter quess: "
   read*, guess
   if(guess < number) then
     write(*, "(a/)") "That is lower"
   else if(guess > number) then
     write(*, "(a/)") "That is higher"
   else
     write(*, "(a)") "That is correct"
     exit
   end if
 end do

end program</lang> Output

I have chosen a number bewteen 1 and 100 and you have to try to guess it.
I will score your guess by indicating whether it is higher, lower or the same as that number.

Enter guess: 50
That is lower

Enter guess: 75
That is higher

Enter guess: 62
That is higher

Enter guess: 57
That is correct

Haskell

<lang haskell> import Control.Monad import System.Random

-- Repeat the action until the predicate is true. until_ act pred = act >>= pred >>= flip unless (until_ act pred)

answerIs ans guess =

 case compare ans guess of
   LT -> putStrLn "Too high. Guess again." >> return False
   EQ -> putStrLn "You got it!" >> return True
   GT -> putStrLn "Too low. Guess again." >> return False

-- Repeatedly read until the input *starts* with a number. (Since -- we use "reads" we allow garbage to follow it, though.) ask = do line <- getLine

        case reads line of
          ((num,_):_) -> return num
          otherwise -> putStrLn "Please enter a number." >> ask

main = do

 ans <- randomRIO (1,100) :: IO Int
 putStrLn "Try to guess my secret number between 1 and 100."
 ask `until_` answerIs ans

</lang>

J

<lang j>require 'misc' game=: verb define

 assert. y -: 1 >. <.{.y
 n=: 1 + ?y
 smoutput 'Guess my integer, which is bounded by 1 and ',":y
 whilst. -. x -: n do.
   x=. {. 0 ". prompt 'Guess: '
   if. 0 -: x do. 'Giving up.' return. end. 
   smoutput (*x-n){::'You win.';'Too high.';'Too low.'
 end.

)</lang>

Note: in computational contexts, J programmers typically avoid loops. However, in contexts which involve progressive input and output and where event handlers are too powerful (too complicated), loops are probably best practice.

Example use:

<lang> game 100 Guess my integer, which is bounded by 1 and 100 Guess: 64 Too high. Guess: 32 Too low. Guess: 48 Too high. Guess: 40 Too low. Guess: 44 You win.</lang>

JavaScript

Note: This would work if inserted into a blank HTML page's script tag.

<lang javascript>document.write('

Pick a number between 1 and 100.


' +

'<input type="text" id="guess"><input type="button" value="Submit Guess" id="submit">' +

'

');

var number = undefined,

   submit = document.getElementById('submit'),
   guess = document.getElementById('guess');

function newNumber(){

   number = Math.ceil(Math.random() * 100);
   // No var statement, so we reset the global number variable.
   console.log(number);
   // This way we can check the answer.

}

newNumber();

function verify(){

   var guess = document.getElementById('guess').value,
       output = document.getElementById('output');
   if(isNaN(guess)){
       output.innerHTML = "Enter a number. Not letters."
   } else if(number == guess){
       output.innerHTML = "You guessed right!";
   } else if(guess > 100){
       output.innerHTML = "Your guess is out of the 1 to 100 range."
   } else if(guess < number){
       output.innerHTML = "Nope. Guess higher."
   } else if(guess > number){
       output.innerHTML = "Nope. Guess smaller."
   }

}

submit.onclick = verify; guess.onkeypress = function(event){

   var value = this.value;
   if(event.keyCode == 13){
       // This way we can just hit Enter,
       // and not necessarily click the Submit Guess button.
       verify();
   }

} </lang>


OCaml

<lang ocaml>let rec _read_int() =

 try read_int()
 with _ ->
   print_endline "Please give a cardinal numbers.";
   (* TODO: what is the correct word? cipher, digit, figure or numeral? *)
   _read_int() ;;

let () =

 print_endline "Please give a set limits (two integers):";
 let a = _read_int()
 and b = _read_int() in
 let a, b =
   if a < b
   then (a, b)
   else (b, a)
 in
 Random.self_init();
 let target = a + Random.int (b - a) in
 Printf.printf "I have choosen a number between %d and %d\n%!" a b;
 print_endline "Please guess it!";
 let rec loop () =
   let guess = _read_int() in
   if guess = target then
   begin
     print_endline "The guess was equal to the target.\nCongratulation!";
     exit 0
   end;
   if guess < a || guess > b then
     print_endline "The input was inappropriate."
   else if guess > target then
     print_endline "The guess was higher than the target."
   else if guess < target then
     print_endline "The guess was less than the target.";
   loop ()
 in
 loop ()</lang>

Playing the game:

$ ocaml inapropriate.ml
Please give a set limits (two integers):
3
7
I have choosen a number between 3 and 7
Please guess it!
6
The guess was higher than the target.
7
The guess was higher than the target.
8
The input was inappropriate.
3
The guess was less than the target.
4
The guess was equal to the target.
Congratulation!
$ ocaml inapropriate.ml
Please give a set limits (two integers):
2
6
I have choosen a number between 2 and 6
Please guess it!
three
Please give a cardinal numbers.

PARI/GP

<lang parigp>guess_the_number(N=10)={ a=random(N); print("guess the number between 0 and "N); for(x=1,N, if(x>1, if(b>a, print("guess again lower") , print("guess again higher") ); b=input(); if(b==a,break()) ); print("You guessed it correctly") };</lang>

Perl

<lang Perl>#!/usr/bin/perl -w use strict ; use warnings ;

sub validateInput {

  my $dataentry = shift ;
  chomp $dataentry ;
  while ( $dataentry !~ m/^\b\d+\b$/ ) {
     print "Incorrect data entry! Please guess again!\n" ;
     $dataentry = <STDIN> ;
     chomp $dataentry ;
  }
  return $dataentry ;

}

my $times_guessed = 0 ; my $lowerborder = 0 ; print "Which upper border do you want me to set?\n" ; my $upperborder = <STDIN> ; $upperborder = validateInput( $upperborder ) ; my $targetnumber = int( rand ( $upperborder + 1 ) ) ; print "Try to guess a number from $lowerborder to $upperborder!\n" ; my $guessinput = <STDIN> ; $guessinput = validateInput( $guessinput ) ; while ( $guessinput != $targetnumber ) {

  if ( $guessinput < $targetnumber ) {
     print "Your guess is too small!\n" ;
  }
  else {
     print "Your guess is too large!\n" ;
  }
  $times_guessed++ ;
  $guessinput = <STDIN> ;
  $guessinput = validateInput( $guessinput ) ;

} print "Your guess is correct!\n" ; print "It took you $times_guessed attempts to guess the correct number!\n" ;</lang> Sample output:

Which upper border do you want me to set?
24
Try to guess a number from 0 to 24!
12
Your guess is too large!
6
Your guess is too large!
3
Your guess is too large!
2
Your guess is correct!
It took you 3 attempts to guess the correct number!

PicoLisp

Translation of: PureBasic

<lang PicoLisp>(de guessTheNumber ()

  (use (Low High Guess)
     (until
        (and
           (prin "Enter low limit : ")
           (setq Low (read))
           (prin "Enter high limit: ")
           (setq High (read))
           (> High Low) ) )
     (seed (time))
     (let Number (rand Low High)
        (loop
           (prin "Guess what number I have: ")
           (T (= Number (setq Guess (read)))
              (prinl "You got it!") )
           (prinl
              "Your guess is too "
              (if (> Number Guess) "low" "high")
              "." ) ) ) ) )</lang>

Output:

: (guessTheNumber)
Enter low limit : 1
Enter high limit: 64
Guess what number I have: 32
Your guess is too high.
Guess what number I have: 16
Your guess is too low.
Guess what number I have: 24
You got it!

PureBasic

<lang PureBasic>OpenConsole()

Repeat

 ; Ask for limits, with sanity check
 Print("Enter low limit : "): low  =Val(Input())
 Print("Enter high limit: "): High =Val(Input())

Until High>low

TheNumber=Random(High-low)+low Debug TheNumber Repeat

 Print("Guess what number I have: "): Guess=Val(Input())
 If Guess=TheNumber
   PrintN("You got it!"): Break
 ElseIf Guess < TheNumber
   PrintN("Your guess is to low.")
 Else
   PrintN("Your guess is to high.")
 EndIf

ForEver</lang>

Python

<lang python>import random

inclusive_range = (1, 100)

print("Guess my target number that is between %i and %i (inclusive).\n"

     % inclusive_range)

target = random.randint(*inclusive_range) answer, i = None, 0 while answer != target:

   i += 1
   txt = input("Your guess(%i): " % i)
   try:
       answer = int(txt)
   except ValueError:
       print("  I don't understand your input of '%s' ?" % txt)
       continue
   if answer < inclusive_range[0] or answer > inclusive_range[1]:
       print("  Out of range!")
       continue
   if answer == target:
       print("  Ye-Haw!!")
       break
   if answer < target: print("  Too low.")
   if answer > target: print("  Too high.")

print("\nThanks for playing.")</lang>

Sample Game

Guess my target number that is between 1 and 100 (inclusive).

Your guess(1): 50
  Too high.
Your guess(2): 25
  Too low.
Your guess(3): 40
  Too high.
Your guess(4): 30
  Too low.
Your guess(5): 35
  Too high.
Your guess(6): 33
  Too high.
Your guess(7): 32
  Too high.
Your guess(8): 31
  Ye-Haw!!

Thanks for playing.

Sample trapped Errors

Guess my target number that is between 1 and 100 (inclusive).

Your guess(1): 0
  Out of range!
Your guess(2): 101
  Out of range!
Your guess(3): Howdy
  I don't understand your input of 'Howdy' ?
Your guess(4): 

REXX

<lang rexx>/*REXX program that plays the guessing (the number) game. */

low=1                /*lower range for the guessing game.*/

high=100 /*upper range for the guessing game.*/ try=0 /*number of valid attempts. */ r=random(1,100) /*get a random number (low-->high). */

lows='low small below puny'

highs='high big above huge'

 do forever
 say
 say "guess the number, it's between" low 'and',
     high '(inclusive)   ---or---  QUIT:'
 say
 pull g
 say
 g=space(g)
 if g== then iterate
 if g=='QUIT' then exit
 if \datatype(g,'W') then do
                          call ser g "isn't a whole number"
                          iterate
                          end
 if g<low then do
               call ser g 'is below the lower limit of' low
               iterate
               end
 if g>high then do
                call ser g 'is above the higher limit of' low
                iterate
                end
 try=try+1
 if g==r then leave
 if g>r then what=word(highs,random(1,words(highs)))
        else what=word( lows,random(1,words( lows)))
 say 'your guess of' g "is" what'.'
 end

tries='tries' if try==1 then do; try='one'; tries="try"; end say say 'Congratulations!, you guessed the number in' try tries"." say exit


ser: say; say '*** error ! ***'; say arg(1); say; return</lang>

Tcl

<lang tcl>set from 1 set to 10 set target [expr {int(rand()*($to-$from+1) + $from)}] puts "I have thought of a number from $from to $to." puts "Try to guess it!" while 1 {

   puts -nonewline "Enter your guess: "
   flush stdout
   gets stdin guess
   if {![string is int -strict $guess] || $guess < $from || $guess > $to} {

puts "Your guess should be an integer from $from to $to (inclusive)."

   } elseif {$guess > $target} {

puts "Your guess was too high. Try again!"

   } elseif {$guess < $target} {

puts "Your guess was too low. Try again!"

   } else {

puts "Well done! You guessed it." break

   }

}</lang> Sample output:

I have thought of a number from 1 to 10.
Try to guess it!
Enter your guess: 2
Your guess was too low. Try again!
Enter your guess: skfg
Your guess should be an integer from 1 to 10 (inclusive).
Enter your guess: 9
Your guess was too high. Try again!
Enter your guess: 5
Your guess was too low. Try again!
Enter your guess: 7
Your guess was too high. Try again!
Enter your guess: 6
Well done! You guessed it.