使用reactjs的tic-tac-toe逻辑和语法

时间:2017-02-19 08:38:04

标签: javascript reactjs

我是react.js的新手,我开始尝试创建一个简单的Tic-Tac Toe应用程序,但我的逻辑存在问题。

当我在console.log中当前转弯时,我有正确的“X”或“O”字符拼贴。但是,当我在render()函数中调试它时,我得到相反的字符区块(即如果获胜者是“X”,则获胜者在模板上呈现为“O”)。

我尝试在render()函数中交换当前值的值,但它给了我一个错误。关于我在这里做错了什么想法?

我的github回购链接在这里,或者检查代码如下。 https://github.com/jchan922/tic-react-toe/blob/master/src/App.js

谢谢!

编辑:

  • CodePen

    - http://codepen.io/jchan922/pen/LxKEwm?editors=0010

  • 问题澄清

    - 即使我的逻辑是其他地方正确的控制台记录,如果获胜者是“X”,则获胜者在视图上呈现为“O”,反之亦然。我无法让我的模板呈现正确的“X”或“O”播放器。

enter image description here

class App extends Component {
    // Component Initialization
    constructor(props){
        super(props)
        this.state = {
            player_one: "X",
            player_two: "O",
            currentTurn: "X",
            board: [
                "", "", "", "", "", "", "", "", ""
            ],
            winner: null,
            moveCount: 0
        }
    }

    handleClick(index){
        if(this.state.board[index] === "" && !this.state.winner) {
            var currentBoard = this.state.board,
                count = this.state.moveCount;

            currentBoard[index] = this.state.currentTurn;
            count += 1;

            this.setState({
                board: this.state.board,
                winner: this.checkForWinner(),
                currentTurn: this.state.currentTurn === this.state.player_one ? this.state.player_two : this.state.player_one,
                moveCount: count
            });

        }
    }

    handleReset(){
        console.log("RESET")
        this.setState({
            player_one: "X",
            player_two: "O",
            currentTurn: "X",
            board: [
                "", "", "", "", "", "", "", "", ""
            ],
            winner: null,
            moveCount: 0
        })
    }

    checkForWinner(moveCount) {
        var currentTurn = this.state.currentTurn;
        var symbols = this.state.board;
        var winningCombos = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]];

        return winningCombos.find(function(combo) {
            if(symbols[combo[0]] !== "" && symbols[combo[1]] !== ""  && symbols[combo[2]] !== ""  && symbols[combo[0]] === symbols[combo[1]] && symbols[combo[1]] === symbols[combo[2]]) {
                console.log("Found a winner", currentTurn, [combo[0],combo[1],combo[2]]);
                return currentTurn;
            }
            else {
                return null;
            }

        })
    }

    // Component Render
    render() {
        console.log(this.state.currentTurn);
        return (
            <div className="app-container">
                {this.state.winner ? <h2>{`The winner is ${this.state.currentTurn}`}</h2> : null}
                <div className="board">
                    {this.state.board.map((cell, index) => {
                        return <div onClick={() => this.handleClick(index)} key={index} className="square"><p className="playerSymbol">{cell}</p></div>
                    })}
                </div>
                <div className="reset">
                    <button onClick={() => this.handleReset()} className="resetButton">RESET</button>
                </div>
            </div>
        )
    }
}
export default App;

2 个答案:

答案 0 :(得分:1)

首先,您不需要在您的州内player_oneplayer_two,只需将它们作为常量,以防您希望player_one为&#39; O&# 39;有时我更喜欢有一个布尔道具来控制谁先播放并让父组件处理它们(除非App是唯一呈现的组件但我在UI中看不到任何选择第一个的组件玩)。

其次,因为moveCount根本没有呈现,为什么你的状态呢?也许你想稍后为它添加一些渲染。

现在问题,让我们假装它是&#39; X&#39;然后,玩家点击获胜的点击,&#39; X&#39;赢了但在此之前,点击会在最后一个语句handleClick this.setState(...)等于currentturn之前触发您的this.state.player_one函数,这是&#39; X&#39;但你这样做:

this.setState({... , currentturn : this.state.currentturn === this.state.player_one ? this.state.player_two : this.state.player_one,...});

这意味着&#34;如果currentturn是X然后将其设置为O,否则将其设置为X&#34;之后因为状态更改了UI重新呈现currentturn='O',现在在你的渲染函数中the winner is {currentturn}所以它呈现the winner is O

解决方案很简单,只需将{currentturn}替换为{currentturn===player_one ? player_two : player_one},只需在声明获胜者的位置进行更改。

以下是codepen的更新:http://codepen.io/abnud1/pen/KajpWN?editors=0010

答案 1 :(得分:0)

例如,如果您想要某种可重用的代码,那么如果有4x4或5x5的木板而不是3x3的木板可以使用的代码,则需要这样的东西

只需生成一个包含XO的矩阵,其中X将是true,而O将是false

https://gist.github.com/Hovakimyan/342d579aa22a567d84d92798bf2667a6

这里的大小将是您的董事会SIZE,例如3 | 4 | 5...

  checkMatrixForWin = (matrix) => {
    const angl = [], antiAngl = []
    for (let i = 0; i < SIZE; i++) {
      let rowvalue = null
      for (let j = 0; j < SIZE; j++) {
        if (typeof matrix[j][i] !== 'boolean') break

        if (j === 0) rowvalue = matrix[j][i]

        if (rowvalue !== matrix[j][i]) {
          break
        }
        if (j === SIZE - 1) {
          return matrix[j][i]
        }
      }
      angl.push(matrix[i][i])
      antiAngl.push(matrix[i][SIZE - 1 - i])
      if (matrix[i].every(item => item === matrix[i][0])) {
        return matrix[i][0]
      }
    }
    if (angl.every(item => item === angl[0])) {
      return angl[0]
    }
    if (antiAngl.every(item => item === antiAngl[0])) {
      return antiAngl[0]
    }
  }