是什么导致此事件处理程序保持 运行?为什么当我尝试添加条件时它会停止?

What causes this event handler to keep running?, and why does it halt when I try to add a condition?

我在做国际象棋开局训练器。我有一个基于示例使用 cm-chessboard 的工作游戏,我正在使用 API 来获取计算机的动作。我已经压缩了我的代码并删除了这个 API 以便它更容易阅读。在此版本中,计算机从所有有效的国际象棋走法中随机走法。

这个想法是,API 获得最佳着法,然后玩家尝试通过移动棋子来输入该着法。如果玩家猜对了,计算机会为他们下一步走棋,但如果玩家猜错了最佳棋步,他们会被告知 'Incorrect!' 并且可以重试。

但是,我的代码在正确时工作正常,但在不正确时中断。

这是我所做的:

<!-- Condensed Version -->     

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Chess Opening Trainer</title>
    <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"/>
    <link rel="stylesheet" href="https://alftheelf.github.io/Chess-Trainer/cm-chessboard/styles/cm-chessboard.css"/> 
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500&display=swap" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.2/chess.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

</head>
<body>

<div class="board" id="board" style="width: 800px; max-width: 800px;"></div>

<script type="text/javascript">

function getBestMove(fen){
    //This function has been simplified
    var bestMove = "e5"
    return bestMove
}

</script>

<script type="module">

    var DATA;

    var side = 'black' //select which side to play as


    
    import {INPUT_EVENT_TYPE, COLOR, Chessboard, MARKER_TYPE} from "https://alftheelf.github.io/Chess-Trainer/cm-chessboard/src/cm-chessboard/Chessboard.js"
    import {BORDER_TYPE} from "https://alftheelf.github.io/Chess-Trainer/cm-chessboard/src/cm-chessboard/Chessboard.js"


    const chess = new Chess() //Creates a new Chess() object. Add a FEN string as an argument to start from a paticular FEN.

    function inputHandler(event) {
        console.log("event", event)
        event.chessboard.removeMarkers(undefined, MARKER_TYPE.dot)


        //Before move. Clicking about, and showing dot for possible moves and such.
        if (event.type === INPUT_EVENT_TYPE.moveStart) {
            const moves = chess.moves({square: event.square, verbose: true});
            for (const move of moves) {
                event.chessboard.addMarker(move.to, MARKER_TYPE.dot)
            }
            return moves.length > 0

        //Here is once a move has been attempted    
        } else if (event.type === INPUT_EVENT_TYPE.moveDone) {
            const move = {from: event.squareFrom, to: event.squareTo} //gets which move was attempted from event
            const result = chess.move(move) //gets result of move

            var correctAnswer = getBestMove(chess.fen());

            if (result.san == correctAnswer){console.log('correct!')}else{console.log('Incorrect!')}

            //Makes moves for the player
            if (result && result.san == correctAnswer) {

                event.chessboard.disableMoveInput()
                event.chessboard.setPosition(chess.fen())

                //Makes moves for the computer
                const possibleMoves = chess.moves({verbose: true})
                if (possibleMoves.length > 0) {
                    const randomIndex = Math.floor(Math.random() * possibleMoves.length)
                    const randomMove = possibleMoves[randomIndex]
                    setTimeout(() => { // smoother with 500ms delay
                        chess.move({from: randomMove.from, to: randomMove.to})
                        if(side === 'white') {
                            event.chessboard.enableMoveInput(inputHandler, COLOR.white)
                        }
                        else {
                            event.chessboard.enableMoveInput(inputHandler, COLOR.black)
                        }
                        event.chessboard.setPosition(chess.fen())
                    }, 500)
                }
            } else { //If result returns null, then we will loop back to the begining of the function to have another go.
                console.warn("invalid move", move)
            }
            return result
        }
    }


    if (side == 'white'){
        const board = new Chessboard(document.getElementById("board"), {
            position: chess.fen(),
            sprite: {url: "https://alftheelf.github.io/Chess-Trainer/cm-chessboard/assets/images/chessboard-sprite-staunty.svg"},
            style: {moveMarker: MARKER_TYPE.square, hoverMarker: undefined},
            orientation: COLOR.white
        })
        board.enableMoveInput(inputHandler, COLOR.white)
    }
    else{
        const board = new Chessboard(document.getElementById("board"), {
            position: chess.fen(),
            sprite: {url: "https://alftheelf.github.io/Chess-Trainer/cm-chessboard/assets/images/chessboard-sprite-staunty.svg"},
            style: {moveMarker: MARKER_TYPE.square, hoverMarker: undefined},
            orientation: COLOR.black
        })


        const possibleMoves = chess.moves({verbose: true})
        if (possibleMoves.length > 0) {
            const randomIndex = Math.floor(Math.random() * possibleMoves.length)
            const randomMove = possibleMoves[randomIndex]
            setTimeout(() => { // smoother with 500ms delay
                chess.move({from: randomMove.from, to: randomMove.to});                
                board.enableMoveInput(inputHandler, COLOR.black)
                board.setPosition(chess.fen())

            }, 500)
        }

    }

</script>
</body>
</html>

我做了一个简单的函数,getBestMove(fen) 来替换 API 为获得下一个最佳着法而做的事情。在这种情况下,我希望第一个动作是“pawn e5”,之后所有动作都将不正确,但它应该允许我继续尝试找到正确的动作而不是停止。

我不确定我是否理解这个事件循环是如何重复的。起初我以为函数是用行 event.chessboard.enableMoveInput(inputHandler, COLOR.black) 调用的,但过了一会儿我意识到即使 result == null 它仍然循环,所以我很困惑。

我在 Github 上有实时版本,您可以查看它是否工作(或不工作):

这几天我试了很多方法。我想我错过了一些东西,因为这是我做过的最先进的 Javascript 项目(不过我学到了很多东西)。

我尝试过使用浏览器进行调试,但它非常混乱,我无法通过这种方式解决任何问题。

我需要做什么才能让它正常工作?原始版本中究竟是什么再次调用该函数以便玩家可以下另一个动作,但在编辑版本中不允许这样做?没看懂。

我试了一下,我能够使用它来让它工作。这是您代码的第 90 行左右。它使用您的代码来检查移动是否不正确并重置它直到您执行正确的移动

    else { //If result returns null, then we will loop back to the 
    //begining of the function to have another go.
        chess.undo();
        event.chessboard.setPosition(chess.fen());
         }