首页 > 解决方案 > React native:为什么我会收到“未捕获的错误:超出最大调用堆栈大小”?

问题描述

我已经编写了下面的代码(请注意,一些不相关的功能已被删除)。

我正在尝试制作玩家与计算机的井字游戏。但是每次我尝试在 Android Studio 上运行代码时,Uncaught error: Maximum call stack size exceeded都会显示,特别是当轮到计算机采取行动时。我认为错误出在onTilePress函数中,但我不确定如何解决。有谁知道那里有什么问题?任何建议将不胜感激。先感谢您。

/* eslint-disable prettier/prettier */

...

export default class TicTacToe2 extends React.Component {

    constructor(props){
        super(props);
        
        this.state = {
            gameState: [
                [0, 0, 0],
                [0, 0, 0],
                [0, 0, 0]
            ] ,
            currentPlayer: 1,
        }
        //tilesSelected : 0;
    }

    componentDidMount(){  //To start the first render... I guess
        this.initializeGame();
    }

    //Reset the gameboard
    initializeGame = () => {
        this.setState({gameState:
            [
                [0, 0, 0],
                [0, 0, 0],
                [0, 0, 0]
            ],
            currentPlayer: 1,        
        });
    }

    checkTie = () => {
      ...
    }

    //To check if the tile selected is owned
    checkTilesOwner = (row, col) => {
        var arr = this.state.gameState;
        
        if (arr[row][col] == 1){  //Tile owned by Player 1
            //Alert.alert("Owned by player 1!");  //remove comment for trial-and-error
            this.BotMove();
        }
        else if (arr[row][col] == -1) {  //Tile owned by Bot
            //Alert.alert("Owned by Bot!");  //remove comment for trial-and-error
            this.BotMove();
        }
        else {  //Empty tile
            this.onTilePress(row, col);  //Select the tile
        }
    }

    //Return 1 if player 1 won, -1 if player 2 / bot won, or 0 if no one has won
    getWinner = () => {
       ...
    }
    
    BotMove = () => {
        var RandRow = Math.floor(Math.random() * 3) + 0;  //Generate random number for Row
        var RandCol = Math.floor(Math.random() * 3) + 0;  //Generate random number for Col

        this.checkTilesOwner(RandRow, RandCol);
    }

    onTilePress = (row, col) => {

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

        //Identify and grab current player
        var currentPlayer = this.state.currentPlayer;
        
        //Set the correct tile...
        var arr = this.state.gameState.slice();
        arr[row][col] = currentPlayer;
        this.setState({gameState: arr});

        //Switch to other player
        var nextPlayer = (currentPlayer == 1) ? -1 : 1;  //if yes, then change to -1; else, then change to 1
        this.setState({currentPlayer: nextPlayer});

        //Alert.alert(nextPlayer);

        //Check if the match is tie
        var checkDraw = this.checkTie();

        //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 (checkDraw == 9){
            Alert.alert("It's a draw!");
            this.initializeGame();    
        }
        
        //Identify the current player: 1 is human, -1 is bot
        var takePlayer = '' + nextPlayer;
        if (takePlayer == 1) {
            Alert.alert("Player 1's turn!");
        }
        else if (takePlayer == -1) {  //If it is Bot's turn to nmake a move, then trigger BotMove
            Alert.alert("Bot's turn!");
            this.BotMove();  //Uncaught error: Maximum call stack size exceeded  //possible cause: endless loop
        }

    }

    onNewGamePress = () => {
        this.initializeGame();
    }

    renderIcon = (row, col) => {
        var value = this.state.gameState[row][col];
        switch(value) {
            case 1:
                return <TouchableOpacity><Text style={styles.tileX}>X</Text></TouchableOpacity>;
            case -1: 
                return <TouchableOpacity><Text style={styles.tileO}>O</Text></TouchableOpacity>;
            default: 
                return <View />
        }
    }

    render() {
        return (
            //Container for Gameboard
            ...
        );
    }
}

标签: reactjs

解决方案


是的,你的BotMovecheckTilesOwner是循环的。

尝试将您的逻辑简化为

  onTilePress(...) {
    // think what needs to be done
    // get only stuff you need without moving it
    
    this.BotMove(...)
  }

不要将思维代码(逻辑)与行动本身混为一谈。因为否则你最终会接到很多this.setState电话。这不仅会导致很多循环问题,而且只会帮助您理解业务逻辑,在您的情况下,您的游戏逻辑:)

将您的逻辑与您的渲染分开。


推荐阅读