使用reactjs在tic tac toe app中渲染图像 [英] Render Images in tic tac toe app using reactjs

查看:89
本文介绍了使用reactjs在tic tac toe app中渲染图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用reactjs创建一个简单的tic tac toe应用程序,其中包含两种模式:经典图像,在经典模式下我可以选择显示 X O ,而在图像模式下,我有两个显示两个图像的选项,如下所述。我的文件结构是:

I am trying to create a simple tic tac toe app using reactjs, with two modes in it: Classic and Image, in the classic mode I have the options to display X and O, while in the Image mode, I have the options two display two images which are mentioned below. My file structure is:

src
  components
    ChooseGameMode.js
    choosePlayer.js
    GameStatus.js
    Status.js
  images
    connery.svg
    square.svg
App.css
App.js
index.css
index.js
...

以下是代码我开发的:

App.js

import React, { Component } from 'react';

import './App.css';

import Status from'./components/Status';
import GameStatus from'./components/GameStatus';

class App extends Component {


  constructor(props){

    super(props)

    this.state = {

      board : Array(9).fill(null),
      player : null,
      winner : null,
      gamemode : null,
      /* array to store the ndex */
      order_ndex : []
    }

  }

  checkWinner(){

    let winLines =
      [
        ["0", "1", "2"],
        ["3", "4", "5"],
        ["6", "7", "8"],
        ["0", "3", "6"],
        ["1", "4", "7"],
        ["2", "5", "8"], 
        ["0", "4", "8"],
        ["2", "4", "6"]
      ]

    this.checkmatch(winLines)
  }

  checkmatch(winLines){
    let board = this.state.board;
    for (let index = 0; index < winLines.length; index++) {
      const [a,b,c]=winLines[index];
      if(board[a] && board[a] === board[b] && board[a] === board[c] ){
        alert('You won!');
        this.setState({
          winner : this.state.player
        })
        this.state.winner = this.state.player;
      }
    }
    if(!this.state.winner && !board.includes(null)){
      this.state.winner = 'None';
      alert('Its a Draw!');
    }
  }

  handleClick(index){

    //To render images on selecting ImageMode mode
    const images ={
      connery : require('./images/connery.svg'),
      square : require('./images/square.svg')
    }


    if(this.state.player && !this.state.winner && this.state.gamemode === "Classic"){

      let newBoard = this.state.board

      if(this.state.board[index]===null){

        newBoard[index] = this.state.player
        /* push the last index into the array */
        this.state.order_ndex.push(index) 
        this.setState({
          board: newBoard,
          player: this.state.player==="X" ? "O" : "X"
        })

        this.checkWinner()

      }
    }

    else{

      let newBoard = this.state.board

      if(this.state.board[index]===null){

        newBoard[index] = this.state.player
        /* push the last index into the array */
        this.state.order_ndex.push(index) 
        this.setState({
          board: newBoard,
          player: this.state.player=== images.connery ? images.square : images.connery
        })

        this.checkWinner()

      }

    }
  } 

  setPlayer(player){
    this.setState({player})

  }

  setGameMode(gamemode){
    console.log(gamemode)
    this.setState({gamemode})

  }

  renderBoxes(){
    return this.state.board.map(
      (box, index) => 
      <div className="box" key={index} 
        onClick={()=> {this.handleClick(index)}}>
        {box}
      </div>
    )
  }

  reset(){

    this.setState({
      board : Array(9).fill(null),
      player :  null,
      winner : null,
      gamemode : null,
      order_ndex : []

    })

  } 

  undo() {
    let ndex = this.state.order_ndex.pop() 
    let newBoard = this.state.board
    let prev = newBoard[ndex]
    newBoard[ndex] = null
    this.setState({
      board: newBoard,
      player: prev
    })
  }

  render() {


    return (

      <div className="container">
        <h1>Tic Tac Toe App</h1>

        <GameStatus 
          gamemode ={this.state.gamemode} 
          setGameMode = {(e)=> this.setGameMode(e)}
        />

        <Status
          player={this.state.player} 
          setPlayer={(e) => this.setPlayer(e)}
          winner = {this.state.winner}
        />

        <div className="board">

          {this.renderBoxes()}

        </div>
        <div className="btn">
          <button className='reset' onClick = {() => this.reset()}> Reset </button>
          <div className="divider"/>
          <button className='reset' disabled ={this.state.winner} onClick = {() => this.undo()}> Undo </button>
        </div>

      </div>

    );
  }
}

export default App;

ChooseGameMode.js

import React, { Component } from 'react';

class ChooseGameMode extends Component{

    handleForm(e){
        e.preventDefault();
        this.props.gamemode(e.target.gamemode.value);
    }

    render(){
        return (
            <form onSubmit={(e)=> this.handleForm(e)}>
                <label>
                    Classic
                    <input type="radio" name="gamemode" value="Classic"/>
                </label>

                <label>
                    Frontenddevlandia
                    <input type="radio" name="gamemode" value="Frontenddevlandia"/>
                </label>

                <input type="submit" value="Submit" />
            </form>
        )

    }
}

export default ChooseGameMode;

choosePlayer.js

import React, { Component } from 'react';

class Player extends Component{

    handleForm(e){
        e.preventDefault();
        this.props.player(e.target.player.value);
    }

    render(){
        return (
            <form onSubmit={(e)=> this.handleForm(e)}>
                <label>
                    Player X
                    <input type="radio" name="player" value="X"/>
                </label>

                <label>
                    Player O
                    <input type="radio" name="player" value="O"/>
                </label>

                <input type="submit" value="Start" />
            </form>
        )

    }
}

export default Player;

GameStatus.js

import React, { Component } from 'react';

import ChooseGameMode from'./ChooseGameMode';


class GameStatus extends Component {

    handleSetGameMode(e){
        this.props.setGameMode(e)
    }

    render(){

        return (this.props.gamemode ? 
              <h3>You are playing the {this.props.gamemode} mode</h3> : 
              <ChooseGameMode gamemode={(e) => this.handleSetGameMode(e)} />
        )
    }
}

export default GameStatus;

Status.js

import React, { Component } from 'react';

import Player from'./choosePlayer';

class Status extends Component {

    handleSetPlayer(e){
        this.props.setPlayer(e)
    }

    renderHtml(){
        if (this.props.winner){
            return (<h2>Winner is {this.props.winner}</h2>)
        } else {
            return this.props.player ? 
            <h2>Next player is {this.props.player}</h2> : 
            <Player player={(e) => this.handleSetPlayer(e)} />
        }
    }

    render(){

        return (<span>{this.renderHtml()}</span>)
    }
}

export default Status;

当我选择图像模式并选择播放器而非渲染时图像,它只是将图像文件的路径渲染到应用程序中。我使用 require('./ images / connery.svg'),来渲染图像。
我可能知道我做错了什么,我也没有在这里使用Redux进行状态管理,因为我是学习反应和redux的新手,有人可以请教我如何在现有应用程序中实现redux,这样可以更好地处理状态管理,而不是将状态作为不同组件的单独道具传递?关于如何实现这一点以及任何其他改进或建议的一般想法也将非常有用。此外,正如所建议的那样,这是我的 codesandbox链接

When I select the Image mode and choose the player instead of rendering the image, its simply rendering the path of the image file into the app. I used require('./images/connery.svg'), for rendering the image. May I know what am I doing wrong, also I haven't used Redux here for state management, as I am new to learning react and redux, can someone please help me on how to implement redux into this existing app, so that the state management can be handled in a better way rather than passing the states as individual props for different components? A general idea on how to implement this and any other improvements or suggestions will also be really helpful. Also, as suggested this is my codesandbox link.

推荐答案

要使用图像,您无需修改​​经典代码,只需在工作经典代码中更新renderBoxes()并删除图像您添加到代码的其他部分,例如在App.js handleClick()中。

To use images, you do not need to modify your classic code, you only need to update renderBoxes() in your working classic code and remove the conditions for Image that you added to other parts of the code e.g in App.js handleClick().

const connery = require("./images/connery.svg"); // or import connery from "./images/connery.svg"
const square = require("./images/square.svg");

  ...
  
  renderBoxes() {
    
    const isFrontend = this.state.gamemode === 'Image'
  
    return this.state.board.map((box, index) => (
      <div
        className="box"
        key={index}
        onClick={() => {
          this.handleClick(index);
        }}
      >
        {box === "X" && isFrontend && <img src={connery} />}
        {box === "O" && isFrontend && <img src={square} />}
        {!isFrontEnd && box}
      </div>
    ));
  }

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

为了让您的问题在下次IMO时不那么麻烦,您可以在 https://codesandbox.io上托管您的代码/ s 并且只在这里显示问题。

To make your question less cumbersome next time IMO you can host your code at https://codesandbox.io/s and just show only the question here.

这篇关于使用reactjs在tic tac toe app中渲染图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆