javascript

Камень, ножницы, бумага: путешествие во времени, стратегия и код

  • суббота, 7 сентября 2024 г. в 00:00:06
https://habr.com/ru/companies/piter/articles/841080/
image


«Камень, ножницы, бумага» — простая, но очень популярная жестовая игра, которой вот уже не первый век развлекаются люди во всём мире. Поскольку правила игры просты, а жесты общепонятны, ею широко пользуются для улаживания споров, принятия решений или просто чтобы провести время. В этой статье мы исследуем богатую историю игры «Камень, ножницы, бумага», поговорим о том, как в неё играть, напишем саму игру и разберём структуру её кода, а также узнаем, как на материале этой игры можно прокачать навыки программирования.

История игры «Камень, ножницы, бумага»


Игра «Камень, ножницы, бумага» зародилась в Древнем Китае – там существовала аналогичная игра под названием «шушилинь», известная уже примерно во II веке до н.э. В ранней версии этой игры использовались три жеста, обозначавшие животных: тигр, курица и червь. В данном случае курица боится тигра, червь боится курицы, а тигр боится, что у него заведутся черви. Возникает кольцевое взаимоотношение, подобное тому, что известно нам из игры «Камень, ножницы, бумага».

Постепенно игра проникла в Японию, где закрепилась под названием «ян-кен-пон» и приобрела особую популярность в период Эдо (1603–1868). В японской версии исходную китайскую троицу животных заменили на всем знакомые камень, ножницы и бумагу, а также изобрели жесты, известные нам сегодня. Со временем игра распространилась и в европейские страны, где остаётся популярным развлечением по сей день.

Разработка игры «Камень, ножницы, бумага»


Разработка компьютерной версии «Камень, ножницы, бумага» — отличное упражнение для программистов, желающих попрактироваться и отточить свои навыки. Такую игру можно написать на HTML, CSS и JavaScript, этого хватит, чтобы предоставить пользовательский интерфейс и запрограммировать игровую логику.

Структурно код для игры «Камень, ножницы, бумага» можно разбить на несколько ключевых компонентов:
  1. Структура HTML: в файле HTML определяется структура и содержимое игры, в том числе, кнопки, которыми пользователь может выбирать ход. Также в HTML отображаются области для вывода результатов и очков.
  2. Стили CSS: в файле CSS обеспечивается стилевое оформление игры, в том числе, макет страницы, цвета, шрифты и другие визуальные элементы (правда, в этом примере мы не будем серьёзно останавливаться на стилях и сосредоточимся на функциональной составляющей)
  3. Логика 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-элементы, входящие в эту структуру:

[…]

  1. <body>
    В этом элементе заключено всё содержимое, которое будет отображаться на странице, в частности, заголовки, абзацы, кнопки и другие элементы пользовательского интерфейса.
  2. <h1>
    <В этом элементе содержится заголовок, то есть, название игры: “Rock, Paper, Scissors”.
  3. <p>
    Это элемент, в котором заключается абзац (параграф). В нём содержатся инструкции, то есть, подсказки для пользователя, как выбирать ход.
  4. <button>
    В этих элементах представлены варианты хода, которые может выбрать пользователь («камень», «ножницы» или «бумага»). У каждой кнопки есть атрибут id, по которому его легко выбирать в файле JavaScript, а также атрибут onclick, по которому срабатывает функция handleClick(). В качестве аргумента эта функция принимает тот или иной ход.
  5. <div id=”result”>
    Данный div-элемент – это контейнер, в котором отображается результат каждого раунда. По атрибуту id можно выбирать и обновлять этот элемент на JavaScript.
  6. Очки пользователя и компьютера
    В этих div-элементах содержатся очки, заработанные пользователем и компьютером. Каждое значение очков заключено в элемент span, обладающий уникальным атрибутом id. Поэтому данные элементы легко выбирать и обновлять при помощи JavaScript.
  7. <script src=”script.js”></script>
    В этом элементе заключён скрипт, который связывает файл JavaScript с HTML-документом. Он размещается в самом конце элемента body и таким образом гарантирует, что сначала полностью загрузится содержимое HTML-документа, и только потом будет выполняться код JavaScript.

Структура файла 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 логику игры «Камень, ножницы, бумага», можно освоить различные аспекты программирования, в частности, работу с функциями, условными операторами, а также обработку событий.

  1. Объявление и инициализация глобальных переменных: userScor, computerScore, roundsPlayed. В них хранятся очки пользователя, очки компьютера и общее количество отыгранных раундов.
  2. Функция getUserChoice(): она принимает пользовательский ввод (строку) и возвращает её же в нижнем регистре. Это делается для того, чтобы все записи в игре не отличались по регистру.
  3. Функция getComputerChoice(): она создаёт случайный вариант, который станет ходом компьютера. Эта функция генерирует случайное число от 0 до 2 и сопоставляет его с соответствующим вариантом (камень, ножницы или бумага).
  4. Функция determineWinner(): она принимает выбор, сделанный компьютером и выбор, сделанный пользователем, сравнивает их и определяет победителя раунда. Проверяет, равны ли варианты (в таком случае фиксируется ничья) или находит победителя в зависимости от условий того, какой объект берёт верх. Эти условия определяются в объекте winConditions.
  5. Функция checkGameOver(): проверяет, завершена ли игра, в зависимости от того, какая из сторон победила по итогам 5 раундов. Если пользователь или компьютер победили в 3 или более раундах, то игра считается завершённой и выводится окно-уведомление с указанием победителя. После вывода такого уведомления вызывается функция resetGame(), сбрасывающая состояние игры в исходное.
  6. Функция resetGame(): эта функция сбрасывает состояние игры, устанавливая в 0 очки пользователя, очки компьютера и количество сыгранных раундов. Также она обновляет таблицу лидеров и стирает текст с описанием результата.
  7. Функция handleClick(): Функция `handleClick()` вызывается, как только пользователь щёлкнет по одной из кнопок – камню, ножницам или бумаге. Сначала функция проверяет, не завершена ли ещё игра (прошло ли 5 раундов) и, если требуется, выводит уведомление о начале новой игры. После этого функция извлекает значение, выбранное пользователем (передаётся в качестве аргумента) и получает значение, выбранное компьютером (оно генерируется случайным образом). Далее она определяет победителя при помощи функции determineWinner() и обновляет текст с результатами. В зависимости от того, кто выиграл раунд – пользователь или компьютер – счёт этого игрока увеличивается, что соответствующим образом отражается на экране. Также увеличивается значение переменной roundsPlayed и вызывается функция checkGameOver(), проверяющая, закончена ли игра.

Какими продвинутыми навыками программирования можно овладеть, работая над игрой «Камень, ножницы, бумага»


  1. Понять объектную модель документа (DOM) и научиться манипулировать ею. Программируя «Камень, ножницы, бумага», можно научиться выбирать, создавать и модифицировать HTML-элементы при помощи JavaScript.
  2. Обработка событий: в игре требуются слушатели событий, которые будут обнаруживать пользовательский ввод и реагировать на него. Так приобретается ценный опыт по работе с событиями в JavaScript.
  3. Реализация игровой логики: при разработке игровой логики программист всегда практикуется в написании функций, использовании условных операторов и работе с переменными.
  4. Работа с CSS-стилями: разрабатывая внешний вид игры, разработчик учится обращаться со свойствами и селекторами CSS. В ходе этой работы можно лучше понять принципы веб-дизайна.
  5. Организация кода и наилучшие практики: при разработке игры «камень, ножницы, бумага» мы учимся писать чистый и организованный код, следовать наилучшим практикам, задумываться о масштабируемости и поддержке кода в разных проектах.

В дальнейшем этот проект может послужить основой для дальнейших исследований и творчества. Разработчик вполне может реализовать в этой игре и дополнительные возможности – например, звуковые эффекты, анимацию, таблицы рекордов и альтернативные игровые режимы.

Поиграть в «Камень, ножницы, бумага» можно здесь.