美文网首页
React官方教程游戏改进完善

React官方教程游戏改进完善

作者: iBleakNight | 来源:发表于2019-12-11 10:21 被阅读0次

React官方教程中的井字棋,根据文档提供的改进意见进行改进完善。

1.改进功能

  1. 在游戏历史记录列表显示每一步棋的坐标,格式为 (列号, 行号)。
  2. 在历史记录列表中加粗显示当前选择的项目。
  3. 使用两个循环来渲染出棋盘的格子,而不是在代码里写死(hardcode)。
  4. 添加一个可以升序或降序显示历史记录的按钮。
  5. 每当有人获胜时,高亮显示连成一线的 3 颗棋子。
  6. 当无人获胜时,显示一个平局的消息。

2.核心代码

2.1 index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}
  
  class Board extends React.Component {
    renderSquare(i) {
      return (
        <Square 
          value={this.props.squares[i]}
          onClick={() => this.props.onClick(i)} 
        />
      );
        
    }
  
    render() {
      return (
        <div>
          {
            Array(3).fill(null).map((item,x) =>(
              <div className="board-row" key={x}>
                {
                  Array(3).fill(null).map((item,y) =>(
                    this.renderSquare(3 * x + y)
                  ))
                }
              </div>
            ))
          }
        </div>
      );
    }
  }
  
  class Game extends React.Component {
    constructor(props){
      super(props);
      this.state = {
        history: [{
          squares: Array(9).fill(null),
          coordinate:'',
        }],
        stepNumber: 0,
        xIsNext: true,
        sort: true,
      }
    }

    handleClick(i) {
      const history = this.state.history.slice(0,this.state.stepNumber + 1);
      const current = history[history.length - 1];
      const squares = current.squares.slice();
      if(calculateWinner(squares) || squares[i]){
        return;
      }
      squares[i] = this.state.xIsNext ? 'X' : 'O';
      this.setState({
        history: history.concat([{
          squares: squares,
          coordinate: calculateCoordinate(i),
        }]),
        stepNumber: history.length,
        xIsNext: !this.state.xIsNext,
      });
    }

    order() {
      this.setState({
        sort: !this.state.sort,
      })
    }

    jumpTo(step){
      for (let i = 0; i < 9; i++) {
        document.getElementsByClassName('square')[i].style = "";
      }

      this.setState({
        stepNumber: step,
        xIsNext: (step % 2) === 0,
      });
    }

    render() {
      const history = this.state.history;
      const current = history[this.state.stepNumber];
      const winner = calculateWinner(current.squares);

      const moves = history.map((step,move) => {
        const desc = move ?
        'Go to move #' + move + ",坐标为:" + step.coordinate:
        'Go to game start';

        return (
          <li key={move}>
            <button 
              onClick={() => this.jumpTo(move)}
              className={move === this.state.stepNumber ? 'bold' : ''}
            >
              {desc}
            </button>
          </li>
        )
      })

      let status;
      if(winner){
        status = 'Winner: ' + winner.winnerName;
        for(let i of winner.winIndex) {
          document.getElementsByClassName('square')[i].style = "background:black;color: white;"
        }
      }else if(history.length > 9){
        status = 'This is a draw.'
      }else{
        status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
      }

      return (
        <div className="game">
          <div className="game-board">
            <Board 
              squares={current.squares}
              onClick={(i) => this.handleClick(i)}
            />
          </div>
          <div className="game-info">
            <div>{status}</div>
            <button onClick={() => this.order()}>
              {this.state.sort ? '倒序' : '正序'}
            </button>
            <ol>{this.state.sort ? moves : moves.reverse()}</ol>
          </div>
        </div>
      );
    }
  }

  function calculateCoordinate(i){
    switch(i){
      case 0:
        return '(1,1)';
        break;
      case 1:
        return '(1,2)';
        break;
      case 2:
        return '(1,3)';
        break;
      case 3:
        return '(2,1)';
        break;
      case 4:
        return '(2,2)';
        break;
      case 5:
        return '(2,3)';
        break;
      case 6:
        return '(3,1)';
        break;
      case 7:
        return '(3,2)';
        break;
      case 8:
        return '(3,3)';
        break;
      default:
        break;
    }
  }

  function calculateWinner(squares) {

    const lines = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8],
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      [0, 4, 8],
      [2, 4, 6],
    ];
    for (let i = 0; i < lines.length; i++) {
      const [a, b, c] = lines[i];
      if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
        return {
          winnerName:squares[a],
          winIndex: [a,b,c],
        }
      }
    }
    return null;
  }
   
  ReactDOM.render(
    <Game />,
    document.getElementById('root')
  );

2.2 index.css

body {
    font: 14px "Century Gothic", Futura, sans-serif;
    margin: 20px;
  }
  
  ol, ul {
    padding-left: 30px;
  }
  
  .board-row:after {
    clear: both;
    content: "";
    display: table;
  }
  
  .status {
    margin-bottom: 10px;
  }
  
  .square {
    background: #fff;
    border: 1px solid #999;
    float: left;
    font-size: 24px;
    font-weight: bold;
    line-height: 34px;
    height: 34px;
    margin-right: -1px;
    margin-top: -1px;
    padding: 0;
    text-align: center;
    width: 34px;
  }
  
  .square:focus {
    outline: none;
  }
  
  .kbd-navigation .square:focus {
    background: #ddd;
  }
  
  .game {
    display: flex;
    flex-direction: row;
  }
  
  .game-info {
    margin-left: 20px;
  }

  /* 新增样式 */
  button.bold {
    font-weight: bold;
  }

3.完成效果

效果1
效果2
效果3
效果4

相关文章

  • React官方教程游戏改进完善

    React官方教程中的井字棋,根据文档提供的改进意见进行改进完善。 1.改进功能 在游戏历史记录列表显示每一步棋的...

  • React-Route相关

    官方教程 react-route官方教程非常完善,而且一步一步,通俗易懂,入门可以参看官方教程https://gi...

  • 充电站

    一、前端 ES6教程-菜鸟教程 React官方文档-中文 Vue官方文档-中文 Antd UI组件官方文档 ECh...

  • 2020-03-12

    React Router教程 React项目的可用的路由库是 React-Router ,当然这也是官方支持的。它...

  • React Router教程

    React Router教程 React项目的可用的路由库是React-Router,当然这也是官方支持的。它也分...

  • react-native-ble-manager在安卓端的配置

    官方教程:https://github.com/innoveit/react-native-ble-manager

  • react学习

    react脚手架大集合 react4.0 官网redux入门教程react-native中文官网react官方文档...

  • React Native 封装Android原生UI组件(含通信

    说明 本教程根据React Native 中文网的封装原生UI组件文档说明进行完善。 前言 React Nativ...

  • awesome-react-native

    React React 中文文档一定要看官方文档 React 入门实例教程阮一峰老师出品,最好的 react 入门...

  • react官网井字棋的修改完善

    跟着react官方文档进行了井字游戏的开发,最后刚好有时间就进行了部分修改与完善。参考地址:https://blo...

网友评论

      本文标题:React官方教程游戏改进完善

      本文链接:https://www.haomeiwen.com/subject/qmcogctx.html