【问题标题】:Render Images in tic tac toe app using reactjs使用 reactjs 在井字游戏应用程序中渲染图像
【发布时间】:2018-10-16 00:03:13
【问题描述】:

我正在尝试使用 reactjs 创建一个简单的井字游戏应用程序,其中有两种模式:ClassicImage,在经典模式下,我可以选择显示 XO,在图像模式下,我有两个选项,显示两个图像,如下所述。我的文件结构是:

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;

选择GameMode.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;

选择播放器.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 进行状态管理,因为我是学习 react 和 redux 的新手,有人可以帮助我如何在这个现有的应用程序中实现 redux,以便状态管理可以以更好的方式处理,而不是将状态作为不同组件的单独道具传递?关于如何实现这一点以及任何其他改进或建议的一般想法也将非常有帮助。另外,正如建议的那样,这是我的codesandbox link

【问题讨论】:

    标签: javascript reactjs redux tic-tac-toe


    【解决方案1】:

    要使用图像,您不需要修改经典代码,您只需要更新工作经典代码中的 renderBoxes() 并删除您添加到代码其他部分的Image 条件,例如在 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 托管您的代码,并在此处仅显示问题。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    相关资源
    最近更新 更多