Як написати гру "камінь, ножиці, папір" на Java
«Камінь, ножиці, папір» - це гра «на пальцях» для двох. Гравці разом кажуть «камінь, ножиці, папір» і викидають вперед руку, пальцями формуючи одну з трьох фігур (камінь, ножиці або папір). Переможець визначається таким чином: ножиці б`ють папір, папір б`є камінь, камінь б`є ножиці. Якщо обидва гравці показують одну й ту саму фігуру, це вважається нічиєю. Ми напишемо просту гру на Java, яка дозволить грати в «камінь, ножиці, папір» з комп`ютером.
Кроки
1
Створіть основний клас і назвіть йогоRockPaperScissors
. У цьому класі ми опишемо гру. Ви можете назвати його інакше, наприкладGame
абоMain
. Напишіть оголошення конструктора і методу main.public class RockPaperScissors {public RockPaperScissors() {}public static void main(String[] args) {}}
2
Створіть перерахування (enum) для опису можливих ходів (камінь, ножиці, папір). Ми можемо поставити ходи рядками, але перерахування дозволяє нам визначити константи, тому використання enum краще. Назвемо наше перерахуванняMove
і задамо значенняROCK
,PAPER
іSCISSORS
.private enum Move {ROCK, PAPER, SCISSORS}
3
Створіть два закритих (ключове слово private) класуUser
іComputer
. Ці класи будуть представляти гравців. Ви також можете зробити ці класи відкритими (ключове слово public). КласUser
буде запитувати у користувача, який хід він робить - камінь, ножиці або папір - тому нам потрібно написати методgetMove ()
. КласComputer
також повинен мати методgetMove ()
, щоб ми могли отримати хід комп`ютера. Поки що ми просто оголосимо ці методи, а реалізацію напишемо пізніше. КласUser
повинен мати конструктор, в якому инициализируется об`єктScanner
, який буде зчитувати введення користувача. ОголосимоScanner
закритим членом даних класуUser
і инициализируем його в конструкторі. Оскільки ми збираємося використовувати класScanner
, ми повинні підключити його, використовуючи ключове словоimport
. КласуComputer
конструктор не потрібен, тому ми не будемо його пісать- при ініціалізації об`єктуComputer
ми просто викличемо конструктор за замовчуванням. Ось як класRockPaperScissors
виглядає тепер:import java.util.Scanner;public class RockPaperScissors {private enum Move {ROCK, PAPER, SCISSORS}private class User {private Scanner inputScanner;public User() {inputScanner = new Scanner(System.in);}public Move getMove() {// TODO: Реалізація методуreturn null;}}private class Computer {public Move getMove() {// TODO: Реалізація методуreturn null;}}public RockPaperScissors() {}public static void main(String[] args) {}}
4
Напишіть реалізацію методуgetMove ()
для класуComputer
. Цей метод буде повертати випадкове значенняMove
. Ми можемо отримати масив значеньMove
викликавши методvalues ()
ось так:Move.values ()
. Щоб вибрати випадкове значенняMove
з цього масиву, нам потрібно згенерувати випадковий індекс між 0 і кількістю елементом масиву. Для цього викличемо методnextInt ()
класуRandom
, який ми підключимо так:import java.util.Random
. Отримавши випадковий індекс, повернемо значенняMove
з цим індексом в нашому масиві.public Move getMove() {Move[] moves = Move.values();Random random = new Random();int index = random.nextInt(moves.length);return moves[index];}
5
Напишіть реалізацію методуgetMove ()
для класуUser
. Цей метод буде повертати значенняMove
відповідне введенню користувача. Користувач може ввести "камінь", "ножиці", або "папір". Спочатку виведемо повідомлення:System.out.print ("Камінь, ножиці або папір?")
. Потім, за допомогою методуnextLine ()
об`єктаScanner
, ми отримаємо введення користувача у вигляді рядка. Тепер потрібно перевірити коректність введення користувача. Однак ми не звертатиме увагу на друкарські помилки, а просто перевіримо першу букву «К», «Н» або «Б». Також ми не будемо звертати увагу на регістр букв, так як, попередньо, ми викличемо методtoUpperCase ()
класуString
, приводячи введення користувача до верхнього регістру. Якщо користувач не ввів навіть приблизно коректний вибір, запитаємо його хід ще раз. Потім, залежно від введення користувача, наш метод поверне відповідне значенняMove
.public Move getMove() {// Виведемо запит на введенняSystem.out.print("Камінь, ножиці або папір?");// Прочитаємо введення користувачаString userInput = inputScanner.nextLine();userInput = userInput.toUpperCase();char firstLetter = userInput.charAt(0);if (firstLetter == `К` || firstLetter == `Н` || firstLetter == `Б`) {// Введення коректнийswitch (firstLetter) {case `К`:return Move.ROCK;case `Н`:return Move.PAPER;case `Б`:return Move.SCISSORS;}}// Введення некоректний. Виведемо запит на введення знову.return getMove();}
6
Напишіть реалізацію методуplayAgain ()
класуUser
. Користувач повинен мати можливість грати знову і знову. Щоб визначити чи хоче користувач зіграти ще раз, напишіть методplayAgain ()
, який буде повертати значення типу bool і, таким чином, повідомляти грі чи хоче користувач зіграти ще раз. У цьому методі ми використовуємо об`єктScanner
, який ми ініціалізували в конструкторі, щоб отримати "Так" або "Ні" від користувача. Ми всього лише перевіримо першу букву, якщо вона `Д`, значить, користувач хоче зіграти ще раз, будь-яка інша буква буде означати "Ні".public boolean playAgain() {System.out.print("Хочете зіграти ще раз?");String userInput = inputScanner.nextLine();userInput = userInput.toUpperCase();return userInput.charAt(0) == `Д`;}
7
Зв`яжіть код класуUser
і класуComputer
в класіRockPaperScissors
. Написавши код для класівUser
іComputer
, ми можемо зайнятися самою грою. Оголосіть класиUser
іComputer
закритими членами даних класуRockPaperScissors
. Ми будемо звертатися до них, викликаючи методgetMove ()
, щоб отримати ходи гравців. Ініціалізуйте їх в конструкторі класуRockPaperScissors
. Також нам потрібно зберігати рахунок. ОголосітьuserScore
іcomputerScore
, потім Ініціалізуйте їх нулем. І, нарешті, створіть поле даних для зберігання кількості ігор, також ініціалізувати його нулем.private User user;private Computer computer;private int userScore;private int computerScore;private int numberOfGames;public RockPaperScissors() {user = new User();computer = new Computer();userScore = 0;computerScore = 0;numberOfGames = 0;}
8
Доповніть перерахуванняMove
методом, який буде порівнювати ходи і визначати переможця. Напишемо код для методуcompareMoves ()
який буде повертати 0, якщо ходи однакові, 1 - якщо поточний хід б`є іншого і -1 - якщо інший хід б`є поточний. Поточний хід представлений покажчиком this, а інший передається в параметрі otherMove. Це стане в нагоді для визначення переможця. Спочатку напишемо код визначальний нічию і повертає 0, а потім напишемо інструкцію switch для визначення переможця.private enum Move {ROCK, PAPER, SCISSORS;/ *** Порівнює поточний хід з переданим в параметрі otherMove і визначає * перемогу, поразку чи нічию. **param OtherMove * хід, з яким порівнюється поточний *return 1 якщо поточний хід б`є іншого, -1 якщо інший хід б`є поточний , * 0 в разі нічиєї * /public int compareMoves(Move otherMove) {// Нічияif (this == otherMove)return 0;switch (this) {case ROCK:return (otherMove == SCISSORS ? 1 : ;1);case PAPER:return (otherMove == ROCK ? 1 : ;1);case SCISSORS:return (otherMove == PAPER ? 1 : ;1);}// Цей код не повинен виконуватися ніколиreturn 0;}}
9
Оголосіть методstartGame ()
в класіRockPaperScissors
. У цьому методі відбуватиметься гра. Почніть викликом методуSystem.out.println
.public void startGame() {System.out.println("КАМІНЬ, НОЖИЦІ, ПАПІР!");}
10
Отримайте ходи комп`ютера і користувача. У методіstartGame ()
викличтеgetMove ()
класівUser
іComputer
, щоб отримати їх ходи.Move userMove = user.getMove();Move computerMove = computer.getMove();System.out.println(" NВаш хід " + userMove + ".");System.out.println("Хід комп`ютера" + computerMove + ". N");
11
Порівняйте хід комп`ютера і хід гравця, щоб визначити хто виграв. Викличте методcompareMoves ()
перерахуванняMove
, щоб визначити чи виграв користувач. Якщо так, збільште його рахунок на 1. Якщо ні, збільшіть рахунок комп`ютера. У разі нічиєї рахунок залишається колишнім. Після цього збільште кількість зіграних ігор на 1.int compareMoves = userMove.compareMoves(computerMove);switch (compareMoves) {case 0: // НічияSystem.out.println("Нічия!");break;case 1: // Переміг гравецьSystem.out.println(userMove + "Beats" + computerMove + ". Ви перемогли!");userScore++;break;case ;1: // Переміг комп`ютерSystem.out.println(computerMove + "Beats" + userMove + ". Ви програли.");computerScore++;break;}numberOfGames++;
12
Запитайте користувача чи хоче він зіграти ще раз. Якщо так, викличте методstartGame ()
ще раз. Якщо ж ні, викличте методprintGameStats ()
, який виведе статистику гри. Ми напишемо його реалізацію в наступному кроці.if (user.playAgain()) {System.out.println();startGame();} else {printGameStats();}
13
Напишіть реалізацію методуprintGameStats ()
. Цей метод буде виводити статистику гри: кількість перемог, поразок, нічиїх, кількість зіграних ігор і відсоток перемог гравця. Відсоток виграних ігор вважається так: (кол-во перемог + (кол-во нічиїх / 2)) / (к-ть зіграних ігор). Цей метод використовуєSystem.out.printf
для форматованого виведення тексту.private void printGameStats() ");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("
14
Почніть гру. В основному класі Ініціалізуйте об`єктRockPaperScissors
і викличте його методstartGame ()
.public static void main(String[] args) {RockPaperScissors game = new RockPaperScissors();game.startGame();}
15
Протестуйте гру. Тепер, коли вся робота позаду, настав час скомпілювати і протестувати нашу гру!
Приклад програми
import java.util.Random;import java.util.Scanner;public class RockPaperScissors {private User user;private Computer computer;private int userScore;private int computerScore;private int numberOfGames;private enum Move {ROCK, PAPER, SCISSORS;/ *** Порівнює поточний хід з переданим в параметрі otherMove і визначає * перемогу, поразку чи нічию. **param OtherMove * хід, з яким порівнюється поточний *return 1 якщо поточний хід б`є іншого, -1 якщо інший хід б`є поточний , * 0 в разі нічиєї * /public int compareMoves(Move otherMove) {// Нічияif (this == otherMove)return 0;switch (this) {case ROCK:return (otherMove == SCISSORS ? 1 : ;1);case PAPER:return (otherMove == ROCK ? 1 : ;1);case SCISSORS:return (otherMove == PAPER ? 1 : ;1);}// Цей код не повинен виконуватися ніколиreturn 0;}}private class User {private Scanner inputScanner;public User() {inputScanner = new Scanner(System.in);}public Move getMove() {// Виведемо запит на введенняSystem.out.print("Камінь, ножиці або папір?");// Прочитаємо введення користувачаString userInput = inputScanner.nextLine();userInput = userInput.toUpperCase();char firstLetter = userInput.charAt(0);if (firstLetter == `К` || firstLetter == `Н` || firstLetter == `Б`) {// Введення коректнийswitch (firstLetter) {case `К`:return Move.ROCK;case `Н`:return Move.PAPER;case `Б`:return Move.SCISSORS;}}// Введення некоректний. Виведемо запит на введення знову.return getMove();}public boolean playAgain() {System.out.print("Хочете зіграти ще раз?");String userInput = inputScanner.nextLine();userInput = userInput.toUpperCase();return userInput.charAt(0) == `Y`;}}private class Computer {public Move getMove() {Move[] moves = Move.values();Random random = new Random();int index = random.nextInt(moves.length);return moves[index];}}public RockPaperScissors() {user = new User();computer = new Computer();userScore = 0;computerScore = 0;numberOfGames = 0;}public void startGame() {System.out.println("КАМІНЬ, НОЖИЦІ, ПАПІР!");// Отримання ходівMove userMove = user.getMove();Move computerMove = computer.getMove();System.out.println(" NВаш хід " + userMove + ".");System.out.println("Хід комп`ютера" + computerMove + ". N");// Порівняння ходів і визначення переможцяint compareMoves = userMove.compareMoves(computerMove);switch (compareMoves) {case 0: // НічияSystem.out.println("Tie!");break;case 1: // Переміг гравецьSystem.out.println(userMove + "Beats" + computerMove + ". Ви перемогли!");userScore++;break;case ;1: // Переміг комп`ютерSystem.out.println(computerMove + "Beats" + userMove + ". Ви програли.");computerScore++;break;}numberOfGames++;// Запропонуємо користувачеві зіграти ще разif (user.playAgain()) {System.out.println();startGame();} else {printGameStats();}}/ *** Висновок статистики. Нічиї враховуються як півперемоги * при підрахунку відсотка перемог. * /private void printGameStats() % 12s private void printDashes(int numberOfDashes) {for (int i = 0; i < numberOfDashes; i++) {System.out.print("-");}}public static void main(String[] args) {RockPaperScissors game = new RockPaperScissors();game.startGame();}}