3

我正在尝试为 Android 应用程序制作井字游戏。我打算制作的井字游戏模式是人机对抗。但问题是程序没有更新我的 switchPlayer 函数中的切换过程(setState),因为在执行 setState 后,Previous player 和 Current player 是相同的。switchPlayer 函数的预期输出:上一个玩家:1,当前玩家:-1,但实际输出:上一个玩家:1,当前玩家:1。

我也尝试使用其他 Stackoverflow 问题中建议/推荐的回调方法,但仍然无法正常工作。我做对了吗?任何建议将不胜感激。先感谢您。

代码如下:

switchPlayer = (newPlayer) => {
   console.log("Previous player: "+this.state.currentPlayer);
   this.setState(

   {currentPlayer: newPlayer},
   function () {console.log("Current player: "+this.state.currentPlayer); }

   );
};

onTilePress = (row, col, ValidMove) => {

   if (ValidMove == 1) {  //If move is valid

       //Dont allow tiles to change
       var value = this.state.gameState[row][col];
       if (value !== 0) { return;}

       //Identify and grab current player
       var PlayerNow = this.state.currentPlayer;   

       console.log(row, col, PlayerNow);
       //Set the correct tile...
       var arr = this.state.gameState.slice();
       arr[row][col] = PlayerNow;
       this.setState({gameState: arr});

       //Switch to other player
       if (PlayerNow == 1) { //if player 1, then change to bot
           this.switchPlayer(-1);
       }            
       else if (PlayerNow == -1) {
           this.switchPlayer(1);
       }

       console.log("New current player " + this.state.currentPlayer);

       //check winner
       var winner = this.getWinner();  //get the winner update
       if (winner == 1) {
          Alert.alert("Player 1 has won!");
          this.initializeGame();
       }
       else if (winner == -1){
          Alert.alert("Bot has won!");
          this.initializeGame();
       }
       else if (this.checkTie() == 9){ //check if the match is a draw
          Alert.alert("It's a draw!");
          this.initializeGame();
       }
       //Alert.alert("It's Player "+takePlayer+"'s turn!");
       this.BotMove();
   }
   else {
       Alert.alert("Player 1, please make a move!");
   }

}
4

2 回答 2

1

如果您的问题是您希望调用后的日志语句switchPlayer()已经包含状态更改...那么您必须将调用后的所有内容放入switchPlayer已传播的回调中switchPlayer

switchPlayer = (newPlayer, cb) => {
   console.log("Previous player: "+this.state.currentPlayer);
   this.setState(
       {currentPlayer: newPlayer},
       function () { 
          console.log("Current player: "+this.state.currentPlayer);
          // Callers should put their code 
          if (cb) {
              cb();
          }
       }
   );
};

onTilePress = (row, col, ValidMove) => {
       // Switch to other player
       if (PlayerNow == 1) { //if player 1, then change to bot
           this.switchPlayer(-1, () => {
                // Here, you know the state has been updated
            });
       }            
       else if (PlayerNow == -1) {
             ....
       }
       // This code executes before the state is changed, you get the old state
       // All your code should really be in the callbacks to `switchPlayer`
       // or to any method that calls `setState`
       console.log("New current player " + this.state.currentPlayer);
       ...
}

于 2021-09-10T10:44:27.540 回答
0

从反应文档:

因为 this.props 和 this.state 可能是异步更新的,所以你不应该依赖它们的值来计算下一个状态。

如果您想处理更新,您可以尝试componentDidUpdate

更新发生后立即调用 componentDidUpdate()。初始渲染不调用此方法。

componentDidUpdate(prevProps, prevState) {
  if (this.state.currentUser !== prevState.currentUser) {
    console.log('previous user:', prevState.currentUser);
    console.log('current user:', this.state.currentUser);
  }
}

如果您只想检查某些内容是否已更新(不与之前的值进行比较),您可以使用render

render() {
  console.log('current user', this.state.currentUser);
  /* ... */
}

还有一种方法componentWillUpdate(nextProps, nextState)可以比较当前状态和下一个状态,但现在它被标记为不安全,所以你不应该使用它

componentWillUpdate(nextProps, nextState) {
  if (this.state.currentUser !== nextState.currentUser) {
    console.log('current user:', this.state.currentUser);
    console.log('next user:', nextState.currentUser);
  }
}

https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate

一个可以解决很多问题的技巧:不要function(){}用作回调,而是使用箭头函数() => {},因为function(){}有它自己的this而箭头函数没有

于 2021-09-10T10:52:20.863 回答