В этой статье мы создадим простую игру в крестики-нолики с помощью Reactjs.

Охватываемый контент

— Компонентный дизайн
— Расширенная игровая логика JS
— Расширенные эффекты при наведении курсора CSS
— CSS Flex
— CSS Shape Building

Результат нашей игры в крестики-нолики будет выглядеть так:

Самый простой способ создать приложение React.js — использовать команду create-react-app. Установите этот пакет, используя следующую команду в вашем терминале.

npx create-react-app Tic-Tac-Toe-using-React
cd Tic-Tac-Toe-using-React
npm start

Подготовьте файл и папку следующим образом:

src/
 App.css
 App.js
 EndGame.js
 index.js
 Square.js
 TicTacToe.js

Мы начнем с квадратного компонента

Квадратный компонент

Откройте файл «Square.js» с приведенным ниже кодом и сохраните его.

const Square = ({ clickedArray, handleClick }) => {
  return (
    <div className="board">
      {clickedArray.map((item, index) => {
        if (item === "") {
          return (
            <div
              key={index}
              className="square"
              onClick={() => handleClick(index)}
            >
              {item}
            </div>
          );
        } else {
          return (
            <div key={index} className="square clicked">
              {item}
            </div>
          );
        }
      })}
    </div>
  );
};
export default Square;

Компонент EndGame

Откройте файл «EndGame.js» и напишите код:

const EndGame = ({ newGame, player, draw, X_PLAYER, O_PLAYER }) => {
  return (
    <div className="end-game-screen">
      {!draw && (
        <span className="win-text">
          Player {player ? O_PLAYER : X_PLAYER} Win!
        </span>
      )}
      {draw && <span className="win-text">Draw</span>}
      <button className="btn" onClick={newGame}>
        New Game
      </button>
    </div>
  );
};
export default EndGame;

Компонент TicTacToe

Этот компонент будет хранить нашу игровую логику, но позже мы добавим игровую логику.

import { useState } from "react";
import Square from "./Square";
import EndGame from "./EndGame";
const INITIAL = "";
const X_PLAYER = "X";
const O_PLAYER = "O";
const winCombination = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6],
];
const TicTacToe = () => {
  const [grid, setGrid] = useState(Array(9).fill(INITIAL));
  const [player, setPlayer] = useState(false);
  const [gameFinished, setGameFinished] = useState(false);
  const [draw, setDraw] = useState(false);
  const newGame = () => {
    setGrid(Array(9).fill(INITIAL));
    setGameFinished(false);
    setDraw(false);
  };
 
  return (
    <div>
      <div className="player-turn">
        Turn player: {player ? X_PLAYER : O_PLAYER}
      </div>
      {gameFinished && (
        <EndGame
          newGame={newGame}
          player={player}
          draw={draw}
          X_PLAYER={X_PLAYER}
          O_PLAYER={O_PLAYER}
        />
      )}
      <Square clickedArray={grid} handleClick={handleClick} />
    </div>
  );
};
export default TicTacToe;

Добавьте стиля в нашу игру

App.css

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "PT Sans", sans-serif;
}
.App {
  height: 100vh;
  background: #cbd2d6;
  display: flex;
  align-items: center;
  justify-content: center;
}
.square {
  background: #498da6;
  height: 10rem;
  width: 10rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: white;
  font-size: 4rem;
}
.square:hover {
  background: #fcf649;
}
.square.clicked {
  background: #01233d;
  cursor: not-allowed;
}
.board {
  display: grid;
  grid-template-columns: repeat(3, auto);
  align-items: center;
  justify-content: center;
  grid-gap: 5px;
}
.end-game-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  position: absolute;
  top: 0;
  left: 0;
  height: 100vh;
  width: 100vw;
  background: rgba(0, 0, 0, 0.8);
}
.btn {
  background: #cbd2d6;
  color: #01233d;
  border: 2px solid #cbd2d6;
  font-size: 2rem;
  margin-bottom: 1rem;
  padding: 10px 14px;
  cursor: pointer;
  border-radius: 5px;
  transition: 0.3s ease-out;
  max-height: 7rem;
}
.win-text {
  color: white;
  font-size: 10rem;
}
.player-turn {
  color: #01233d;
  font-size: 2rem;
  margin: 2rem 0;
}

Позвольте открыть App.js и изменить код

import "./App.css";
import TicTacToe from "./TicTacToe";
const App = () => {
  return (
    <div className="App">
      <TicTacToe />
    </div>
  );
};
export default App;

Вы должны увидеть такой результат, но он еще не работает.

Последний шаг реализует нашу игровую логику, открывает компонент TicTacToe, модифицирует функцию handleClick и добавляет функцию isGameOver.

Окончательный код компонента TicTacToe

import { useState } from "react";
import Square from "./Square";
import EndGame from "./EndGame";
const INITIAL = "";
const X_PLAYER = "X";
const O_PLAYER = "O";
const winCombination = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6],
];
const TicTacToe = () => {
  const [grid, setGrid] = useState(Array(9).fill(INITIAL));
  const [player, setPlayer] = useState(false);
  const [gameFinished, setGameFinished] = useState(false);
  const [draw, setDraw] = useState(false);
  const newGame = () => {
    setGrid(Array(9).fill(INITIAL));
    setGameFinished(false);
    setDraw(false);
  };
  const handleClick = (id) => {
    setGrid(
      grid.map((item, index) => {
        if (index === id) {
          if (player) {
            return X_PLAYER;
          } else {
            return O_PLAYER;
          }
        } else {
          return item;
        }
      })
    );
    setPlayer(!player);
  };
  const isGameOver = () => {
    if (!gameFinished) {
      for (let i = 0; i < 8; i++) {
        if (
          grid[winCombination[i][0]] === X_PLAYER &&
          grid[winCombination[i][1]] === X_PLAYER &&
          grid[winCombination[i][2]] === X_PLAYER
        ) {
          setGameFinished(true);
          return;
        }
      }
      for (let i = 0; i < 8; i++) {
        if (
          grid[winCombination[i][0]] === O_PLAYER &&
          grid[winCombination[i][1]] === O_PLAYER &&
          grid[winCombination[i][2]] === O_PLAYER
        ) {
          setGameFinished(true);
          return;
        }
      }
      if (!grid.includes(INITIAL)) {
        setDraw(true);
        setGameFinished(true);
      }
    }
  };
  isGameOver();

  return (
    <div>
      <div className="player-turn">
        Turn player: {player ? X_PLAYER : O_PLAYER}
      </div>
      {gameFinished && (
        <EndGame
          newGame={newGame}
          player={player}
          draw={draw}
          X_PLAYER={X_PLAYER}
          O_PLAYER={O_PLAYER}
        />
      )}
      <Square clickedArray={grid} handleClick={handleClick} />
    </div>
  );
};
export default TicTacToe;

Заключение

Сделанный! Это отличный проект для тех, кто хочет повеселиться, изучая концепции React, JavaScript и CSS.

Исходный код: https://github.com/easywebsify/Tic-Tac-Toe-React