如何让这两个事件处理程序协同工作?

如何解决如何让这两个事件处理程序协同工作?

我正在使用 cm-chessboardchess.js 创建国际象棋开局训练器。这个想法是从 Lichess opening Explorer API 中提取连续的国际象棋位置,玩家通过移动下一个最佳移动和/或回答关于开局名称的问题来测试自己。

但是,我有点不适应。

目前,它只在计算机轮到用户提问。我想不出办法让它等待用户按下返回键,然后才显示有关玩家移动的答案。

这是我的代码

<!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-opening-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>

    <style type="text/css">

        body{font-family: 'Montserrat',sans-serif;}

        .grid-container {
        display: grid;
        grid-template-columns: 1fr 0.6fr;
        grid-template-rows: 1fr;
        gap: 0px 0px;
        }

        .board {
            grid-area: 1 / 1 / 2 / 3;
            width: 800px;
            max-width: 800px;
        }
        #interface { 
            grid-area: 1 / 2 / 2 / 3; 
            border-style: solid;
            border-width: thin;
            width: 400px;
            max-width: 400px;
        }

        p{
            width: 100%;
            align: center;
        }

    </style>
</head>
<body>


<div class="grid-container">
  <div class="board" id="board"></div>
  <div id="interface">
      <span id="prompt"></span>
  </div>
</div>


<script type="text/javascript">


//SETTINGS

var side = 'black' //select which side to play as
var rating = '1600';
var realistic = true;
var limit = 50;


//Define initial variables

var state = null;
var moveCount = 0;
if (side == 'black') {var notSide = 'white'} else{var notSide = 'black'}
var positionAnswer
var bestMove
var opponentMove
var PGN


//define functions

var addEvent = document.addEventListener ? function(target,type,action){
    if(target){
        target.addEventListener(type,action,false);
    }
} : function(target,action){
    if(target){
        target.attachEvent('on' + type,false);
    }
}

addEvent(document,'keydown',function(e){
    e = e || window.event;
    var key = e.which || e.keyCode;
    if(key===13){ //Press the return key
        keypress()
    }
});

function keypress(){
    if (state == 'questionPosition') { //Then reveal the answer

        document.getElementById("prompt").innerHTML = positionAnswer;

        setTimeout(() => {
            document.getElementById("prompt").innerHTML = positionAnswer + "<br><br>key) What is " + side + "\'s best move?"
            state = "questionBestMove";
        },500)
    }
}


</script>

<script type="module">
    
    import {INPUT_EVENT_TYPE,COLOR,Chessboard,MARKER_TYPE} from "https://alftheelf.github.io/Chess-opening-Trainer/cm-chessboard/src/cm-chessboard/Chessboard.js"
    import {BORDER_TYPE} from "https://alftheelf.github.io/Chess-opening-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 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) {

            if (state == "questionBestMove") {

                const move = {from: event.squareFrom,to: event.squareto} //gets which move was attempted from event
                const result = chess.move(move) //gets result of move

                bestMove = PGN[moveCount];

                if (result){
                    if (result.san == bestMove.san) {

                        moveCount += 1;

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

                        document.getElementById("prompt").innerHTML = "";

                        //Here is where I need it to ask a question if the bestMove.name is not null.

                        opponentMove = PGN[moveCount];
                        positionAnswer = PGN[moveCount].name;
                        moveCount += 1;

                        setTimeout(() => { // smoother with 500ms delay
                            chess.move({from: opponentMove.uci.slice(0,2),to: opponentMove.uci.slice(2,4)})
                            event.chessboard.enableMoveInput(inputHandler,side[0])
                            event.chessboard.setPosition(chess.fen())

                            if (positionAnswer){
                                document.getElementById("prompt").innerHTML = "event) What position is this?";
                                state = 'questionPosition';
                            }else{
                                document.getElementById("prompt").innerHTML = "key) What is " + side + "\'s best move?"
                            }

                        },500)

                    }else{
                        console.warn("That move is not the answer")
                        chess.undo();
                        event.chessboard.setPosition(chess.fen());
                    }
                    return result
                

                } else { //If result returns null,then we will loop back to the begining of the function to have another go with new dots.
                    console.warn("invalid move",move)
                }
                return result
            }
        }
    }

    // The PGN is inputted manually here. normally this would be extracted from the Lichess API.
    if (side == 'black') {
    
        PGN = [
            {uci: "e2e4",san: "e4",name: "King's Pawn"},{uci: "e7e5",san: "e5",name: "King's Pawn Game"},{uci: "g1f3",san: "Nf3",name: "King's Knight opening"},{uci: "b8c6",san: "Nc6",name: "King's Knight opening: normal Variation"},{uci: "f1b5",san: "Bb5",name: "Ruy Lopez"},{uci: "a7a6",san: "a6",name: "Ruy Lopez: Morphy Defense"},{uci: "b5c6",san: "Bxc6",name: "Ruy Lopez: Exchange Variation"},{uci: "d7c6",san: "dxc6",name: null},{uci: "b1c3",san: "Nc3",name: "Ruy Lopez: Exchange Variation,Keres Variation"},{uci: "f7f6",san: "f6",{uci: "e1g1",san: "O-O",name: null}
        ]
    }else{

        PGN = [
            {uci: "e2e4",{uci: "b5a4",san: "Ba4",{uci: "b7b5",san: "b5",name: "Ruy Lopez: Morphy Defense,Caro Variation"},{uci: "a4b3",san: "Bb3",{uci: "g8f6",san: "Nf6",name: null}
        ]
    }

    console.log('PGN',PGN)

    if (side == 'white'){
        const board = new Chessboard(document.getElementById("board"),{
            position: chess.fen(),sprite: {url: "https://alftheelf.github.io/Chess-opening-Trainer/cm-chessboard/assets/images/chessboard-sprite-staunty.svg"},style: {moveMarker: MARKER_TYPE.square,hoverMarker: undefined},orientation: COLOR.white
        })
        state = 'questionBestMove';
        document.getElementById("prompt").innerHTML = "What is " + side + "\'s best move?";
        board.enableMoveInput(inputHandler,COLOR.white)
    }
    else{
        const board = new Chessboard(document.getElementById("board"),orientation: COLOR.black
        })


        //Get opponent move and name
        var opponentMove = PGN[moveCount];
        positionAnswer = PGN[moveCount].name;

        moveCount += 1;

        setTimeout(() => { // smoother with 500ms delay
            chess.move({from: opponentMove.uci.slice(0,4)})
            board.enableMoveInput(inputHandler,COLOR.black)
            board.setPosition(chess.fen())
            
            if (positionAnswer){
            
                document.getElementById("prompt").innerHTML = "What position is this?";
                state = "questionPosition"
            }

        },500)

    }

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

我已经为这篇文章浓缩了它。通常,变量 PNG 是使用 Lichess API 创建的,但在本示例中,我改为手动定义了两种游戏,一种用于黑色,一种用于白色。我选择了中间带有一些“空”名称的示例,以便我可以测试它是否正常工作。

如您所见,我让对手位置问题等待,因为它在 keypress() 函数中。我在对球员位置问题做同样的事情时遇到的问题是,一旦问题被揭示,计算机需要自动移动。我尝试从 keypress() 函数内部进行移动,但我无法使其工作,因为 event 未定义。我以某种方式尝试将 event 传递给 keypress,但没有奏效,而且我确信这无论如何都不是最好的方法

我认为正确的方法是正确组织 inputHandler。我已经重写了很多次,但我从来没有设法让它工作。这个逻辑让我很困惑,我认为使用我的 state = "questionPosition" 想法来分离游戏状态可能会导致比它解决的问题更多的问题。如果我在 r/badcode 上看到它,我不会感到惊讶。 ?

我非常感谢有关如何解决此问题的任何建议。

我发布的这个版本是一个几乎可以运行的版本,我认为与我遵循的一些版本相比,它会更容易看出发生了什么。

我还在 https://alftheelf.github.io/Chess-Opening-Trainer/ 发布了实时版本。

有谁知道我该如何解决这个问题?我花了一个星期试图修复它,但我不知道了。

解决方法

我终于成功了。

我最终将 event 中的 inputHander 重命名为 chessEvent,使其与 event 中的 keypress() 分开。然后我克隆了 chessEvent 并在按键功能中使用了它。 chess 还必须与 inputHandler 一起成为全局变量,这是我通过将其设为变量来实现的。

inputHandler1 = function inputHandler(chessEvent) {...

现在我可以从 keypress() 内控制板子,它运行良好。 ?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?