Learn Programming in Java


<<Previous | ToC | Next >>

Rock-Paper-Scissors

Always the first thing to do in programming any new program is to think about what you want it to do. When you have programmed as long as I have, you can think in Java or Python or even (yuk!) C, but for now let's do it in English.

Speaking of English, maybe you already did RPS in English. If you got that working and you saved it, use it here. Otherwise use mine. There will be some differences, but we are playing the same game, the same logic, just a different language.

Each player -- both simultaneously -- chooses one of three things to shape their hand to model: a fist for rock, the hand flat, palm down for paper, or the first two fingers extended and open in a "V" like a pair of scissors. When people do it, they synchronize by pounding their fist on the other open hand three times, and the third time they open up the fist into either paper or scissors (or leave it a fist), both at the same time.

Scoring is simple: Paper covers (wins against) rock, scissors cut (wins against) paper, and rock breaks (wins against) scissors. If both players chose the same thing, it's a tie (no score).

In the computer, scoring is easy: we compare the two plays, and if they are different, whichever wins that hand gets their score increased.

Without hands and eyes, in the computer, the human player will type in the first letter of the thing they chose, and the computer will type whatever it chose. Here's my English version:

Repeat
  Print out "One"
  Wait 1 second
  Print out "Two"
  Wait 1 second
  Print out "Three"
  {decide what to play..}
  Variable myPlay = "S"
  Random r < 3
  if r=0 then Let myPlay = "R"
  if r=1 then Let myPlay = "P"
  Input HumPlay,1
  Print "I played " myPlay ", you played " HumPlay
  {compare plays..}
  let score = 0
  if myPlay = "R" then if HumPlay = "P" then let score = 1
  if myPlay = "R" then if HumPlay = "S" then let score = -1
  if myPlay = "P" then if HumPlay = "R" then let score = -1
  if myPlay = "P" then if HumPlay = "S" then let score = 1
  if myPlay = "S" then if HumPlay = "P" then let score = -1
  if myPlay = "S" then if HumPlay = "R" then let score = 1
  {announce winner}
  if score>0 Print "You win"
  if score<0 Print "I win"
  otherwise Print "Tie"
  Next
 
The English computer can often figure out what your variables are from how they got used, but Java insists that you declare every one of them. Find your variables and decide what data type(s) to use, then declare them.

Except for the delay and the random number, you have already done everything in Java that is used in this program. So let's work on those two issues.

For dramatic effect, I would like the computer to print out the three numbers at one-second intervals. I Googled "Java delay" (no quotes) and found several answers, but the simplest seems to be "Thread.sleep(milliseconds)" which I found here. Later we can learn about threads, but for now, this just works:

  Thread.sleep(1000);
  System.out.print("One... ");
  Thread.sleep(1000);
  System.out.print("Two... ");
  Thread.sleep(1000);
  System.out.print("Three... ");
Notice I used "System.out.print" so they all come out on the same line.

When I tried to compile this, I expected the compiler to tell me that it doesn't know about class Thread. That didn't happen, which explains why I couldn't find any help or teaching websites that said how to "import" it. Instead, Java complained about exceptions. I planned that topic for a later session (see "Exceptions" and maybe also "Threads" in the "Things You Need to Know" page), and at least one website said you don't need to worry about it unless you have other threads running (you don't). I solved it by adding one word at the front, on the same line as the outer while loop:

while (true) try {
and a little more at the end of the same loop:
} catch (Exception ex) {}
Exceptions are a convenient way to deal with rare catastrophes in robust software. They mostly don't happen in carefully planned pedagogical programs like you will get from me. You need to know about exceptions, but not today. Back to the main topic...

To be perfectly fair, the computer needs to make its choice (rock, paper, or scissors) before seeing the human play, so we do that next. In the English program the computer plays randomly (later you might try some strategy to anticipate the human play). I Googled "Java random integer" and StackOverflow almost always has the best answers, in this case for a random integer between 1 and 10:
Random rn = new Random();
int answer = rn.nextInt(10) + 1;
Obviously we are interested in only three values (instead of ten) so I'd put 3 inside the parentheses. The "+1" is also unnecessary, its purpose is to raise the output from 0..9 to 1..10, and we don't care about that, we just need to deal with the three numbers we get, which will be 0, 1, 2. Notice that both of these lines are declarations, so we want to put them at the top with the other declarations. Except we don't need that random number until the computer is ready to decide its play, so declare the integer variable as "int answer;" or maybe 'int r;" to match the English usage (in either case uninitialized).

Random is a Java library class (like Thread), which not everybody wants to tell you what to import. Whenever you see in one of the help sites, a Java class name like Thread or Random (they always start with a capital letter), you can expect that you probably will need to import it. You will be looking for a line that starts with "import" and ends with the class you are trying to use, in this case "Random;". I suppose you could just guess and randomly try different standard Java class path names, but there are so many of them! I Googled "Java random import" and the correct spelling of the import line came up in the first hit. What you need at the front of your program (at the very top, before the [green box] "public class Hello" line) is

import java.util.Random;


So now, after printing out the third synchronization number, we query the random number generator for an answer to make the computer's choice:

  r = rn.nextInt(3);
  if (r==0) cplay = 'r';
  else if (r==1) cplay = 'p';
    else cplay = 's'; // (r==2)


OK, the computer has decided its own play, it's ready to ask for the human play. You remember Zystem.ReadLetter() in the guessing game? We can use it again here:

  System.out.print("Your play? ");
  HumPlay = Zystem.ReadLetter();
I think you can do the rest, it's just like what you have already done, right?

If you didn't make any mistakes, this should compile and run. If you did, well the computer will tell you about them and you can fix them.

Next: Arrays

<<Previous | ToC | Next >>

Revised: 2021 August 28