Scissors, Paper or Rock?

It's considerably more fun to have the computer prompt users for their selection, then "choose" its own and decide who won.

Making It into a Game

Interactivity is easily added by prompting users to choose whether they want rock, paper or scissors using a numeric value. Even better, you can prompt them using the same numeric values you're using internally:


echo -n "Please choose (1 = rock / 2 = paper / 3 = scissors): "
read choice

It's not a particularly onerous task to add interactivity, eh?

Now you need to compare answers and generate a result message. This is best done in a function, either standalone or by including an output string and tracking win/loss. I'll go for overkill (of course), so here's my function:


results() {
   # output results of the game, increment wins if appropriate
   echo ""
   if [ $choice = $compchoice ] ; then
    echo "You both chose $choicename. TIED!"

   # rock beats scissors. paper beats rock. scissors beat paper.
   #  OR: 1 beats 3, 2 beats 1, and 3 beats 2.

   elif [ $choice -eq 1 -a $compchoice -eq 3 ] ; then
     echo "Your rock beats the computer's scissors! Huzzah!!"
     wins=$(( $wins + 1 ))
   elif [ $choice -eq 2 -a $compchoice -eq 1 ] ; then
     echo "Your paper beats the computer's rock! Hurray!"
     wins=$(( $wins + 1 ))
   elif [ $choice -eq 3 -a $compchoice -eq 2 ] ; then
     echo -n "Your scissors cut - and beat - the computer's "
     echo "paper! YAY!"
     wins=$(( $wins + 1 ))
   elif [ $choice -eq 3 -a $compchoice -eq 1 ] ; then
     echo "The computer's rock beats your scissors! Boo."
   elif [ $choice -eq 1 -a $compchoice -eq 2 ] ; then
     echo "The computer's paper beats your rock! Ptoi!"
   elif [ $choice -eq 2 -a $compchoice -eq 3 ] ; then
     echo -n "The computer's scissors cut - and beat - "
     echo "your paper! Bummer."
   else
     echo "Huh? choice=$choice and compchoice=$computer"
   fi
}

It's straightforward, just a lot of typing. But really, that's 95% of the program. All you need is a looping mechanism so that you're "stuck" in the program until you get sick of the game—I mean ready to wrap things up.

Notice that the above code tracks wins, but not total games played; that'll have to be done in the main code, which, of course, is pretty straightforward because of how much of the code is pushed into the results() function:


echo "Rock, paper, scissors..."
echo "(quit by entering 'q' to see your results)"
while [ true ] ; do
  echo ""
  echo -n "Choose (1 = rock / 2 = paper / 3 = scissors): "
  read choice
  if [ "$choice" = "q" -o "$choice" = "quit" -o -z "$choice" ]
  then
    echo ""
    echo "Done. You played $games games, and won $wins of 'em."
    exit 0
  fi
  compchoice=$(( ($RANDOM % 3) + 1 ))
  choicename=${RPS[$compchoice]}
  games=$(( $games + 1 ))
  results
done

A quick run reveals that scissors isn't a bad strategy when the game is picking completely randomly:


$ sh rps.sh
Choose (1 = rock / 2 = paper / 3 = scissors): 3
Your scissors cut - and beat - the computer's paper! YAY!
$

When I tried it, I had a surprisingly longer-term result: an all-scissors strategy produced a 50% win rate (six games out of 12). Statistically that's unlikely if the computer really is picking randomly, but sometimes random is not so random.

Let's look at choosing paper:


$ sh rps.sh
Choose (1 = rock / 2 = paper / 3 = scissors): 2
The computer's scissors cut - and beat - your paper! Bummer.
$

In fact, playing all paper won only four of 14 games on a trial, and rock, the most popular choice? That produces a win rate of three out of 14—worse than paper!

Matching Probabilities

The biggest change you could make to this program to match the "real" choice statistics is to stop picking randomly and instead reflect the percentages that the Rock Paper Scissors Society publishes: rock is chosen 35.4%, paper 35% and scissors only 29.6% of the time.

The easiest way to model that is to choose a random number between 1–1000 and then say that 1–354 is rock, 355–705 is paper, and 706–1000 is scissors. Instead of a single line where the number is being chosen, a function would be well written, and it's pretty darn easy.

The other area you can expand this is to add a few more possibilities, and I bet most everyone reading this knows how to add "lizard" and "Spock" to the mix. Not sure? Here's how a five-object RPS game works.

So there you have it. Scientific? Not really. But, uh, rock, paper, scissors—come on!

______________________

Dave Taylor has been hacking shell scripts for over thirty years. Really. He's the author of the popular "Wicked Cool Shell Scripts" and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.