问题描述
我正在制作国际象棋开局训练师。我有一个基于示例的使用 cm-chessboard 的工作游戏,我正在使用 API 来获取计算机的动作。我已经压缩了我的代码并删除了这个 API 以便于阅读。在这个版本中,计算机从所有有效的国际象棋移动中随机移动。
这个想法是,API 获取最佳移动,然后玩家尝试通过移动一个棋子来输入该移动。如果玩家是正确的,计算机会为他们的下一次移动而移动,但如果玩家错误地猜测了最佳移动,他们会被告知“不正确!”并且可以再试一次。
这是我所做的:
<!-- 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"),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 上有实时版本,您可以查看它是否有效(或无效):
- 没有
getBestMove()
的原始版本(有效):https://alftheelf.github.io/Chess-Trainer/original.html - 如果移动不正确则停止的编辑版本(不起作用):https://alftheelf.github.io/Chess-Trainer/edited
过去几天我尝试了很多方法。我想我错过了一些东西,因为这是我做过的最先进的 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());
}