Javascript React.JS组件类中的递归函数

Javascript React.JS组件类中的递归函数,javascript,reactjs,Javascript,Reactjs,我对使用React的项目有问题。这是一个井字游戏,我正在尝试实现电脑播放器 当人类玩家点击一个方块(场分量)时,这会触发 线路板组件中的updateField()函数。它还调用computerMove()函数,该函数反过来调用minimax()函数 极大极小函数是递归定义的。但是,当代码执行到达调用minimax(possibleGame)的行时,我会收到以下错误消息 [ERROR] react-dom Uncaught TypeError: Cannot read property 'mini

我对使用React的项目有问题。这是一个井字游戏,我正在尝试实现电脑播放器

当人类玩家点击一个方块(场分量)时,这会触发 线路板组件中的updateField()函数。它还调用computerMove()函数,该函数反过来调用minimax()函数

极大极小函数是递归定义的。但是,当代码执行到达调用minimax(possibleGame)的行时,我会收到以下错误消息

[ERROR] react-dom Uncaught TypeError: Cannot read property 'minimax' of undefined
显然这个函数是未知的,我不理解,因为我将它绑定到了Board作用域

class Field extends React.Component{

  render(){
    return(
      <button className='field' onClick={this.props.clickFunc}>{this.props.value}</button>
    );
  }
}

class Board extends React.Component{
  constructor(){
    super();
    this.state = {
      fields: Array(9).fill(null),
    };
    this.minimax = this.minimax.bind(this);
    this.updateField = this.updateField.bind(this);
    this.computerMove = this.computerMove.bind(this);
  }

  updateField(id){
    const fields = this.state.fields.slice();

    // only proceed if field hasn't been taken yet
    if (fields[id] == null && this.props.winner == null){
      fields[id] = this.props.playerSymbol;
      this.setState({fields: fields});

      this.computerMove(fields);
    } 
  }

// check if somebody won the game
  checkWinner(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;

  }

  computerMove(fields){
    var computerSymbol = (this.props.playerSymbol == "X" ? "O" : "X");
    var game = {fields: fields,turn:computerSymbol};
    var result = this.minimax(game);
    var newBoard = fields.slice();
    newBoard[result[1]] = computerSymbol;
    this.setState({fields: newBoard}); 

    }

  score(game){
    // check for winner
    var result = this.checkWinner(game.fields);
    if (result !== null){
      if (result == this.props.playerSymbol){
        return -10;
      } else{
        return 10;
      }
    }else{
      return 0;
    }
  }

  minimax(game) {
    var score = this.score(game);
    if (score !== 0){
      return score;
    }
    var scores = [];
    var moves = [];

    game.fields.forEach(function(value,index,arr){
      if (value==null){
        var newField = arr.slice();
        newField[index] = game.turn;

        var nextTurn = (game.turn == "X" ? "O" : "X");
        var possibleGame = {fields: newField,turn:nextTurn};
        var result = this.minimax(possibleGame);
        scores.push(result[0]);
        moves.push(index);
      }
    }); 
    if (game.turn == this.props.playerSymbol){
      var max_ind = scores.indexOf(Math.max(...scores));
      return [scores[max_ind],moves[max_ind]];
    } else{
      var min_ind = scores.indexOf(Math.min(...scores));
      return [scores[min_ind],moves[min_ind]];
    }   
  }

  render(){
    var fields = this.state.fields;

    // check if somebody won

    const winner = this.checkWinner(fields);
    if (winner){
      this.props.declareWinner(winner);
    }


    return (
      <div className="animated fadeInUp board-container">
        <div className='row'>
          <Field value={fields[0]} clickFunc={() => this.updateField(0)} />
          <Field value={fields[1]} clickFunc={() => this.updateField(1)}/>
          <Field value={fields[2]} clickFunc={() => this.updateField(2)}/>
        </div>
        <div className='row'>
          <Field value={fields[3]} clickFunc={() => this.updateField(3)} />
          <Field value={fields[4]} clickFunc={() => this.updateField(4)}/>
          <Field value={fields[5]} clickFunc={() => this.updateField(5)}/>
        </div>
        <div className='row'>
          <Field value={fields[6]} clickFunc={() => this.updateField(6)}/>
          <Field value={fields[7]} clickFunc={() => this.updateField(7)}/>
          <Field value={fields[8]} clickFunc={() => this.updateField(8)}/>
        </div>
      </div>
      )
  }
}
类字段扩展了React.Component{
render(){
返回(
{this.props.value}
);
}
}
类板扩展React.Component{
构造函数(){
超级();
此.state={
字段:数组(9)。填充(null),
};
this.minimax=this.minimax.bind(this);
this.updateField=this.updateField.bind(this);
this.computerMove=this.computerMove.bind(this);
}
更新字段(id){
const fields=this.state.fields.slice();
//只有在尚未获取字段的情况下才能继续
if(字段[id]==null&&this.props.winner==null){
字段[id]=this.props.playerSymbol;
this.setState({fields:fields});
这是计算机移动(字段);
} 
}
//检查是否有人赢了这场比赛
胜利者(方格){
常量行=[
[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(设i=0;i
this.updateField(1)}/>
this.updateField(2)}/>
this.updateField(3)}/>
this.updateField(4)}/>
this.updateField(5)}/>
this.updateField(6)}/>
this.updateField(7)}/>
this.updateField(8)}/>
)
}
}
可以在此处测试整个代码:

我还试图提出一个MWE(),然而,这个例子之所以有效,是有原因的


谢谢你的帮助

此的值取决于调用函数的方式和位置

在大多数情况下,
this
的值取决于函数的调用方式。它不能在执行期间通过赋值进行设置,每次调用函数时可能会有所不同。ES5引入了bind方法来设置函数this的值,而不管它是如何调用的,ES2015引入了其this是词汇范围的箭头函数(它被设置为封闭执行上下文的this值)。

您需要显式绑定此,以便在函数中一致使用

game.fields.forEach(function(value,index,arr){
  if (value==null){
    var newField = arr.slice();
    newField[index] = game.turn;

    var nextTurn = (game.turn == "X" ? "O" : "X");
    var possibleGame = {fields: newField,turn:nextTurn};
    var result = this.minimax(possibleGame);
    scores.push(result[0]);
    moves.push(index);
  }
}.bind(this));
或者,使用箭头功能:

game.fields.forEach((value,index,arr) => {
  if (value==null){
    var newField = arr.slice();
    newField[index] = game.turn;

    var nextTurn = (game.turn == "X" ? "O" : "X");
    var possibleGame = {fields: newField,turn:nextTurn};
    var result = this.minimax(possibleGame);
    scores.push(result[0]);
    moves.push(index);
  }
});
箭头函数表达式的语法比函数表达式短,并且不绑定自己的this、arguments、super或new.target。这些函数表达式最适合于非方法函数,并且不能用作构造函数。


维护递归规则:假设我们有一个父子树,那么在下面的小节中,您将找到一个示例

在构造函数中:

this.checkSlug = this.checkSlug.bind(this);
this.onViewToBar = this.onViewToBar.bind(this);

递归函数示例:

  checkSlug = (slug, parent) => {
    for (let i = 0; i < parent.length; i++) {
      if (parent[i].children && parent[i].slug !== slug) {
        const value = this.checkSlug(slug, parent[i].children);
        if (value){
          return value;
        }
      } else {
        if (parent[i].slug === slug) {
          return parent[i];
        }
      }
    }
  }
game.fields.forEach((值、索引、arr)=>{
 onViewToBar({ slug }) {
    this.setState({ slug: slug });
    const { cursor, data } = this.state;

    let node =this.checkSlug(slug, data);
  }
```