- How to create a Rock, Paper, Scissors game using classes and methods
- How to make readable code using classes and methods
This tutorial will NOT teach you
- How to make a class
- How to make/call a method
I hope my tutorial will help you see the beauty in classes and method, and will be an inspiration for you to start using them. My tutorial gives a good example of a basic OO design, and java newcomers can hopefully learn a thing or two
I have created a basic Rock, Paper, Scissors game (like you haven't found out already!), and I will go through the code with you. I will do my best to try and explain what is going on in the code, but feel free to ask if you have any questions.
Lets get started!
Input & output
We want to start off with a console application, so all of out input and output will go through the console.
The class "IO" will be handling everything that has to do with input and output. It is important that the IO class ONLY will have one responsibility, which will be IO handling.
import java.util.Scanner;
public class IO {
private Scanner scanner = new Scanner(System.in);
/**
* Receive input from the user, and check the input against all of the allowed inputs.
*
* @param message The message to show the user before taking input.
* @param possibleInputs All of the allowed inputs.
* @return Returns the first allowed input made by the user.
*/
public String getInput(String message, String... possibleInputs) {
//Show the message
printLine(message);
//Loop as long as the user haven't entered an allowed input
String input;
while (true) {
//Read input from our scanner
input = scanner.nextLine();
//If the input is allowed then break out of the while loop
if (isAllowedInput(input, possibleInputs))
break;
else
printLine("Invalid input!\n" + message);
}
return input;
}
/**
* Checks if 'input' is equal to one of the allowed inputs.
*
* @param input Input made by the user.
* @param possibleInputs All allowed inputs.
* @return Returns true if the input is allowed.
*/
private boolean isAllowedInput(String input, String[] possibleInputs) {
for (int i=0; i<possibleInputs.length; i++)
if (input.equals(possibleInputs[i]))
return true;
return false;
}
/**
* Shows a message to the user through the console.
*
* @param line The message to show.
*/
public void printLine(String line) {
System.out.println(line);
}
}
First of all we have the printLine method. The printLine method is simply a way to show a message to the user, and because we are making a console application, all we have to do is make a System.out.println
The next method isAllowedInput is also straight forward. We loop through the array and check if we have a match. If there is a match, then we return true to tell the input is allowed. After we have looped through our array, we are sure there is no match, therefore we return false to tell the input is not allowed.
The last method, getInput, is a little tricky! You might see something new here, and if you don't then why are you reading this tutorial anyway (you already know it all)?!
Lets start with the parameter
String... possibleInputs
Many experienced programmers haven't seen this before, and will say it is an error. Well it is not!
String... tells you that possibleInputs is an array, and should be treated that way. What makes String... special is that java will make your parameters (when you call the method) into an array by itself.
It requires an example:
//Input1, Input2, and Input3 will be made into an array!
io.getInput("Our message to show the user", "Input1", "Input2", "Input3");
//Here we call the method using a normal array instead
String[] array = { "Input1", "Input2", "Input3" };
io.getInput("Our message to show the user", array);
So lets move on with our code.
We see that we let the user make an input, then we check the input from the user. If the input is allowed, then we break out of the loop and returns the input, else we just continue looping asking for a new input.
Weapons!!!
Weapons yaaaaaaaay!
We know we will be needing three weapons: Rock, Paper, and Scissors.
The player would need one of these weapons, so we will be having a super class Weapon that all weapons should extend.
/**
* The super class of all weapons.
* All weapons should be able to be compared to another weapon to check which is strongest.
*/
public abstract class Weapon implements Comparable<Weapon> {
}
We would like to be able to compare the weapons against each other (to see who wins), and that is why the Comparable interface is implemented. We could as well had made a method ourselves named something like: beat(Weapon other)
The interface only has one method: compareTo(T other), where other is the object we want to compare ourself against.
The method should return 1 IF we are stronger than the other, we return -1 if we are weaker, and we return 0 if we are equally strong.
If there are new weapons added to the game, then you would have to edit the compareTo method of all weapons.
How it is implemented:
public class Paper extends Weapon {
@Override
public int compareTo(Weapon o) {
if (o instanceof Paper)
return 0;
else if (o instanceof Rock)
return 1;
return -1;
}
}
The players
The player classes are pretty straight forward. We want a player to be able to pick a weapon, and we want to know what weapon the player is wearing and the name of the player
public class Player {
private IO io;
private Weapon weapon;
private String name;
/**
* Initialize the player
*
* @param io Class to use for all IO.
* @param name Name of this player.
*/
public Player(IO io, String name) {
this.io = io;
this.name = name;
}
/**
* It is our time to pick a weapon.
* After a call to this method, it is guaranteed that a weapon has been picked.
*/
public void pickWeapon() {
//Get input from the player. Possible inputs are: Rock, Paper, or Scissors
String input = io.getInput(name + " pick your weapon - Rock, Paper, or Scissors", "Rock", "Paper", "Scissors");
switch (input) {
case "Rock":
weapon = new Rock();
break;
case "Paper":
weapon = new Paper();
break;
default:
weapon = new Scissors();
break;
}
}
/**
* @return Returns the weapon picked or null if yet to pick a weapon.
*/
public Weapon getWeapon() {
return weapon;
}
/**
* @return Returns the name of this player.
*/
public String getName() {
return name;
}
}
The game class
This is where everything happens!
Our game is progressed from this class, and we also have some basic logic (since the game is small)
/**
* The game class is responsible for any progress made in the game.
* You should edit this class to change the flow of the game.
*
* @author Stephan S. Jensen
*
*/
public class Game {
private IO io;
private Player player1, player2;
public Game() {
io = new IO();
}
/**
* This method starts the game and is responsible for any progress made in the game.
*
* @param player1Start True if player1 will start the game, false if player2.
*/
public void startRound(boolean player1Start) {
io.printLine("New round!");
//Initialize the players, giving them a name and access to the IO class
player1 = new Player(io, "Player 1");
player2 = new Player(io, "Player 2");
//Swap the players if player2 should start the round
if (!player1Start)
swapPlayers();
//Let the players pick their weapon
player1.pickWeapon();
player2.pickWeapon();
//Find the winner of the round
findWinner();
//Find out if we should play again
if (playAgain())
//Negate the boolean value to swap starting player
startRound(!player1Start);
}
/**
* Find the winner of the round and congratulate them.
*/
private void findWinner() {
//Compare the two weapons against each other to find out which is strongest
int winner = player1.getWeapon().compareTo(player2.getWeapon());
switch (winner) {
case 1: //Player1's weapon beats player2's
io.printLine(player1.getName() + " wins!");
break;
case -1: //Player2's weapon beats player1's
io.printLine(player2.getName() + " wins!");
break;
case 0: //Draw
io.printLine("Draw!");
break;
}
}
/**
* Will swap the two player references.
*/
private void swapPlayers() {
Player temp = player1;
player1 = player2;
player2 = temp;
}
/**
* Checks if the two players want to play another round.
*
* @return Returns true if we should play again.
*/
private boolean playAgain() {
String input = io.getInput("Play again? - Y/N", "Y", "N");
return input.equals("Y");
}
}
We initialize the players and IO, but then we actually just use the classes and methods we have already made. The code is easy to maintain, and is highly readable (at least I think!).
Hopefully my javadoc and comments can explain most of what is going on.
I want to explain what is going on here:
int winner = player1.getWeapon().compareTo(player2.getWeapon());
Remember our Comparable interface? This is where we use it.
We get both of the weapons and compare one of them against the other, We do not need to call compareTo on both of them!
All of the code
public class Main {
public static void main(String[] args) {
new Game().startRound(true);
}
}
/**
* The game class is responsible for any progress made in the game.
* You should edit this class to change the flow of the game.
*
* @author Stephan S. Jensen
*
*/
public class Game {
private IO io;
private Player player1, player2;
public Game() {
io = new IO();
}
/**
* This method starts the game and is responsible for any progress made in the game.
*
* @param player1Start True if player1 will start the game, false if player2.
*/
public void startRound(boolean player1Start) {
io.printLine("New round!");
//Initialize the players, giving them a name and access to the IO class
player1 = new Player(io, "Player 1");
player2 = new Player(io, "Player 2");
//Swap the players if player2 should start the round
if (!player1Start)
swapPlayers();
//Let the players pick their weapon
player1.pickWeapon();
player2.pickWeapon();
//Find the winner of the round
findWinner();
//Find out if we should play again
if (playAgain())
//Negate the boolean value to swap starting player
startRound(!player1Start);
}
/**
* Find the winner of the round and congratulate them.
*/
private void findWinner() {
//Compare the two weapons against each other to find out which is strongest
int winner = player1.getWeapon().compareTo(player2.getWeapon());
switch (winner) {
case 1: //Player1's weapon beats player2's
io.printLine(player1.getName() + " wins!");
break;
case -1: //Player2's weapon beats player1's
io.printLine(player2.getName() + " wins!");
break;
case 0: //Draw
io.printLine("Draw!");
break;
}
}
/**
* Will swap the two player references.
*/
private void swapPlayers() {
Player temp = player1;
player1 = player2;
player2 = temp;
}
/**
* Checks if the two players want to play another round.
*
* @return Returns true if we should play again.
*/
private boolean playAgain() {
String input = io.getInput("Play again? - Y/N", "Y", "N");
return input.equals("Y");
}
}
import java.util.Scanner;
public class IO {
private Scanner scanner = new Scanner(System.in);
/**
* Receive input from the user, and check the input against all of the allowed inputs.
*
* @param message The message to show the user before taking input.
* @param possibleInputs All of the allowed inputs.
* @return Returns the first allowed input made by the user.
*/
public String getInput(String message, String... possibleInputs) {
//Show the message
printLine(message);
//Loop as long as the user haven't entered an allowed input
String input;
while (true) {
//Read input from our scanner
input = scanner.nextLine();
//If the input is allowed then break out of the while loop
if (isAllowedInput(input, possibleInputs))
break;
else
printLine("Invalid input!\n" + message);
}
return input;
}
/**
* Checks if 'input' is equal to one of the allowed inputs.
*
* @param input Input made by the user.
* @param possibleInputs All allowed inputs.
* @return Returns true if the input is allowed.
*/
private boolean isAllowedInput(String input, String[] possibleInputs) {
for (int i=0; i<possibleInputs.length; i++)
if (input.equals(possibleInputs[i]))
return true;
return false;
}
/**
* Shows a message to the user through the console.
*
* @param line The message to show.
*/
public void printLine(String line) {
System.out.println(line);
}
}
public class Player {
private IO io;
private Weapon weapon;
private String name;
/**
* Initialize the player
*
* @param io Class to use for all IO.
* @param name Name of this player.
*/
public Player(IO io, String name) {
this.io = io;
this.name = name;
}
/**
* It is our time to pick a weapon.
* After a call to this method, it is guaranteed that a weapon has been picked.
*/
public void pickWeapon() {
//Get input from the player. Possible inputs are: Rock, Paper, or Scissors
String input = io.getInput(name + " pick your weapon - Rock, Paper, or Scissors", "Rock", "Paper", "Scissors");
switch (input) {
case "Rock":
weapon = new Rock();
break;
case "Paper":
weapon = new Paper();
break;
default:
weapon = new Scissors();
break;
}
}
/**
* @return Returns the weapon picked or null if yet to pick a weapon.
*/
public Weapon getWeapon() {
return weapon;
}
/**
* @return Returns the name of this player.
*/
public String getName() {
return name;
}
}
/**
* The super class of all weapons.
* All weapons should be able to be compared to another weapon to check which is strongest.
*/
public abstract class Weapon implements Comparable<Weapon> {
}
public class Paper extends Weapon {
@Override
public int compareTo(Weapon o) {
if (o instanceof Paper)
return 0;
else if (o instanceof Rock)
return 1;
return -1;
}
}
public class Rock extends Weapon {
@Override
public int compareTo(Weapon o) {
if (o instanceof Rock)
return 0;
else if (o instanceof Scissors)
return 1;
return -1;
}
}
public class Scissors extends Weapon {
@Override
public int compareTo(Weapon o) {
if (o instanceof Scissors)
return 0;
else if (o instanceof Paper)
return 1;
return -1;
}
}





MultiQuote






|