Table of Contents

Guess a Number (Bash Script Implementation)

To get us going on shell scripting, here are some variations of the “Guess a number” script we started writing in class.

Look through them, try them out, and make sure everything is making sense (if not, PLEASE ASK).

Round One: Yes or No

#!/bin/bash
#
# guess.sh - guess the number the computer has chosen (1 try)
#
value=`bc -q <<< "(${RANDOM} % 10) + 1"`
 
echo -n "Pick a value (1-10): "
read num
 
if [ "${num}" -eq "${value}" ]; then
    echo "You guessed correctly!"
else
    echo "You did not guess the number."
fi
 
exit 0

Round Two: Yes, High, or Low

#!/bin/bash
#
# guess.sh - guess the number the computer has chosen (1 try)
#            now with an elif
#
value=`bc -q <<< "(${RANDOM} % 10) + 1"`
 
echo -n "Pick a value (1-10): "
read num
 
if [ "${num}" -eq "${value}" ]; then
    echo "You guessed correctly!"
elif [ "${num}" -lt "${value}" ]; then
    echo "Too low"
else
    echo "Too high"
fi
 
exit 0

Round Three: 6 tries to guess (for loop)

#!/bin/bash
#
# guess.sh - guess the number the computer has chosen (1 try)
#            now with a for loop
#
value=`bc -q <<< "(${RANDOM} % 10) + 1"`
 
for ((i=1; i<=6; i++)); do
    echo -n "[Guess ${i}/6] Pick a value (1-10): "
    read num
 
    if [ "${num}" -eq "${value}" ]; then
        echo "You guessed correctly!"
        break
    elif [ "${num}" -lt "${value}" ]; then
        echo "Too low"
    else
        echo "Too high"
    fi
done
 
if [ "${i}" -eq 7 ]; then
    echo "Too bad, my pick was ${value}"
fi
 
exit 0

Round Four: user-specified tries to guess (while loop)

#!/bin/bash
#
# guess.sh - guess the number the computer has chosen (1 try)
#            now with a while loop
#
 
##
## Collect required information from the user
##
echo -n "Please enter the lower range for the computer's choice: "
read lower
 
echo -n "Please enter the upper range for the computer's choice: "
read upper
 
# Make sure we have correct relationships for our range
if [ "${lower}" -ge "${upper}" ]; then
    echo "Range values non-conformant"
    exit 1
fi
 
echo -n "How many tries do you wish to have? (1-100): "
read tries
 
# Make sure we have a correct choice
if [ ! "${tries}" -gt 0 ] || [ ! "${tries}" -le 100 ]; then
    echo "Invalid range, MUST be somewhere 1 through 100."
    exit 1
fi
 
##
## Computer's pick
##
 
# Adjust upper variable with respect to lower variable for appropriate range
let highval=${upper}-lower
 
value=`bc -q <<< "(${RANDOM} % ${highval}) + ${lower}"`
 
##
## Main program
##
i=1
while [ "${i}" -le "${tries}" ]; do
    echo -n "[Guess ${i}/${tries}] Pick a value (${lower}-${upper}): "
    read num
 
    if [ "${num}" -eq "${value}" ]; then
        echo "You guessed correctly!"
        i=0
        break
    elif [ "${num}" -lt "${value}" ]; then
        echo "Too low"
    else
        echo "Too high"
    fi
 
    let i=${i}+1
done
 
##
## Check to see if we are out of luck/game over
##
if [ "${i}" -gt 0 ]; then
    echo "Too bad, my pick was ${value}"
fi
 
exit 0

Rounds three and four could each have been done with a for loop OR a while loop. When a while is used, if we need to maintain a count, we need to do it ourselves, whereas with the for loop, it takes care of it as part of the loop.

The choice of loop to use is dependent upon your choosing; there really isn't a functional difference between them, although as indicated the resulting algorithm may need to be tweaked one way or the other to accommodate the desired intent of the script.

Round Five: Round four but using a function

#!/bin/bash
#
# guess.sh - guess the number the computer has chosen (1 try)
#            now with functions
#
 
function determine {
    if [ "${num}" -eq "${value}" ]; then
        echo "You guessed correctly!"
        i=0
        break
    elif [ "${num}" -lt "${value}" ]; then
        echo "Too low"
    else
        echo "Too high"
    fi
}
 
function init {
    ##
    ## Collect required information from the user
    ##
    echo -n "Please enter the lower range for the computer's choice: "
    read lower
 
    echo -n "Please enter the upper range for the computer's choice: "
    read upper
 
    # Make sure we have correct relationships for our range
    if [ "${lower}" -ge "${upper}" ]; then
        echo "Range values non-conformant"
        exit 1
    fi
 
    echo -n "How many tries do you wish to have? (1-100): "
    read tries
 
    # Make sure we have a correct choice
    if [ ! "${tries}" -gt 0 ] || [ ! "${tries}" -le 100 ]; then
        echo "Invalid range, MUST be somewhere 1 through 100."
        exit 1
    fi
}
 
function pick {
    ##
    ## Computer's pick
    ##
 
    # Adjust upper variable with respect to lower variable for appropriate range
    let highval=${upper}-lower
 
    value=`bc -q <<< "(${RANDOM} % ${highval}) + ${lower}"`
}
 
##
## Main program
##
init
pick
 
i=1
while [ "${i}" -le "${tries}" ]; do
    echo -n "[Guess ${i}/${tries}] Pick a value (${lower}-${upper}): "
    read num
 
    determine
 
    let i=${i}+1
done
 
##
## Check to see if we are out of luck/game over
##
if [ "${i}" -gt 0 ]; then
    echo "Too bad, my pick was ${value}"
fi
 
exit 0

For those familiar with function in other languages, notice how we are just blatantly using variables, regardless of location. It would appear that bash prefers global scope for its variables (something to keep in mind).

Round Six: Round five with command-line args and function parameters

#!/bin/bash
#
# guess.sh - guess the number the computer has chosen (1 try)
#            now with command-line arguments and function parameters
#
 
function determine {
    you="${1}"
    computer="${2}"
 
    if [ "${you}" -eq "${computer}" ]; then
        echo "You guessed correctly!"
        i=0
        break
    elif [ "${you}" -lt "${computer}" ]; then
        echo "Too low"
    else
        echo "Too high"
    fi
}
 
function init {
    ##
    ## Collect required information from the user
    ##
    if [ "$#" -ge 1 ]; then
        lower="${1}"
    else
        echo -n "Please enter the lower range for the computer's choice: "
        read lower
    fi
 
    if [ "$#" -ge 2 ]; then
        upper="${2}"
    else
        echo -n "Please enter the upper range for the computer's choice: "
        read upper
    fi  
 
    # Make sure we have correct relationships for our range
    if [ "${lower}" -ge "${upper}" ]; then
        echo "Range values non-conformant"
        exit 1
    fi
 
    if [ "$#" -eq 3 ]; then
        tries="${3}"
    else
        echo -n "How many tries do you wish to have? (1-100): "
        read tries
    fi
 
    # Make sure we have a correct choice
    if [ ! "${tries}" -gt 0 ] || [ ! "${tries}" -le 100 ]; then
        echo "Invalid range, MUST be somewhere 1 through 100."
        exit 1
    fi
}
 
function pick {
    ##
    ## Computer's pick
    ##
    lo="${1}"
    hi="${2}"
 
    # Adjust upper variable with respect to lower variable for appropriate range
    let highval=${hi}-${lo}
 
    value=`bc -q <<< "(${RANDOM} % ${highval}) + ${lo}"`
}
 
##
## Main program
##
init ${1} ${2} ${3}
pick ${lower} ${higher}
 
i=1
while [ "${i}" -le "${tries}" ]; do
    echo -n "[Guess ${i}/${tries}] Pick a value (${lower}-${upper}): "
    read num
 
    determine ${num} ${value}
 
    let i=${i}+1
done
 
##
## Check to see if we are out of luck/game over
##
if [ "${i}" -gt 0 ]; then
    echo "Too bad, my pick was ${value}"
fi
 
exit 0

Here we make use of command-line arguments (the $1, $2, $3, …, $n; and $# variables), to specify potential values for upper, lower, and tries from the command-line, as follows:

lab46:~$ ./guess.sh 1 10 3
[Guess 1/3] Pick a value (1-10): 

Where if we had left them out:

lab46:~$ ./guess.sh
Please enter the lower range for the computer's choice:

We're also pretending some of the variables aren't global scope (function parameters are also $1, $2, $3, etc. just set to whatever values were passed to them).