Skip to content

Instantly share code, notes, and snippets.

@kerryb
Created Jul 15, 2011
Embed
What would you like to do?
My solution to Neil's bash masterclass exercise
#/bin/bash
#
# Number guessing game.
# A simple demo of bash capabilities
#
# neil.winton@bt.com
readonly MaxGuesses=6
readonly Timeout=10
function validate {
local answer="$1"
local interactive=$2
local status=1;
case "$answer" in
[0-9]|[0-9][0-9]|100)
: OK
status=0
;;
[0-9]*)
$interactive && echo "Look, I said a number between 1 and 100"
;;
*)
$interactive && echo "D'oh! I need a number!"
;;
esac
(( status != 0 )) && ! $interactive && echo "?"
return $status
}
interactive=true
if getopts n option
then
if [[ $option = 'n' ]]
then
interactive=false
elif [[ $option = '?' ]]
then
echo "Usage: $0 [-n]" >&2
exit 2
fi
fi
typeset -i magic=$((RANDOM % 100 + 1))
$interactive && cat <<EOF
I've thought of a number between 1 and 100.
You've got $MaxGuesses attempts to try to guess it.
Oh and you've only got $Timeout seconds for each guess!
Good luck!
EOF
typeset -i guess
typeset -a prompt
if $interactive
then
hiMsg="Sorry, that's too high"
loMsg="Sorry, that's too low"
timeoutMsg="\nWhoops, too slow! You've lost a life ..."
else
hiMsg=">"
loMsg="<"
timeoutMsg=""
fi
for ((guess = 1; guess <= MaxGuesses; guess++))
do
if $interactive
then
prompt=(-p "What's your guess? [$guess/$MaxGuesses] ")
else
prompt=()
fi
read -t $Timeout ${prompt[0]:+"${prompt[@]}"} answer
(( $? > 128 )) && {
echo -e $timeoutMsg
continue
}
validate $answer $interactive || continue
if (( answer == magic ))
then
# Got it
break
elif (( answer < magic ))
then
echo $loMsg
else
echo $hiMsg
fi
done
status=1
if ((guess > MaxGuesses))
then
$interactive && echo "I win! My number was $magic"
$interactive || echo $magic
else
$interactive && echo "Congratulations! You win!"
status=0
fi
exit $status
#!/bin/bash
#
# Plays the guessing game (see guess.sh above)
trap 'rm -f guesses replies' EXIT
mkfifo guesses replies
exec 3<> guesses
exec 4<> replies
(./guess.sh -n ; echo 'Correct!') < guesses > replies &
guess=50
min=0
max=100
while : ; do
if [ $guess -eq 69 ]; then
echo Guessing $guess, dude!
else
echo Guessing $guess
fi
echo $guess > guesses
read response < replies
echo Got back $response
case $response in
'<')
new_min=$guess
guess=$((max - ((max - guess) / 2)))
min=$new_min
;;
'>')
new_max=$guess
guess=$((guess - (guess - min)/ 2))
max=$new_max
;;
*)
exit
;;
esac
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment