React es una biblioteca JavaScript de código abierto de frontend, que se utiliza para crear interfaces de usuario interactivas. React se centra en aplicaciones de una sola página y se conoce más popularmente como SPA. En este tutorial, usaremos React y sus ganchos para crear una divertida aplicación Tic-Tac-Toe. Antes de saltar al código, asegúrese de verificar los requisitos previos para una mejor comprensión.
Requisito previo:
Módulos requeridos:
- npm
- Reaccionar
Creación de la aplicación React y configuración:
Paso 1: Comenzará un nuevo proyecto usando create-react-app, así que abra su terminal y escriba.
npx create-react-app tic-tac-toe-react
Paso 2: cambia a la carpeta tres en raya usando el siguiente comando.
cd tic-tac-toe-react
Paso 3: cambie a la carpeta src y elimine las cosas innecesarias con el siguiente comando
cd src rm *
Paso 4: Cree una carpeta css en src, que contenga los archivos app.css, board.css, index.css e info.css.
mkdir css touch app.css board.css index.css info.css
Paso 5: en la carpeta src , cree archivos App.js, Board.js, index.js e Info.js.
touch App.js Board.js index.js Info.js
Estructura del proyecto: La estructura de archivos en el proyecto se verá así.
Ejemplo: este ejemplo lo guiará con el código para crear un juego de Tic-Tac-Toe usando React Hooks.
index.js: Este fHTML
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './css/index.css'; import App from './App'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') );
App.js: este archivo actúa como un archivo base que contiene los componentes Info y Board. Edite el archivo App.js de la siguiente manera:
App.js
// Importing the required components import Board from './Board'; import Info from "./Info"; // Importing the CSS File import "./css/app.css"; // Importing the useState hook import { useState } from 'react'; function App() { // Creating a reset state, which indicates whether // the game should be reset or not const [reset, setReset] = useState(false); // Creating a winner state, which indicates // the current winner const [winner, setWinner] = useState(''); // Sets the reset property to true // which starts the chain // reaction of resetting the board const resetBoard = () => { setReset(true); } return ( <div className="App"> {/* Shrinks the popup when there is no winner */} <div className={`winner ${winner !== '' ? '' : 'shrink'}`}> {/* Display the current winner */} <div className='winner-text'>{winner}</div> {/* Button used to reset the board */} <button onClick={() => resetBoard()}> Reset Board </button> </div> {/* Custom made board component comprising of the tic-tac-toe board */} <Board reset={reset} setReset={setReset} winner={winner} setWinner={setWinner} /> <Info /> </div> ); } export default App;
Board.js: este archivo contiene el tablero de tres en raya y la lógica del juego. Edite Board.js de la siguiente manera:
Board.js
// Importing the CSS for the board import "./css/board.css"; // Importing the useState hook, useEffect hook and useRef hook import { useState, useEffect, useRef } from "react"; const Board = ({ reset, setReset, winner, setWinner }) => { // Creating a turn state, which indicates the current turn const [turn, setTurn] = useState(0); // Creating a data state, which contains the // current picture of the board const [data, setData] = useState(['', '', '', '', '', '', '', '', '']) // Creating a reference for the board const boardRef = useRef(null); // Function to draw on the board const draw = (event, index) => { // Draws only if the position is not taken // and winner is not decided yet if (data[index - 1] === '' && winner === '') { // Draws X if it's player 1's turn else draws O const current = turn === 0 ? "X" : "O" // Updating the data state data[index - 1] = current; //Drawing on the board event.target.innerText = current; // Switching the turn setTurn(turn === 0 ? 1 : 0) } } // UseEffect hook used to reset the board whenever // a winner is decided useEffect(() => { // Clearing the data state setData(['', '', '', '', '', '', '', '', '']); // Getting all the children(cells) of the board const cells = boardRef.current.children // Clearing out the board for (let i = 0; i < 9; i++) { cells[i].innerText = ''; } // Resetting the turn to player 0 setTurn(0); // Resetting the winner setWinner(''); setReset(false); }, [reset, setReset, setWinner]) // useEffect hook used to check for a winner useEffect(() => { // Checks for the win condition in rows const checkRow = () => { let ans = false; for (let i = 0; i < 9; i += 3) { ans |= (data[i] === data[i + 1] && data[i] === data[i + 2] && data[i] !== '') } return ans; } // Checks for the win condition in cols const checkCol = () => { let ans = false; for (let i = 0; i < 3; i++) { ans |= (data[i] === data[i + 3] && data[i] === data[i + 6] && data[i] !== '') } return ans; } // Checks for the win condition in diagonals const checkDiagonal = () => { return ((data[0] === data[4] && data[0] === data[8] && data[0] !== '') || (data[2] === data[4] && data[2] === data[6] && data[2] !== '')); } // Checks if at all a win condition is present const checkWin = () => { return (checkRow() || checkCol() || checkDiagonal()); } // Checks for a tie const checkTie = () => { let count = 0; data.forEach((cell) => { if (cell !== '') { count++; } }) return count === 9; } // Setting the winner in case of a win if (checkWin()) { setWinner(turn === 0 ? "Player 2 Wins!" : "Player 1 Wins!"); } else if (checkTie()) { // Setting the winner to tie in case of a tie setWinner("It's a Tie!"); } }) return ( <div ref={boardRef} className="board"> <div className="input input-1" onClick={(e) => draw(e, 1)}></div> <div className="input input-2" onClick={(e) => draw(e, 2)}></div> <div className="input input-3" onClick={(e) => draw(e, 3)}></div> <div className="input input-4" onClick={(e) => draw(e, 4)}></div> <div className="input input-5" onClick={(e) => draw(e, 5)}></div> <div className="input input-6" onClick={(e) => draw(e, 6)}></div> <div className="input input-7" onClick={(e) => draw(e, 7)}></div> <div className="input input-8" onClick={(e) => draw(e, 8)}></div> <div className="input input-9" onClick={(e) => draw(e, 9)}></div> </div> ) } export default Board;
Info.js: este archivo contiene información sobre el juego de tres en raya. Edite Info.js de la siguiente manera:
Info.js
// Importing the css for the info import "./css/info.css"; const Info = () => { return ( <div className="info"> <div className="player">Player 1: X</div> <div className="player">Player 2: O</div> </div> ) } export default Info;
index.css
*{ -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; }
App.css
@import url( 'https://fonts.googleapis.com/css2?family=Bellefair&display=swap'); .App{ width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; flex-direction: column; gap: 5vh; backdrop-filter: 5px; background-color: #101010; } .winner { transition: all ease-in .3s; display: flex; opacity: 1; font-size: 1.5rem; font-weight: 600; gap: 1vh; flex-direction: column; justify-content: center; align-items: center; width: 20vw; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -70%); background-color: rgba(195, 141, 158, 0.863); backdrop-filter: 5px; padding: .5rem; padding-bottom: 1rem; border-radius: 10%; } .winner-text{ padding: .3em 1em .25em; font-weight: 600; font-size: 2.5rem; color: white; font-family: 'Bellefair', serif; position:relative; text-align: center; line-height:1.3; } .shrink { transform: scale(.1); opacity: 0; } button { background-color: #111827; border: 1px solid transparent; border-radius: .75rem; box-sizing: border-box; color: #FFFFFF; cursor: pointer; flex: 0 0 auto; font-family: "Inter var"; font-size: 1.125rem; font-weight: 600; line-height: 1.5rem; padding: .75rem 1.2rem; text-align: center; text-decoration: none #6B7280 solid; text-decoration-thickness: auto; transition-duration: .2s; transition-property: background-color, border-color, color, fill, stroke; transition-timing-function: cubic-bezier(.4, 0, 0.2, 1); user-select: none; -webkit-user-select: none; touch-action: manipulation; width: auto; } button:hover { background-color: #374151; } button:focus { box-shadow: none; outline: 2px solid transparent; outline-offset: 2px; } @media (min-width: 768px) { button { padding: .75rem 1.5rem; } };
board.css
:root { --board-background: none; --border-color: #f6546a; --border-thickness: 5px; } .board{ width: 30vw; height: 50%; background-color: var(--board-background); display: flex; align-items: flex-start; flex-direction: row; flex-wrap: wrap; } .input{ height: 33.33%; width: 33.33%; display: flex; justify-content: center; align-items: center; color: whitesmoke; font-family: 'Bellefair', serif; font-style: italic; font-weight: 700; font-size: 6rem; } .input-1{ border-right: var(--border-thickness) dashed var(--border-color); border-bottom: var(--border-thickness) dashed var(--border-color); } .input-2{ border-right: var(--border-thickness) dashed var(--border-color); border-bottom: var(--border-thickness) dashed var(--border-color); } .input-3{ border-bottom: var(--border-thickness) dashed var(--border-color); } .input-4{ border-right: var(--border-thickness) dashed var(--border-color); border-bottom: var(--border-thickness) dashed var(--border-color); } .input-5{ border-right: var(--border-thickness) dashed var(--border-color); border-bottom: var(--border-thickness) dashed var(--border-color); } .input-6{ border-bottom: var(--border-thickness) dashed var(--border-color); } .input-7{ border-right: var(--border-thickness) dashed var(--border-color); } .input-8{ border-right: var(--border-thickness) dashed var(--border-color); }
info.css
.info { width: 30vw; display: flex; justify-content: space-evenly; align-items: center; color: whitesmoke; } .player { border: 2px solid #f6546a; border-radius: 5%; padding: .5rem 0; display: flex; font-size: 1.5rem; justify-content: center; align-items: center; width: 10vw; }
Guarde todos los archivos e inicie la aplicación ejecutando el siguiente comando:
npm start
Producción:
Publicación traducida automáticamente
Artículo escrito por tejsidda34 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA