Crea un juego de piedra, papel o tijera usando ReactJS

Aquí ambos jugadores tomarán su turno uno por uno. Comenzando con el jugador uno seguido por el jugador dos. Hay tres armas para elegir, a saber, piedra, papel, tijeras. Una vez que el jugador dos juega, el resultado de su turno se calcula actualizando el estado de ganar/perder de ambos jugadores.

Tecnologías Utilizadas / Prerrequisitos:

  1. ReaccionarJS
  2. Biblioteca Antd para la interfaz de usuario

Enfoque: los contenedores son componentes de Stateful React (basados ​​en clases). Los componentes son componentes React sin estado (basados ​​en funciones). En este proyecto, tengo un contenedor que es Controller, que es responsable de la gestión del estado y de toda la lógica del juego. Además, hay tres componentes, a saber:

Player ->Represent​ing a Player entity in-game;
GameControls -> For Choosing stone, paper, or scissor; 
DecisionBox -> Displays win/loose status for players;

Al hacer clic en los botones de armas, el estado del controlador se actualiza para el jugador respectivo. Cuando se actualiza el arma del segundo jugador, el resultado se calcula mediante la función del controlador de resultados que cubre las nueve combinaciones de piedra, papel y tijeras tomadas de dos en dos.

Estructura del proyecto:

Pasos :

  1. Configure el proyecto React usando el comando create-react-app: create-react-app <<name of project>> –scripts-version 1.1.5. Usando este comando, se generará una estructura de proyecto como la anterior, excepto los componentes y las carpetas de contenedores que se crearán dentro de la carpeta src manualmente.
  2. Instale la biblioteca antd usando el comando: npm install antd
  3. Elimina el código dentro de App.css .
  4. Edite el código dentro de App.js : el componente de la aplicación representa el controlador y muestra el título.
    Aplicación.js

    JavaScript

    import React, { Component } from "react";
    import Controller from "./containers/controller/controller";
    import { Typography } from "antd";
      
    import "antd/dist/antd.css";
      
    import "./App.css";
    const { Title } = Typography;
      
    class App extends Component {
      render() {
        return (
          <div className="App">
            <Title level={3} style={{ textAlign: "center" }}>
              Stone Paper Scissor
            </Title>
            <Controller />
          </div>
        );
      }
    }
      
    export default App;
  5. Controller.js: el controlador tiene un estado que incluye el último arma utilizada por cada jugador, el estado actual de victoria/pérdida y el estado activo que indica el turno de qué jugador es.

    JavaScript

    import React, { Component } from "react";
    import { Row, Col, Divider } from "antd";
    import { Typography } from "antd";
    import axios from "axios";
    import "antd/dist/antd.css";
      
    import Player from "../../components/Player/Player";
    const { Title } = Typography;
      
    class Controller extends Component {
      state = {
        playerOne: {
          active: true,
          weapon: "",
          status: ""
        },
        playerTwo: {
          active: false,
          weapon: "",
          status: ""
        }
      };

    La idea central aquí es que al hacer clic en los botones de arma, el arma del jugador correspondiente en el estado debería actualizarse y debería llegar el turno del siguiente jugador, lo cual se hace aquí a través de la función de alternancia activa. Además, si se actualiza el arma del segundo jugador, también se debe actualizar ganar/perder, lo que se hace aquí a través de la función resultHandler. Para la lógica del juego, tiene un montón de funciones:

    • Actualización de armas: para actualizar el arma de un jugador en el estado. Se necesitan dos argumentos: el primero es playerId, es decir, playerOne o playerTwo, ya que es un juego de dos jugadores y el segundo es un arma que elige el jugador.

      JavaScript

      weaponUpdate = (player, weapon) => {this.setState({
      [player]: {
      ...this.state[player],
      weapon: weapon
      }
      });
      if (player == "playerTwo") {
      this.resultHandler();
      } else {
      this.toggleActive();
      }
      };
    • ToggleActive: para revertir el estado activo de los jugadores una vez que cualquiera de los jugadores selecciona un arma. La propiedad activa en el estado es una variable booleana, por lo que solo tenemos que usar el operador NOT para invertir el estado actual de cada jugador.

      JavaScript

      toggleActive =() => {
      this.setState(prevState => {
      return {
      ...prevState,
      playerOne: {
      ...prevState.playerOne,
      active: !prevState.playerOne.active
      },
      playerTwo: {
      ...prevState.playerTwo,
      active: !prevState.playerTwo.active
      }
      };
      });
      };
    • ResultHandler: contiene la lógica principal del juego que decide qué jugador ha ganado. Utiliza una función de ayuda llamada ayudante de decisión que toma dos argumentos que son el arma de cada jugador y devuelve una array que contiene dos elementos en los que el primer elemento corresponde al estado de ganar/perder del primer jugador y, de manera similar, el segundo elemento al estado del segundo jugador. Luego, el manejador de resultados actualiza el estado con los valores devueltos por la función decicerhelper.

      JavaScript

      resultHandler =() => {
      this.setState(prevState => {
      let [s1, s2] = this.deciderHelper(
      prevState.playerOne.weapon,
      prevState.playerTwo.weapon);
      return {
      ...prevState,
      playerOne: {
      ...prevState.playerOne,
      status: s1
      },
      playerTwo: {
      ...prevState.playerTwo,
      status: s2
      }
      };
      });
      this.toggleActive();
      };
    • DeciderHelper : es una función auxiliar que toma dos entradas que son armas para cada jugador y devuelve una array que consta de dos elementos, cada uno de los cuales indica el estado de victoria/pérdida del jugador 1 y el jugador 2, respectivamente. Aquí, ‘r’ significa piedra, ‘s’ significa tijera, ‘p’ significa papel, ‘w’ significa victoria y ‘l’ significa suelta. Todas las combinaciones posibles de roca, piedra, tijera se consideran en caso de empate, se devuelven ambos jugadores con estado ganador.

      JavaScript

      deciderHelper = (p1, p2) => {
        if (p1 == "r" && p2 == "s") {
          return ["w", "l"];
        }
       
        if (p1 == "r" && p2 == "p") {
          return ["l", "w"];
        }
       
        if (p1 == "r" && p2 == "r") {
          return ["w", "w"];
        }
       
        if (p1 == "p" && p2 == "r") {
          return ["w", "l"];
        }
        if (p1 == "p" && p2 == "s") {
          return ["l", "w"];
        }
        if (p1 == "p" && p2 == "p") {
          return ["w", "w"];
        }
        if (p1 == "s" && p2 == "r") {
          return ["l", "w"];
        }
        if (p1 == "s" && p2 == "p") {
          return ["w", "l"];
        }
        if (p1 == "s" && p2 == "s") {
          return ["w", "w"];
        }
      };
    • Método de procesamiento:

      JavaScript

      render() {
          return (
            <Row justify="space-around" align="middle">
              <Col className="gutter-row" xs={15} sm={15} md={5} lg={5}>
                <Title level={3}>Player One</Title>
                <Player
                  active={this.state.playerOne.active}
                  weaponUpdate={weapon => this.weaponUpdate("playerOne", weapon)}
                  weapon={this.state.playerOne.weapon}
                  status={this.state.playerOne.status}
                />
              </Col>
        
              <Col className="gutter-row" xs={15} sm={15} md={5} lg={5}>
                <Title level={3}>Player Two</Title>
                <Player
                  active={this.state.playerTwo.active}
                  weaponUpdate={weapon => this.weaponUpdate("playerTwo", weapon)}
                  weapon={this.state.playerTwo.weapon}
                  status={this.state.playerTwo.status}
                />
              </Col>
            </Row>
          );
        }
      }
        
      export default Controller;
  6. Codificación de los componentes: el código es muy simple en estos. Solo la lógica representacional reside aquí.

    • Player.js : como se mencionó anteriormente, es un componente sin estado que representa una entidad de jugador. Recibe cuatro accesorios que son el estado activo del jugador, el arma actual, el estado de ganar/perder y el controlador de funciones para actualizar el arma. Además, utiliza dos componentes, GameControls y decision box, que se analizan a continuación. Además, si las propiedades activas recibidas son verdaderas, se aplica un objeto CSS llamado glowEffect al div.

      JavaScript

      import React from "react";
      import GameControls from "../GameControls/GameControls";
      import DecisionBox from "../DecisionBox/DecisionBox";
        
      const Player = props => {
        let glowEffect = {};
        if (props.active) {
          glowEffect = {
            "-webkit-box-shadow": "0 0 20px blue",
            "-moz-box-shadow": "0 0 20px blue",
            "box-shadow": "0 0 20px blue"
          };
        }
        
        return (
          <div style={glowEffect}>
            <GameControls wUpdate={props.weaponUpdate} isActive={props.active} />
            <DecisionBox weapon={props.weapon} status={props.status} />
          </div>
        );
      };
        
      export default Player;
    • GameControls.js: Contiene tres botones roca, piedra, tijera. Si el reproductor no está activo, los botones están desactivados. Al hacer clic en el botón, se llama a la función de actualización de armas, que toma un argumento ‘p’ para papel, ‘r’ para roca, ‘s’ para tijeras y se actualiza el estado correspondiente.

      JavaScript

      import React from "react";
      import { Card } from "antd";
      import { Button } from "antd";
        
      import "antd/dist/antd.css";
        
      const GameControls = props => {
        return (
          <Card
            title="Controls"
            style={{ width: "300px", height: "250px", alignItems: "center" }}
          >
            <p style={{ alignItems: "center" }}>
              <Button
                type="dashed"
                size="large"
                shape="round"
                block
                onClick={() => props.wUpdate("r")}
                disabled={!props.isActive}
              >
                Rock
              </Button>
            </p>
        
        
            <p style={{ alignItems: "center" }}>
              {" "}
              <Button
                type="dashed"
                size="large"
                shape="round"
                block
                onClick={() => props.wUpdate("p")}
                disabled={!props.isActive}
              >
                Paper
              </Button>
            </p>
        
        
            <p style={{ alignItems: "center" }}>
              <Button
                type="dashed"
                size="large"
                shape="round"
                block
                onClick={() => props.wUpdate("s")}
                disabled={!props.isActive}
              >
                Scissors
              </Button>
            </p>
        
          </Card>
        );
      };
        
      export default GameControls;
    • DecisionBox.js : muestra dos cosas: el arma del jugador y el estado de victoria/pérdida del jugador. Recibe dos accesorios arma (‘r’ o ‘p’ o ‘s’) y estado (‘w’ o ‘l’). Se utilizan dos objetos, el mapa de armas y el mapa de estado, para asignar formas abreviadas a palabras adecuadas que se pueden mostrar en la pantalla.

      JavaScript

      import React from "react";
      import { Card } from "antd";
      import { Typography } from "antd";
        
      const { Title } = Typography;
        
      const weaponMap = {
        s: "Scissors",
        p: "Paper",
        r: "Rock"
      };
      const statusMap = {
        w: "Win",
        l: "Loose"
      };
        
      const DecisionBox = props => {
        return (
          <Card
            title="Decision Box"
            style={{
              width: "300px",
              height: "250px",
              alignItems: "center",
              marginTop: "15px"
            }}
            bodyStyle={{ textAlign: "center" }}
          >
            <Title level={1} type="warning">
              {weaponMap[props.weapon]}
            </Title>
            <Title level={2} mark type="secondary">
              {statusMap[props.status]}
            </Title>
          </Card>
        );
      };
        
      export default DecisionBox;

Producción:

Publicación traducida automáticamente

Artículo escrito por manshalamba y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *