
«Камень, ножницы, бумага» — простая, но очень популярная жестовая игра, которой вот уже не первый век развлекаются люди во всём мире. Поскольку правила игры просты, а жесты общепонятны, ею широко пользуются для улаживания споров, принятия решений или просто чтобы провести время. В этой статье мы исследуем богатую историю игры «Камень, ножницы, бумага», поговорим о том, как в неё играть, напишем саму игру и разберём структуру её кода, а также узнаем, как на материале этой игры можно прокачать навыки программирования.
История игры «Камень, ножницы, бумага»
Игра «Камень, ножницы, бумага» зародилась в Древнем Китае – там существовала аналогичная игра под названием «шушилинь», известная уже примерно во II веке до н.э. В ранней версии этой игры использовались три жеста, обозначавшие животных: тигр, курица и червь. В данном случае курица боится тигра, червь боится курицы, а тигр боится, что у него заведутся черви. Возникает кольцевое взаимоотношение, подобное тому, что известно нам из игры «Камень, ножницы, бумага».
Постепенно игра проникла в Японию, где закрепилась под названием «ян-кен-пон» и приобрела особую популярность в период Эдо (1603–1868). В японской версии исходную китайскую троицу животных заменили на всем знакомые камень, ножницы и бумагу, а также изобрели жесты, известные нам сегодня. Со временем игра распространилась и в европейские страны, где остаётся популярным развлечением по сей день.
Разработка игры «Камень, ножницы, бумага»
Разработка компьютерной версии «Камень, ножницы, бумага» — отличное упражнение для программистов, желающих попрактироваться и отточить свои навыки. Такую игру можно написать на HTML, CSS и JavaScript, этого хватит, чтобы предоставить пользовательский интерфейс и запрограммировать игровую логику.
Структурно код для игры «Камень, ножницы, бумага» можно разбить на несколько ключевых компонентов:
- Структура HTML: в файле HTML определяется структура и содержимое игры, в том числе, кнопки, которыми пользователь может выбирать ход. Также в HTML отображаются области для вывода результатов и очков.
 - Стили CSS: в файле CSS обеспечивается стилевое оформление игры, в том числе, макет страницы, цвета, шрифты и другие визуальные элементы (правда, в этом примере мы не будем серьёзно останавливаться на стилях и сосредоточимся на функциональной составляющей)
 - Логика JavaScript: в файле JavaScript содержится игровая логика, в том числе, функции для обработки пользовательского ввода, определения того, какой ход сделал компьютер, сравнения ходов для определения победителя, ведения счёта и отображения результатов.
 
Теперь давайте подробнее разберём структуру кода и исследуем, как все компоненты работают вместе. Наша цель – создать полнофункциональную игру «Камень, ножницы, бумага».
Структура HTML:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Rock, Paper, Scissors</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1>Rock, Paper, Scissors</h1>
  <p>Choose your move:</p>
  <button id="rock" onclick="handleClick('rock')">Rock</button>
  <button id="paper" onclick="handleClick('paper')">Paper</button>
  <button id="scissors" onclick="handleClick('scissors')">Scissors</button>
  
  <div id="result"></div>
  <div>
    <span>User Score:</span>
    <span id="user-score">0</span>
  </div>
  <div>
    <span>Computer Score:</span>
    <span id="computer-score">0</span>
  </div>
  <script src="script.js"></script>
</body>
</html>
Структура HTML служит основой игры. В разметке определяется, какие элементы будут видны пользователю. Вот основные HTML-элементы, входящие в эту структуру:
[…]
- 
В этом элементе заключено всё содержимое, которое будет отображаться на странице, в частности, заголовки, абзацы, кнопки и другие элементы пользовательского интерфейса.<body> - 
<В этом элементе содержится заголовок, то есть, название игры: “Rock, Paper, Scissors”.<h1> - 
Это элемент, в котором заключается абзац (параграф). В нём содержатся инструкции, то есть, подсказки для пользователя, как выбирать ход.<p> - 
В этих элементах представлены варианты хода, которые может выбрать пользователь («камень», «ножницы» или «бумага»). У каждой кнопки есть атрибут id, по которому его легко выбирать в файле JavaScript, а также атрибут onclick, по которому срабатывает функция handleClick(). В качестве аргумента эта функция принимает тот или иной ход.<button> - 
Данный div-элемент – это контейнер, в котором отображается результат каждого раунда. По атрибуту id можно выбирать и обновлять этот элемент на JavaScript.<div id=”result”> - 
В этих div-элементах содержатся очки, заработанные пользователем и компьютером. Каждое значение очков заключено в элемент span, обладающий уникальным атрибутом id. Поэтому данные элементы легко выбирать и обновлять при помощи JavaScript.Очки пользователя и компьютера - 
В этом элементе заключён скрипт, который связывает файл JavaScript с HTML-документом. Он размещается в самом конце элемента body и таким образом гарантирует, что сначала полностью загрузится содержимое HTML-документа, и только потом будет выполняться код JavaScript.<script src=”script.js”></script> 
Структура файла JavaScript:
let userScore = 0;
let computerScore = 0;
let roundsPlayed = 0;
const getUserChoice = userInput => {
  return userInput.toLowerCase();
};
const getComputerChoice = () => {
  const number = Math.floor(Math.random() * 3);
  return ["rock", "paper", "scissors"][number];
};
const determineWinner = (userChoice, computerChoice) => {
  if (userChoice === computerChoice) {
    return "It's a tie!";
  }
  const winConditions = {
    rock: "scissors",
    paper: "rock",
    scissors: "paper",
  };
  return winConditions[userChoice] === computerChoice
    ? "User wins!"
    : "Computer wins!";
};
const checkGameOver = () => {
  if (userScore >= 3) {
    alert("User wins the game!");
    resetGame();
  } else if (computerScore >= 3) {
    alert("Computer wins the game!");
    resetGame();
  }
};
const resetGame = () => {
  userScore = 0;
  computerScore = 0;
  roundsPlayed = 0;
  document.getElementById("user-score").textContent = userScore;
  document.getElementById("computer-score").textContent = computerScore;
  document.getElementById("result").innerHTML = "";
};
const handleClick = choice => {
  if (roundsPlayed >= 5) {
    alert("Game over! Please start a new game.");
    resetGame();
    return;
  }
  const userChoice = getUserChoice(choice);
  const computerChoice = getComputerChoice();
  const result = determineWinner(userChoice, computerChoice);
  const resultDiv = document.getElementById("result");
  resultDiv.innerHTML = `User: ${userChoice} vs. Computer: ${computerChoice} - ${result}`;
  if (result === "User wins!") {
    userScore++;
  } else if (result === "Computer wins!") {
    computerScore++;
  }
  document.getElementById("user-score").textContent = userScore;
  document.getElementById("computer-score").textContent = computerScore;
  roundsPlayed++;
  checkGameOver();
};
В файле JavaScript содержится игровая логика. В частности, здесь находятся функции для обработки пользовательского ввода, определения хода компьютера, сравнения ходов с целью определения победителя, а также для обновления счёта и выводимых результатов.
Разрабатывая на JavaScript логику игры «Камень, ножницы, бумага», можно освоить различные аспекты программирования, в частности, работу с функциями, условными операторами, а также обработку событий.
- Объявление и инициализация глобальных переменных: 
userScor, computerScore, roundsPlayed. В них хранятся очки пользователя, очки компьютера и общее количество отыгранных раундов. - Функция 
getUserChoice(): она принимает пользовательский ввод (строку) и возвращает её же в нижнем регистре. Это делается для того, чтобы все записи в игре не отличались по регистру. - Функция 
getComputerChoice(): она создаёт случайный вариант, который станет ходом компьютера. Эта функция генерирует случайное число от 0 до 2 и сопоставляет его с соответствующим вариантом (камень, ножницы или бумага). - Функция 
determineWinner(): она принимает выбор, сделанный компьютером и выбор, сделанный пользователем, сравнивает их и определяет победителя раунда. Проверяет, равны ли варианты (в таком случае фиксируется ничья) или находит победителя в зависимости от условий того, какой объект берёт верх. Эти условия определяются в объектеwinConditions. - Функция 
checkGameOver(): проверяет, завершена ли игра, в зависимости от того, какая из сторон победила по итогам 5 раундов. Если пользователь или компьютер победили в 3 или более раундах, то игра считается завершённой и выводится окно-уведомление с указанием победителя. После вывода такого уведомления вызывается функцияresetGame(), сбрасывающая состояние игры в исходное. - Функция 
resetGame(): эта функция сбрасывает состояние игры, устанавливая в 0 очки пользователя, очки компьютера и количество сыгранных раундов. Также она обновляет таблицу лидеров и стирает текст с описанием результата. - Функция 
handleClick(): Функция `handleClick()` вызывается, как только пользователь щёлкнет по одной из кнопок – камню, ножницам или бумаге. Сначала функция проверяет, не завершена ли ещё игра (прошло ли 5 раундов) и, если требуется, выводит уведомление о начале новой игры. После этого функция извлекает значение, выбранное пользователем (передаётся в качестве аргумента) и получает значение, выбранное компьютером (оно генерируется случайным образом). Далее она определяет победителя при помощи функцииdetermineWinner()и обновляет текст с результатами. В зависимости от того, кто выиграл раунд – пользователь или компьютер – счёт этого игрока увеличивается, что соответствующим образом отражается на экране. Также увеличивается значение переменнойroundsPlayedи вызывается функцияcheckGameOver(), проверяющая, закончена ли игра. 
Какими продвинутыми навыками программирования можно овладеть, работая над игрой «Камень, ножницы, бумага»
- Понять объектную модель документа (DOM) и научиться манипулировать ею. Программируя «Камень, ножницы, бумага», можно научиться выбирать, создавать и модифицировать HTML-элементы при помощи JavaScript.
 - Обработка событий: в игре требуются слушатели событий, которые будут обнаруживать пользовательский ввод и реагировать на него. Так приобретается ценный опыт по работе с событиями в JavaScript.
 - Реализация игровой логики: при разработке игровой логики программист всегда практикуется в написании функций, использовании условных операторов и работе с переменными.
 - Работа с CSS-стилями: разрабатывая внешний вид игры, разработчик учится обращаться со свойствами и селекторами CSS. В ходе этой работы можно лучше понять принципы веб-дизайна.
 - Организация кода и наилучшие практики: при разработке игры «камень, ножницы, бумага» мы учимся писать чистый и организованный код, следовать наилучшим практикам, задумываться о масштабируемости и поддержке кода в разных проектах.
 
В дальнейшем этот проект может послужить основой для дальнейших исследований и творчества. Разработчик вполне может реализовать в этой игре и дополнительные возможности – например, звуковые эффекты, анимацию, таблицы рекордов и альтернативные игровые режимы.
Поиграть в «Камень, ножницы, бумага» можно здесь.