Як написати гру "камінь, ножиці, папір" на Java

«Камінь, ножиці, папір» - це гра «на пальцях» для двох. Гравці разом кажуть «камінь, ножиці, папір» і викидають вперед руку, пальцями формуючи одну з трьох фігур (камінь, ножиці або папір). Переможець визначається таким чином: ножиці б`ють папір, папір б`є камінь, камінь б`є ножиці. Якщо обидва гравці показують одну й ту саму фігуру, це вважається нічиєю. Ми напишемо просту гру на Java, яка дозволить грати в «камінь, ножиці, папір» з комп`ютером.


Кроки

  1. 1

    Створіть основний клас і назвіть його RockPaperScissors. У цьому класі ми опишемо гру. Ви можете назвати його інакше, наприклад Game або Main. Напишіть оголошення конструктора і методу main.

    public class RockPaperScissors {public RockPaperScissors() {}public static void main(String[] args) {}}

  2. 2

    Створіть перерахування (enum) для опису можливих ходів (камінь, ножиці, папір). Ми можемо поставити ходи рядками, але перерахування дозволяє нам визначити константи, тому використання enum краще. Назвемо наше перерахування Move і задамо значення ROCK, PAPERі SCISSORS.

    private enum Move {ROCK, PAPER, SCISSORS}

  3. 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. 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. 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. 6

    Напишіть реалізацію методу playAgain () класу User. Користувач повинен мати можливість грати знову і знову. Щоб визначити чи хоче користувач зіграти ще раз, напишіть метод playAgain (), який буде повертати значення типу bool і, таким чином, повідомляти грі чи хоче користувач зіграти ще раз. У цьому методі ми використовуємо об`єкт Scanner , який ми ініціалізували в конструкторі, щоб отримати "Так" або "Ні" від користувача. Ми всього лише перевіримо першу букву, якщо вона `Д`, значить, користувач хоче зіграти ще раз, будь-яка інша буква буде означати "Ні".

    public boolean playAgain() {System.out.print("Хочете зіграти ще раз?");String userInput = inputScanner.nextLine();userInput = userInput.toUpperCase();return userInput.charAt(0) == `Д`;}

  7. 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. 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. 9

    Оголосіть метод startGame () в класі RockPaperScissors. У цьому методі відбуватиметься гра. Почніть викликом методу System.out.println.

    public void startGame() {System.out.println("КАМІНЬ, НОЖИЦІ, ПАПІР!");}

  10. 10

    Отримайте ходи комп`ютера і користувача. У методі startGame () викличте getMove () класів User і Computer , щоб отримати їх ходи.

    Move userMove = user.getMove();Move computerMove = computer.getMove();System.out.println(" NВаш хід " + userMove + ".");System.out.println("Хід комп`ютера" + computerMove + ". N");

  11. 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. 12

    Запитайте користувача чи хоче він зіграти ще раз. Якщо так, викличте метод startGame () ще раз. Якщо ж ні, викличте метод printGameStats (), який виведе статистику гри. Ми напишемо його реалізацію в наступному кроці.

    if (user.playAgain()) {System.out.println();startGame();} else {printGameStats();}

  13. 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. 14

    Почніть гру. В основному класі Ініціалізуйте об`єкт RockPaperScissors і викличте його метод startGame ().

    public static void main(String[] args) {RockPaperScissors game = new RockPaperScissors();game.startGame();}

  15. 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();}}