Welcome!

Linux Authors: Michael Sheehan, Lavenya Dilip, Ian Thain, Bruce Armstrong, Ellen Rubin

Related Topics: Linux

Linux: Article

Loops Within Loops: "hilow.sh"

The hi-low game

If the print gods are with us, this time, after seven previous columns, we'll finally have a shell script that you can type in and experiment with. Imagine!

The last column addressed the challenges of generating a reasonably random number to enable us to write a rudimentary hi-low guessing game. After experimentation, we settled on using the date command with some fancy footwork to generate a number between 1..x as shown here:


toguess="$(expr `date +%S` % 20 + 1)"

In this case, the result is a quasi-random number between 1 and 20. Good enough for our game, which involves the computer picking a number and then you guessing that number. If you guess too high, it'll prompt "lower," and if you guess too low, it indicates "higher." Not quite as complex as the shell script implementation of Halo 2, but let's start with something manageable.

Basic Looping Structures

The core looping structure of the hi-low game is a while loop, which takes the form:


	while condition
	do
	   statements
	done

The condition is a test statement, though use the "[" shortcut to make it a bit cleaner. For this game, I'm going to let the player have a maximum of 10 guesses, which looks like this:


while [ $guesses -lt 10 ]
do
 	  statements
done

The first requirement of the statements within this loop is a statement that keeps track of how many guesses have been entered (which is the same as how many times the script has cycled through the loop). This is done with the modern shell $(( )) math notation:


guesses=$(( $guesses + 1 ))

If you're running a crufty old shell, it might toss up on that statement (even though it's the Posix way of doing things). If so, just replace it with the old fashioned statement


	guesses= "$(expr $guesses + 1)"

The other statement blocks required are user input and a conditional test sequence.

Reading User Input

You already know that echo is the standard method of having shell scripts produce output, but might not know that read is the equivalent for input. Further, since it's nice to have the prompt for input on the same line as the cursor when you're asking for the user to type something in, it's useful to add the "-n" flag to echo. The prompt and input look like this:


echo -n "Guess? "
read answer

Notice that this is the only time when you'll reference a shell variable without the "$" prefix: if you tried read $answer you'd get an error.

Testing User Input

There are a number of different ways to test the guess against the secret value, but I just use a simple if-then-else sequence for clarity:


if [ $answer -eq $toguess ]
then
    echo "Got it!  Guesses = $guesses"
    exit 0
elif [ $answer -lt $toguess ]
then
    echo "higher"
else
    echo "lower"
fi

Again, this should be straightforward: if they've guessed the correct value, output a success message, show how many guesses it took, and exit the script. Otherwise, if the answer is too low, suggest "higher," and if it's too high, suggest "lower."

Putting It All Together

Those are all the pieces; let's put it all together in a single listing:


#!/bin/sh

toguess="$(expr `date +%S` % 20 + 1)"

guesses=1

while [ $guesses -lt 10 ]
do
  echo -n "Guess? "
  read answer
  if [ $answer -eq $toguess ]
  then
    echo "Got it!  Guesses = $guesses"
    exit 0
  elif [ $answer -lt $toguess ]
  then
    echo "higher"
  else
    echo "lower"
  fi
  guesses=$(( $guesses + 1 ))
done

echo "Too many guesses. Number was $toguess"

exit 0

And, since this is a family magazine, let's have a quick game:


$ sh hilow.sh
Guess? 10
higher
Guess? 15
higher
Guess? 17
higher
Guess? 19
lower
Guess? 18
Got it!  Guesses = 5

There we go! Try modifying this script yourself to learn more about scripting. One simple change: make the game harder by having the range of guesses be 1-100 (or more!) or make it really frustrating by changing the number every five guesses, but still only allow a fixed number of guesses.

More Stories By Dave Taylor

Dave Taylor, a contributing editor to Linux.SYS-CON.com, has been involved with the Linux and Unix community since 1980 and has written a number of best-selling Unix books. Currently, he writes, teaches, and works as a management consultant to tech startups, along with his new venture, Ask Dave Taylor!, www.askdavetaylor.com and his personal blog is www.blog.Linux.SYS-CON.com. To contact Dave, please go to /www.intuitive.com/contact.shtml.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.