react实现井字棋

接上一篇文章,用vscode开发react项目,实现官网中的示例
在vscode中通过脚手架搭建项目,打开如下图:
在这里插入图片描述
此次我们只会用到index.css文件和index.js文件:
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: 50px;
    height: 50px;
  }
  
  .square:focus {
    outline: none;
  }
  
  .kbd-navigation .square:focus {
    background: #ddd;
  }
  
  .game {
    display: flex;
    flex-direction: row;
  }
  
  .game-info {
    margin-left: 20px;
  }

js文件:

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

//squar组件渲染了一个单独的button(子组件)
// class Square extends React.Component {
//     // constructor(props){
//     //     super(props);  //定义子类的构造函数是都要调用super函数,在所有含有构造函数的react组件中,构造函数必须以super(props)开头
//     //     this.state = {
//     //         value:null,
//     //     }
//     // }
//     render() {
//       return (
//         <button
//          className="square" 
//          onClick = {()=>this.props.onClick()}
//         >  
//          {this.props.value}
//         </button>
//       );
//     }
//   }

  function Square(props){
      return (
          <button className='square' onClick={props.onClick}>
              {props.value}
          </button>
      );
  }
  
  //board组件渲染了9个方块(父组件)
  class Board extends React.Component {
    //   constructor(props){    //构造函数
    //       super(props);     
    //           this.state={
    //             squares:Array(9).fill(null),   
    //             xIsNext:true,   
    //       };
    //   }
    // handleClick(i){
    //     const squares = this.state.squares.slice();  //slice()方法可从已有的数组中返回选定的元素
    //     if(calculateWinner(squares)||squares[i]){
    //         return;
    //     }
    //     squares[i]=this.state.xIsNext?'X':'O';
    //     this.setState({
    //     squares:squares,
    //     xIsNext:!this.state.xIsNext
    // });
    // }
    renderSquare(i) {
      return(
     <Square 
      value ={this.props.squares[i]}
      onClick ={()=> this.props.onClick(i)}
    //   onClick ={()=> this.handleClick(i)}
     />
      );
    }
  
    render() {
    //   const history = this.state.history;
    //   const current= history[history.length-1];
    //   const winner = calculateWinner(current.squares);  //获取历史记录中的最新一次记录确定并展示游戏状态
    //   let status;
    //   if(winner){
    //       status = '赢家为:'+winner;
    //   }else{
    //     status = '下一步执行者:'+(this.state.xIsNext?'X':'O');
    //   }
      
      return (
        <div>
          {/* <div className="status">{status}</div> */}
          <div className="board-row">
            {this.renderSquare(0)}
            {this.renderSquare(1)}
            {this.renderSquare(2)}
          </div>
          <div className="board-row">
            {this.renderSquare(3)}
            {this.renderSquare(4)}
            {this.renderSquare(5)}
          </div>
          <div className="board-row">
            {this.renderSquare(6)}
            {this.renderSquare(7)}
            {this.renderSquare(8)}
          </div>
        </div>
      );
    }
  }
  
  //game组件渲染了含有默认值的一个棋盘,爷爷组件
  class Game extends React.Component {
     constructor(props){
        super(props);
        this.state={
            history:[{
                squares:Array(9).fill(null),
            }],
            stepNumber:0,  //当前正在查看那一项历史记录
            xIsNext: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();  //slice()方法可从已有的数组中返回选定的元素
        if(calculateWinner(squares)||squares[i]){
            return;
        }
        squares[i]=this.state.xIsNext?'X':'O';
        this.setState({
        history:history.concat([{    // concat() 方法用于连接两个或多个数组。
            squares:squares,
        }]),
        stepNumber:history.length,
        xIsNext:!this.state.xIsNext,
     });
    }

    jumpTo(step){
        this.setState({
            stepNumber:step,
            xIsNext:(step%2)===0, //step为偶数时,xIsNext的状态设为true
        });
    }
    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:
            'Go to game start';
         return (
             <li key={move}>
                 <button onClick = {()=>this.jumpTo(move)}>
                     {desc}
                 </button>
             </li>
         );
        });
      let status;
      if (winner) {
         status = 'Winner: ' + winner;
      } 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>
            <ol>{moves}</ol>
          </div>
        </div>
      );
    }
  }
  
  // ========================================
  
  ReactDOM.render(
    <Game />,
    document.getElementById('root')
  );

  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 squares[a];
      }
    }
    return null;
  }

效果图:

在这里插入图片描述
到这基本结束了,但是革命尚未成功,同志任需努力!(建议自己跟着官网走一遍:地址 https://zh-hans.reactjs.org/tutorial/tutorial.html#overview

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值