wikiHow es un "wiki", lo que significa que muchos de nuestros artículos están escritos por varios autores. Para crear este artículo, 11 personas, algunas anónimas, han trabajado para editarlo y mejorarlo con el tiempo.
Este artículo ha sido visto 26 221 veces.
Piedra, Papel y Tijeras es un juego de manos para dos personas. Ambos jugadores deben decir “piedra, papel, tijeras” y simultáneamente formar uno de los tres objetos (piedra, papel o tijeras) con una mano extendida. El ganador se determina por las formaciones de las manos. Las tijeras le ganan al papel, el papel le gana a la piedra, y la piedra le gana a las tijeras. Si ambos jugadores presentan la misma formación de manos, se considera un empate. Escribiremos un juego sencillo en Java para simular Piedra, Papel, Tijeras en el que un jugador es el usuario y el otro es la computadora.
Pasos
-
1Crea la clase principal y llámala
PiedraPapelTijeras
. Ésta será la clase en la que escribiremos el juego. Puedes escoger nombrarla de alguna otra manera, comoJuego
oPrincipal
. Escribe las declaraciones de método para el constructor y para el método principal.public class PiedraPapelTijeras { public PiedraPapelTijeras() { } public static void main(String[] args) { } }
-
2Crea una enumeración para los gestos de mano (piedra, papel o tijeras). Podríamos usar cadenas para representar piedra, papel o tijeras, pero una enumeración nos permite predefinir nuestras constantes, lo que significa que usar la enumeración resulta en un mejor diseño. Llamaremos a nuestro tipo de enumeración
Move
con los valoresROCA
,PAPEL
, yTIJERAS
.private enum Move { ROCA, PAPEL, TIJERAS }
-
3Crea dos clases privadas
Usuario
yComputadora
. Estas clases representarán a nuestros jugadores en el juego. La claseUsuario
será la clase que le solicite al usuario que escoja entre roca, papel o tijeras, por lo que deberemos escribir un métodogetMove()
. La claseComputadora
también deberá tener un métodogetMove()
para que la computadora también pueda hacer su jugada. Colocaremos marcadores de posición en estos métodos para implementarlos más tarde. La claseUsuario
requerirá un constructor que configure el objetoScanner
que tomará la entrada del usuario. Pondremos elScanner
como un campo privado para el usuario, y luego lo iniciaremos en el constructor. Como estamos usando la claseScanner
, necesitamos escribirle una declaración de importación en la parte de arriba de nuestro código. La claseComputadora
no requiere de un constructor, por lo que no necesitaremos escribir uno; cuando iniciemos el objetoComputadora
, simplemente estaremos llamando al constructor por defecto. Así es como se ve ahora nuestra clasePiedraPapelTijeras
:import java.util.Scanner; public class PiedraPapelTijeras { private enum Move { ROCA, PAPEL, TIJERAS } private class Usuario { private Scanner inputScanner; public Usuario() { inputScanner = new Scanner(System.in); } public Move getMove() { // PORHACER: Implementar este método return null; } } private class Computadora { public Move getMove() { // POR HACER: Implementar este método return null; } } public PiedraPapelTijeras() { } public static void main(String[] args) { } }
-
4Escribe el método
getMove()
para la claseComputadora
. Este método te devolverá unMove
aleatorio. Podemos obtener un array de las enumeraciones deMove
llamando al métodovalues()
:Move.values()
. Para escoger una enumeración aleatoria deMove
en este array de valores necesitamos generar un índice aleatorio que sea un entero de entre 0 y la longitud de nuestro array de valores. Para hacer esto podemos usar el métodonextInt()
de la claseRandom
, la que debemos importar desdejava.util
. Después de haber obtenido el índice aleatorio, podemos devolver elMove
para ese índice de nuestro array de valores.public Move getMove() { Move[] moves = Move.values(); Random random = new Random(); int index = random.nextInt(moves.length); return moves[index]; }
-
5Escribe el método
getMove()
para la claseUsuario
. Este método devolverá unMove
correspondiente a lo que el usuario haya ingresado. Supondremos que el usuario escribirá roca, papel o tijeras. Primero debemos solicitarle una entrada al usuario:System.out.print("Roca, papel o tijeras?")
. Luego usaremos el métodonextLine()
del objetoScanner
para tomar la entrada del usuario como una cadena. Ahora debemos revisar si el usuario ha ingresado una jugada válida, pero podemos ser tolerantes con respecto a la ortografía. Así que sólo revisaremos si la primer letra que ingresa el usuario es una R (para roca), una P (para papel) o una T (para tijeras), independientemente de si son mayúsculas o minúsculas ya que usaremos el métodotoUpperCase()
de la claseString
para poner en mayúsculas todas las entradas del usuario. Si el usuario ingresa una entrada incorrecta, le pediremos nuevamente que ingrese. Luego, dependiendo de lo que haya ingresado el usuario, devolveremos una jugada correspondiente.public Move getMove() { // Solicitarle al usuario System.out.print("Roca, papel o tijeras? "); // Obtener la entrada del usuario String usuarioInput = inputScanner.nextLine(); usuarioInput = usuarioInput.toUpperCase(); char firstLetter = usuarioInput.charAt(0); if (firstLetter == 'R' || firstLetter == 'P' || firstLetter == 'T') { // Usuario ha ingresado un dato válido switch (firstLetter) { case 'R': return Move.ROCA; case 'P': return Move.PAPEL; case 'T': return Move.TIJERAS; } } // Usuario no ha ingresado un dato válido. Solicitar nuevamente. return getMove(); }
-
6Escribe un método
playAgain()
para la claseUsuario
. El usuario debería poder jugar una y otra vez. Para determinar si el usuario quiere jugar nuevamente, necesitamos escribir un métodoplayAgain()
que devuelva un valor booleano que diga si el usuario ha determinado jugar nuevamente o no. En este método usamos elScanner
que habíamos iniciado previamente en el constructor para obtener un Sí o un No del usuario. Sólo revisaremos si la primera letra es una 'S' para determinar si el usuario desea jugar nuevamente. Cualquier otra entrada significará que el usuario no desea jugar nuevamente.public boolean playAgain() { System.out.print("Quieres jugar nuevamente? "); String usuarioInput = inputScanner.nextLine(); usuarioInput = usuarioInput.toUpperCase(); return usuarioInput.charAt(0) == 'S'; }
-
7Conecta las clases
Usuario
yComputadora
juntas en la clasePiedraPapelTijeras
. Ahora que hemos terminado de escribir las clasesUsuario
yComputadora
, podemos concentrarnos en el juego en sí. Crea campos privados para las clasesUsuario
yComputadora
en la clasePiedraPapelTijeras
. Deberemos acceder a estos campos para acceder a los métodosgetMove()
cuando estemos jugando. En el constructor para la clasePiedraPapelTijeras
, inicia estos campos. También deberemos llevar la cuenta de los puntos en los camposusuarioPuntos
ycomputadoraPuntos
, los que debemos iniciar en 0 en el constructor. También necesitamos llevar la cuenta de la cantidad de juegos, lo que también será un campo iniciado en 0.private Usuario usuario; private Computadora computadora; private int usuarioPuntos; private int computadoraPuntos; private int cantidadDeJuegos; public PiedraPapelTijeras() { usuario = new Usuario(); computadora = new Computadora(); usuarioPuntos = 0; computadoraPuntos = 0; cantidadDeJuegos = 0; }
-
8Extiende la enumeración
Move
para incluir un método que nos diga quién ganará en cada caso. Debemos escribir un métodocompareMoves()
que devuelva 0 si las jugadas son la misma, 1 si la jugada actual le gana a la otra, y -1 si la jugada actual pierde frente a la otra. Esto será útil para determinar el ganador del juego. Para implementar este método, primero devolveremos 0 si las jugadas son la misma, y por lo tanto tendremos un empate. Luego escribe una declaración de switch para devolver 1 o -1.private enum Move { ROCA, PAPEL, TIJERAS; /** * Compara esta jugada con otra jugada para determinar empate, victoria o * derrota. * * @param otherMove * jugada a comparar con * @return 1 si esta jugada le gana a la otra, -1 si esta jugada pierde frente a * la otra, 0 si las jugadas empatan */ public int compareMoves(Move otherMove) { // Empate if (this == otherMove) return 0; switch (this) { case ROCA: return (otherMove == TIJERAS ? 1 : -1); case PAPEL: return (otherMove == ROCA ? 1 : -1); case TIJERAS: return (otherMove == PAPEL ? 1 : -1); } // Nunca debería llegar hasta aquí return 0; } }
-
9Crea un método
startGame()
en la clasePiedraPapelTijeras
. Este método será el desarrollo del juego. Comienza poniendo un sencilloSystem.out.println
en el método.public void startGame() { System.out.println("ROCA, PAPEL, TIJERAS!"); }
-
10Obtén las jugadas del usuario y de la computadora. En el método
startGame()
, usa los métodosgetMove()
de la claseUsuario
y de la claseComputadora
para obtener las jugadas del usuario y de la computadora.Move usuarioMove = usuario.getMove(); Move computadoraMove = computadora.getMove(); System.out.println("\nYou played " + usuarioMove + "."); System.out.println("Computadora played " + computadoraMove + ".\n");
-
11Compara las dos jugadas y determina si ganó el usuario o la computadora. Usa el método
compareMoves()
de la enumMove
para determinar si el usuario ganó o no. Si ganó el usuario, incrementa el puntaje de los usuarios en 1. Si el usuario perdió, incrementa el puntaje de la computadora en 1. Si hubo un empate, no incrementes ninguno de los puntajes. Luego incrementa la cantidad de juegos en uno.int compareMoves = usuarioMove.compareMoves(computadoraMove); switch (compareMoves) { case 0: // Empate System.out.println("Empate!"); break; case 1: // Gana Usuario System.out.println(usuarioMove + " le gana a " + computadoraMove + ". Ganaste!"); usuarioPuntos++; break; case -1: // Gana Computadora System.out.println(computadoraMove + " le gana a " + usuarioMove + ". Perdiste."); computadoraPuntos++; break; } cantidadDeJuegos++;
-
12Pregúntale al usuario si quiere jugar de nuevo. Si el usuario quiere jugar nuevamente, llama otra vez a
startGame()
. De otra manera, llama aprintGameStats()
que imprimirá las estadísticas del juego. Escribiremos este método en el paso siguiente.if (usuario.playAgain()) { System.out.println(); startGame(); } else { printGameStats(); }
-
13Escribe el método
printGameStats()
. Este método mostrará las estadísticas del juego: cantidad de victorias, cantidad de derrotas, cantidad de empates, cantidad de juegos, yy porcentaje de triunfos del usuario. El porcentaje de juegos ganados se calcula por (# voctorias + (# empates/2))/(# juegos). Este método usaSystem.out.printf
para imprimir texto con formato.private void printGameStats() { int wins = usuarioPuntos; int losses = computadoraPuntos; int ties = cantidadDeJuegos - usuarioPuntos - computadoraPuntos; double percentageWon = (wins + ((double) ties) / 2) / cantidadDeJuegos; // Línea System.out.print("+"); printDashes(68); System.out.println("+"); // Imprime títulos System.out.printf("| %6s | %6s | %6s | %12s | %14s |\n", "VICTORIAS", "DERROTAS", "EMPATES", "JUEGOS", "PORCENTAJE DE TRIUNFOS"); // Línea System.out.print("|"); printDashes(10); System.out.print("+"); printDashes(10); System.out.print("+"); printDashes(10); System.out.print("+"); printDashes(16); System.out.print("+"); printDashes(18); System.out.println("|"); // Imprime valores System.out.printf("| %6d | %6d | %6d | %12d | %13.2f%% |\n", wins, losses, ties, cantidadDeJuegos, percentageWon * 100); // Línea System.out.print("+"); printDashes(68); System.out.println("+"); }
-
14Comienza el juego en la clase principal. En la clase principal, inicializa una instancia de la clase
PiedraPapelTijeras
y llama al métodostartGame()
.public static void main(String[] args) { PiedraPapelTijeras game = new PiedraPapelTijeras(); game.startGame(); }
-
15Prueba tu juego. Ahora que hemos hecho todo el esfuerzo de escribir el juego de Piedra, Papel, Tijeras, ¡es hora de compilarlo y probar todo!
Programa de Muestra
import java.util.Random;
import java.util.Scanner;
public class PiedraPapelTijeras {
private Usuario usuario;
private Computadora computadora;
private int usuarioPuntos;
private int computadoraPuntos;
private int cantidadDeJuegos;
private enum Move {
ROCA, PAPEL, TIJERAS;
/**
* Compara esta jugada con otra para determinar si es un empate, un triunfo o
* una derrota.
*
* @param otherMove
* jugada a comparar
* @return 1 si esta jugada le gana a la otra, -1 se esta jugada pierde frente a
* la otra, 0 si las jugadas empatan
*/
public int compareMoves(Move otherMove) {
// Empate
if (this == otherMove)
return 0;
switch (this) {
case ROCA:
return (otherMove == TIJERAS ? 1 : -1);
case PAPEL:
return (otherMove == ROCA ? 1 : -1);
case TIJERAS:
return (otherMove == PAPEL ? 1 : -1);
}
// Nunca debería llegar hasta aquí
return 0;
}
}
private class Usuario {
private Scanner inputScanner;
public Usuario() {
inputScanner = new Scanner(System.in);
}
public Move getMove() {
// Solicitarle al usuario
System.out.print("Roca, papel o tijeras? ");
// Obtener la entrada del usuario
String usuarioInput = inputScanner.nextLine();
usuarioInput = usuarioInput.toUpperCase();
char firstLetter = usuarioInput.charAt(0);
if (firstLetter == 'R' || firstLetter == 'P' || firstLetter == 'T') {
// Usuario ha ingresado un dato válido
switch (firstLetter) {
case 'R':
return Move.ROCA;
case 'P':
return Move.PAPEL;
case 'T':
return Move.TIJERAS;
}
}
// Usuario no ha ingresado un dato válido. Solicitar nuevamente.
return getMove();
}
public boolean playAgain() {
System.out.print("Quieres jugar de nuevo? ");
String usuarioInput = inputScanner.nextLine();
usuarioInput = usuarioInput.toUpperCase();
return usuarioInput.charAt(0) == 'S';
}
}
private class Computadora {
public Move getMove() {
Move[] moves = Move.values();
Random random = new Random();
int index = random.nextInt(moves.length);
return moves[index];
}
}
public PiedraPapelTijeras() {
usuario = new Usuario();
computadora = new Computadora();
usuarioPuntos = 0;
computadoraPuntos = 0;
cantidadDeJuegos = 0;
}
public void startGame() {
System.out.println("ROCA, PAPEL, TIJERAS!");
// Obtener jugadas
Move usuarioMove = usuario.getMove();
Move computadoraMove = computadora.getMove();
System.out.println("\nYou played " + usuarioMove + ".");
System.out.println("Computadora played " + computadoraMove + ".\n");
// Comparar jugadas y determinar ganador
int compareMoves = usuarioMove.compareMoves(computadoraMove);
switch (compareMoves) {
case 0: // Empate
System.out.println("Empate!");
break;
case 1: // Gana Usuario
System.out.println(usuarioMove + " le gana a " + computadoraMove + ". Ganaste!");
usuarioPuntos++;
break;
case -1: // Gana Computadora
System.out.println(computadoraMove + " le gana a " + usuarioMove + ". Perdiste.");
computadoraPuntos++;
break;
}
cantidadDeJuegos++;
// Preguntar al usuario si jugar nuevamente
if (usuario.playAgain()) {
System.out.println();
startGame();
} else {
printGameStats();
}
}
/**
* Imprimir las estadísticas del juego. Calcular un empate como ½ victoria en
* el porcentaje de victorias.
*/
private void printGameStats() {
int wins = usuarioPuntos;
int losses = computadoraPuntos;
int ties = cantidadDeJuegos - usuarioPuntos - computadoraPuntos;
double percentageWon = (wins + ((double) ties) / 2) / cantidadDeJuegos;
// Línea
System.out.print("+");
printDashes(68);
System.out.println("+");
// Imprimir títulos
System.out.printf("| %6s | %6s | %6s | %12s | %14s |\n",
"VICTORIAS", "DERROTAS", "EMPATES", "JUEGOS", "PORCENTAJE VICTORIAS");
// Línea
System.out.print("|");
printDashes(10);
System.out.print("+");
printDashes(10);
System.out.print("+");
printDashes(10);
System.out.print("+");
printDashes(16);
System.out.print("+");
printDashes(18);
System.out.println("|");
// Imprimir valores
System.out.printf("| %6d | %6d | %6d | %12d | %13.2f%% |\n",
wins, losses, ties, cantidadDeJuegos, percentageWon * 100);
// Línea
System.out.print("+");
printDashes(68);
System.out.println("+");
}
private void printDashes(int numberOfDashes) {
for (int i = 0; i < numberOfDashes; i++) {
System.out.print("-");
}
}
public static void main(String[] args) {
PiedraPapelTijeras game = new PiedraPapelTijeras();
game.startGame();
}
}