В этой статье мы создадим простую игру в крестики-нолики с помощью 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