哎chess.js onangular onDrop丑

Ai chess.js on angular onDrop ugly

无法读取未定义的 属性 'moves'

你好,我目前正在和Angular

一起下棋

你好我不能让人工智能工作,这件作品卡在了 mause

我目前使用 chess.js 和棋盘库 但问题是AI主要写在jquery

如果我评论那几行,这有效但 Ai 无效

onDrop: onDrop, onMouseoutSquare: onMouseoutSquare, onMouseoverSquare: onMouseoverSquare, onSnapEnd: onSnapEnd,

Angular代码

import { Component, OnInit } from '@angular/core';
import * as ChessBoard from 'chessboardjs/www/js/chessboard';
declare var $: any;

declare var ChessBoard: any;
declare var Chess: any;
@Component({
  selector: 'app-chess',
  templateUrl: './chess.component.html',
  styleUrls: ['./chess.component.scss']
})
export class ChessComponent implements OnInit {
  board: any;
  game: any;

  constructor() { }



  ngOnInit() {
////////////////////////// 7


      let minimaxDepth = 2;
      initGame();

    function setDepth(depth){
      console.log("este es el "+depth);
      document.getElementById('difficulty').style.display = 'none';
      document.getElementById('chessboard').style.display = 'block';
      document.getElementById('restart').style.display = 'block';
      console.log(depth);
      minimaxDepth = depth;
    }

      function initGame(){
       //document.getElementById('chessboard').style.display = 'none';
        document.getElementById('gameover').style.display = 'none';
        document.getElementById('restart').style.display = 'none';
        document.getElementById('difficulty').style.display = 'block';

        $('.easy').click(function(){
          setDepth(0);
        });
        $('.medium').click(function(){
          setDepth(1);
        });
        $('.hard').click(function(){
          setDepth(2);
        });


      }


      $('.restartGame').click(function(){
        this.board.clear();
        this.board.start();
        this.game.reset();
        initGame();
      });



        // game = new Chess();
    this.game = new Chess();

      let removeGreySquares = function() {
        $('#chessboard .square-55d63').css('background', '');
      };


      let greySquare = function(square) {
        let squareEl = $('#chessboard .square-' + square);

        let background = '#a9a9a9';
        if (squareEl.hasClass('black-3c85d') === true) {
          background = '#696969';
        }

        squareEl.css('background', background);
      };




      // uses the minimax algorithm with alpha beta pruning to caculate the best move
      let calculateBestMove = function() {

        let possibleNextMoves = this.game.moves();
        let bestMove = -9999;
        let bestMoveFound;

        for (let i = 0; i < possibleNextMoves.length; i++) {
          let possibleNextMove = possibleNextMoves[i];
          this.game.move(possibleNextMove);
          let value = minimax(minimaxDepth, -10000, 10000, false);
          this.game.undo();
          if (value >= bestMove) {
            bestMove = value;
            bestMoveFound = possibleNextMove;
          }
        }
        return bestMoveFound;
      };


      // minimax with alhpha-beta pruning and search depth d = 3 levels
      let minimax = function(depth, alpha, beta, isMaximisingPlayer) {
        if (depth === 0) {
          return -evaluateBoard(this.game.board());
        }

        let possibleNextMoves = this.game.moves();
        let numPossibleMoves = possibleNextMoves.length;
        let bestMove = -9999;
        if (isMaximisingPlayer) {

          for (let i = 0; i < numPossibleMoves; i++) {
            this.game.move(possibleNextMoves[i]);
            bestMove = Math.max(bestMove, minimax(depth - 1, alpha, beta, !isMaximisingPlayer));
            this.game.undo();
            alpha = Math.max(alpha, bestMove);
            if (beta <= alpha){
              return bestMove;
            }
          }

        } else {
          let bestMove = 9999;
          for (let i = 0; i < numPossibleMoves; i++) {
            this.game.move(possibleNextMoves[i]);
            bestMove = Math.min(bestMove, minimax(depth - 1, alpha, beta, !isMaximisingPlayer));
            this.game.undo();
            beta = Math.min(beta, bestMove);
            if (beta <= alpha){
              return bestMove;
            }
          }
        }

        return bestMove;
      };


      // the evaluation function for minimax
      let evaluateBoard = function(board) {
        let totalEvaluation = 0;
        for (let i = 0; i < 8; i++) {
          for (let j = 0; j < 8; j++) {
            totalEvaluation = totalEvaluation + getPieceValue(board[i][j], i, j);
          }
        }
        return totalEvaluation;
      };


      let reverseArray = function(array) {
        return array.slice().reverse();
      };

      let whitePawnEval =
        [
          [0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0],
          [5.0,  5.0,  5.0,  5.0,  5.0,  5.0,  5.0,  5.0],
          [1.0,  1.0,  2.0,  3.0,  3.0,  2.0,  1.0,  1.0],
          [0.5,  0.5,  1.0,  2.5,  2.5,  1.0,  0.5,  0.5],
          [0.0,  0.0,  0.0,  2.0,  2.0,  0.0,  0.0,  0.0],
          [0.5, -0.5, -1.0,  0.0,  0.0, -1.0, -0.5,  0.5],
          [0.5,  1.0,  1.0,  -2.0, -2.0,  1.0,  1.0,  0.5],
          [0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0]
        ];

      let blackPawnEval = reverseArray(whitePawnEval);

      let knightEval =
        [
          [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0],
          [-4.0, -2.0,  0.0,  0.0,  0.0,  0.0, -2.0, -4.0],
          [-3.0,  0.0,  1.0,  1.5,  1.5,  1.0,  0.0, -3.0],
          [-3.0,  0.5,  1.5,  2.0,  2.0,  1.5,  0.5, -3.0],
          [-3.0,  0.0,  1.5,  2.0,  2.0,  1.5,  0.0, -3.0],
          [-3.0,  0.5,  1.0,  1.5,  1.5,  1.0,  0.5, -3.0],
          [-4.0, -2.0,  0.0,  0.5,  0.5,  0.0, -2.0, -4.0],
          [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0]
        ];

      let whiteBishopEval = [
        [ -2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0],
        [ -1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -1.0],
        [ -1.0,  0.0,  0.5,  1.0,  1.0,  0.5,  0.0, -1.0],
        [ -1.0,  0.5,  0.5,  1.0,  1.0,  0.5,  0.5, -1.0],
        [ -1.0,  0.0,  1.0,  1.0,  1.0,  1.0,  0.0, -1.0],
        [ -1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0, -1.0],
        [ -1.0,  0.5,  0.0,  0.0,  0.0,  0.0,  0.5, -1.0],
        [ -2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0]
      ];

      let blackBishopEval = reverseArray(whiteBishopEval);

      let whiteRookEval = [
        [  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0],
        [  0.5,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  0.5],
        [ -0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -0.5],
        [ -0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -0.5],
        [ -0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -0.5],
        [ -0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -0.5],
        [ -0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -0.5],
        [  0.0,   0.0, 0.0,  0.5,  0.5,  0.0,  0.0,  0.0]
      ];

      let blackRookEval = reverseArray(whiteRookEval);

      let evalQueen = [
        [ -2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0],
        [ -1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -1.0],
        [ -1.0,  0.0,  0.5,  0.5,  0.5,  0.5,  0.0, -1.0],
        [ -0.5,  0.0,  0.5,  0.5,  0.5,  0.5,  0.0, -0.5],
        [  0.0,  0.0,  0.5,  0.5,  0.5,  0.5,  0.0, -0.5],
        [ -1.0,  0.5,  0.5,  0.5,  0.5,  0.5,  0.0, -1.0],
        [ -1.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.0, -1.0],
        [ -2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0]
      ];

      let whiteKingEval = [

        [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0],
        [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0],
        [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0],
        [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0],
        [ -2.0, -3.0, -3.0, -4.0, -4.0, -3.0, -3.0, -2.0],
        [ -1.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -1.0],
        [  2.0,  2.0,  0.0,  0.0,  0.0,  0.0,  2.0,  2.0 ],
        [  2.0,  3.0,  1.0,  0.0,  0.0,  1.0,  3.0,  2.0 ]
      ];

      let blackKingEval = reverseArray(whiteKingEval);


      let getPieceValue = function(piece, x, y) {
        if (piece === null) {
          return 0;
        }

        let absoluteValue = getAbsoluteValue(piece, piece.color === 'w', x , y);

        if (piece.color === 'w'){
          return absoluteValue;
        } else {
          return -absoluteValue;
        }
      };


      let getAbsoluteValue = function(piece, isWhite, x , y) {
        if (piece.type === 'p') {
          return 10 + ( isWhite ? whitePawnEval[y][x] : blackPawnEval[y][x] );
        } else if (piece.type === 'r') {
          return 50 + ( isWhite ? whiteRookEval[y][x] : blackRookEval[y][x] );
        } else if (piece.type === 'n') {
          return 30 + knightEval[y][x];
        } else if (piece.type === 'b') {
          return 30 + ( isWhite ? whiteBishopEval[y][x] : blackBishopEval[y][x] );
        } else if (piece.type === 'q') {
          return 90 + evalQueen[y][x];
        } else if (piece.type === 'k') {
          return 900 + ( isWhite ? whiteKingEval[y][x] : blackKingEval[y][x] );
        }
      };


      let makeAImove = function() {
        let bestMove = calculateBestMove();
        this.game.move(bestMove);
        this.board.position(this.game.fen());
      };


      let onDrop = function(source, target) {
        removeGreySquares();

        // see if the move is legal
        var move = this.game.move({
          from: source,
          to: target,
          promotion: 'q'
        });

        // illegal move
        if (move === null) { return 'snapback'; }

        // make legal move for black AI player
        window.setTimeout(makeAImove, 250);
      };


    var onMouseoverSquare = function(square, piece) {
      // get list of possible moves for this square
      var moves = this.game.moves({
        square: square,
        verbose: true
      });

      // exit if there are no moves available for this square
      if (moves.length === 0) return;

      // highlight the square they moused over
      greySquare(square);

      // highlight the possible squares for this piece
      for (var i = 0; i < moves.length; i++) {
        greySquare(moves[i].to);
      }
    };

      let onMouseoutSquare = function(square, piece) {
        removeGreySquares();
      };


      // update the board position after the piece snap
      // for castling, en passant, pawn promotion
      let onSnapEnd = function() {
        this.board.position(this.game.fen());
      };

     /* var cfg = {
        draggable: true,
        position: 'start',
        onDragStart: onDragStart,
        onDrop: onDrop,
        onMouseoutSquare: onMouseoutSquare,
        onMouseoverSquare: onMouseoverSquare,
        onSnapEnd: onSnapEnd
      };
      board = ChessBoard('board', cfg);*/


///////////////////////////////
      let config = {
      orientation: 'white',
      draggable: true,
      position: 'start',
      moveSpeed: 'fast',
      snapbackSpeed: 100,
      snapSpeed: 100,
      pieceTheme: 'img/chesspieces/wikipedia/{piece}.png',
      showNotation: false,
        onDrop: onDrop,
        onMouseoutSquare: onMouseoutSquare,
        onMouseoverSquare: onMouseoverSquare,
        onSnapEnd: onSnapEnd,
      onDragStart: this.onDragStart.bind( this )
    };


      this.board = new ChessBoard( 'chessboard', config );

      //this.game = new Chess();

      console.log('color of g5: ' + this.game.square_color('g5'));

     //this.board.move('e2-e4');

      this.updateStatus();

  }


  // do not pick up pieces if the game is over
  // only pick up pieces for White
/*
  var onDragStart = (source, piece, position, orientation) => {
    if (this.game.in_checkmate() === true || this.game.in_draw() === true || this.game.game_over() === true ) {
      $('#gameover').show();
      $("#gameover").html('Game over!');
      return false;
    }
  };
*/



  onDragStart(source, piece, position, orientation) {
    if (this.game.in_checkmate() === true || this.game.in_draw() === true || this.game.game_over() === true ) {
      document.getElementById('gameover').style.display="block";
      $('#gameover').html('Game over!');
      return false;
    }
    /*// do not pick up pieces if the game is over
    if (this.game.game_over()) {return false};

    // only pick up pieces for the side to move
    if ((this.game.turn() === 'w' && piece.search(/^b/) !== -1) ||
      (this.game.turn() === 'b' && piece.search(/^w/) !== -1)) {
      return false
    };

    return true;*/
  }


  updateStatus() {
    let status = '';

    let moveColor = 'White';
    if (this.game.turn() === 'b') {
      moveColor = 'Black';
    }

    // checkmate?
    if (this.game.in_checkmate()) {
      status = 'Game over, ' + moveColor + ' is in checkmate.';
    }

    // draw?
    else if (this.game.in_draw()) {
      status = 'Game over, drawn position';
    }

    // game still on
    else {
      status = moveColor + ' to move';

      // check?
      if (this.game.in_check()) {
        status += ', ' + moveColor + ' is in check';
      }
    }

    console.log(status);
  }




/*
 dropOffBoard: 'snapback', // this is the default
      position: 'start'
* */
}
<div class=" alert alerta-game alert-warning alert-dismissible fade show" role="alert" >

  <p>
    <strong>Attention: </strong>this game is in development.
  </p>
</div>



<div class="menu" id="difficulty">
  <br>
  <h1>Select Difficulty:</h1>
  <hr><br>
  <button type="button" class="btn easy btn-success btn-xlarge">Easy</button>
  <br><br>
  <button type="button" class="btn medium btn-warning btn-xlarge">Medium</button>
  <br><br>
  <button type="button" class="btn hard btn-danger btn-xlarge">Hard</button>
</div>

<div id="chessboard" role="main"style="margin:0px auto; max-width: 600px;"></div>

<div id="gameover" class="alert alert-primary hide" role="alert"><strong></strong></div>
<div id="restart" class="restartGame">
  <button type="button" class="btn medium btn-danger btn-xlarge">Restart</button>
</div>

您似乎只是在组件中复制粘贴了一个 Javascript 文件……好吧……这根本行不通。

  1. 尽量避免“getElementById”,这些是 Vanilla JS,而你可以使用 Reactive Form(Angular 方式)

  2. 您正在将“点击”事件作为普通 JS 处理,您应该使用 Angular 方法,通过附加到元素的方法,该方法在用户执行“点击”时执行视图。

  3. 你的“onDrag”和“orDrop”等也会发生同样的情况

  4. 不要使用匿名函数而是使用胖箭头“=>”,它避免了绑定 this 的需要(大多数时候)。

TLTR;如果你只是将它的代码放在 ngOnInit 方法中,Vanilla JS 将无法工作。你需要调整代码,主要是关于事件控制和视图重绘的逻辑。似乎您正在尝试 port/wrap 一个主要是事件控制和视图渲染的 JS 库....(除了 2-3 种 AI 方法)所以这并不容易。