
在基于 Socket.io 构建的在线国际象棋游戏中,玩家的每一步操作都需要经过客户端验证、服务器同步,并最终反馈给所有参与者。onDrop 函数是处理棋子落子的核心逻辑,它承担了多项关键任务:
以下是 onDrop 函数的简化流程和相关辅助函数:
// on dropping piece
function onDrop(source, target) {
// ... (玩家身份、回合验证、移除灰色方块等初始化逻辑) ...
// 假设currentPlayerColor 已正确确定为 "white" 或 "black"
let isPlayerTurn = (engine.getSide() === (currentPlayerColor === "white" ? 0 : 1));
if (!isPlayerTurn) {
return; // 不是当前玩家的回合
}
removeGreySquares(); // 移除棋盘上的辅助标记
// 尝试构建并验证移动
let promotedPiece = (engine.getSide() ? (5 + 6) : 5); // 简化:只考虑后兵升变
let move = source + target + engine.promotedToString(promotedPiece);
let validMove = engine.moveFromString(move);
if (validMove == 0) return 'snapback'; // 非法移动,棋子弹回
// 进一步检查移动是否在引擎生成的合法移动列表中
let legalMoves = engine.generateLegalMoves();
let isLegal = 0;
for (let count = 0; count < legalMoves.length; count++) {
if (validMove == legalMoves[count].move) isLegal = 1;
}
if (isLegal == 0) {
return 'snapback'; // 非法移动
}
// 执行合法移动
engine.makeMove(validMove);
engine.printBoard();
playSound('move.wav'); // 播放移动音效
let fen = engine.generateFen(); // 生成当前棋盘的FEN字符串
socket.emit('makeMove', { source, target, fen }); // 通知服务器棋子移动
// --- 将军检测的核心逻辑 ---
// ... (此处是问题所在,将在下一节详细讨论) ...
console.log(engine.generateFen());
$fen.html(engine.generateFen()); // 更新FEN显示
}
// 发送将军事件到服务器
function sendCheck(message, checkCoord) {
socket.emit('check', { message: message, checkCoord: checkCoord });
}
// 播放音效
function playSound(soundFile) {
var audio = new Audio('./Sounds/' + soundFile);
audio.play();
}
// 监听服务器发来的将军控制事件
socket.on('checkControl', (data) => {
console.log(data.message);
redSquare(data.checkCoord); // 标记被将军的王
});在上述 onDrop 函数中,将军检测是至关重要的一环。最初的实现中,开发者面临一个问题:当棋子落下后,尽管服务器端的 io.emit 逻辑正确,但前端的 sendCheck 函数却未能触发预期的将军通知。经过排查,发现问题出在将军检测的逻辑上。
问题根源: 在玩家完成一步移动后,engine.inCheck() 函数被调用以判断是否有王被将军。然而,关键在于 engine.inCheck() 需要一个参数来指定要检查哪一方的王。原始代码如下:
let checkControl = localStorage.getItem('playerColor') === "white" ? 0 : 1;
if(engine.inCheck(checkControl)){
// ... 找到王的位置并发送将军事件 ...
}这里 checkControl 的值是根据当前玩家的颜色来设定的。例如,如果当前玩家是白色,checkControl 就是 0。这意味着在白色玩家移动后,代码会检查白色方的王是否被将军。这显然是错误的,因为一个玩家不可能在自己的回合结束时将军自己的王。我们真正需要检查的是对手的王是否被将军。
解决方案: 为了正确检测将军状态,checkControl 变量应该代表对手的颜色。因此,我们需要反转 checkControl 的逻辑:如果当前玩家是白色,那么我们需要检查黑色方的王;如果当前玩家是黑色,则检查白色方的王。
修正后的代码如下:
// 修正前的代码:
// let checkControl = localStorage.getItem('playerColor') === "white" ? 0 : 1;
// 修正后的代码:检查对手的王是否被将军
let checkControl = localStorage.getItem('playerColor') === "white" ? 1 : 0; // 如果当前玩家是白(0),则检查黑(1);反之亦然。
if (engine.inCheck(checkControl)) { // 检查对手的王是否被将军
// 遍历棋盘上的棋子,找到被将军的王的位置
// 注意:moves 变量可能需要根据具体棋盘库的API进行调整
for (var key in moves) {
if (moves.hasOwnProperty(key)) {
// 假设 moves[key] 存储了棋子的类型,key 存储了棋子的坐标
if (moves[key] === "wK" && checkControl === 0) { // 白王被将军 (checkControl为0表示检查白方)
console.log("白王被将军! 位置: " + key);
redSquare(key); // 标记王的位置为红色
sendCheck('whitecheck', key); // 发送将军事件给服务器
} else if (moves[key] === "bK" && checkControl === 1) { // 黑王被将军 (checkControl为1表示检查黑方)
console.log("黑王被将军! 位置: " + key);
redSquare(key); // 标记王的位置为红色
sendCheck('blackcheck', key); // 发送将军事件给服务器
}
}
}
}通过这一简单的逻辑反转,engine.inCheck() 现在能够正确地判断对手的王是否处于将军状态,从而触发 sendCheck 函数,将将军信息发送到后端。
当客户端通过 sendCheck 函数发射 'check' 事件到服务器后,服务器端会监听此事件并进行处理。
服务器端处理 (socket.on('check', ...)): 服务器接收到将军事件后,其主要职责是将此信息广播给房间内的所有其他客户端。
socket.on('check', (data) => {
// 将将军信息广播给房间内的所有用户
io.to(user.room).emit('checkControl', { message: data.message, checkCoord: data.checkCoord });
console.log(data.message, data.checkCoord);
});io.to(user.room).emit('checkControl', ...) 确保了房间内的所有客户端都会收到 'checkControl' 事件,其中包含了将军消息和被将军王的坐标。
客户端接收与反馈 (socket.on('checkControl', ...)): 所有客户端(包括发起将军的客户端和被将军的客户端)都会监听 'checkControl' 事件。一旦收到此事件,客户端就会调用 redSquare 函数,将被将军王的棋盘格高亮显示为红色,从而提供即时的视觉反馈。
socket.on('checkControl', (data) => {
console.log(data.message);
redSquare(data.checkCoord); // 在客户端棋盘上将指定坐标的格子标记为红色
});通过上述修正,整个将军检测和同步机制得以完善。这个案例强调了在开发实时游戏时,以下几点至关重要:
正确实现将军检测是任何国际象棋游戏的基础。通过仔细分析逻辑并确保 engine.inCheck() 等核心函数的参数正确,可以避免这类常见的开发陷阱,从而构建出更健壮、更准确的实时游戏应用。
以上就是Socket.io 实时国际象棋对弈中的将军检测与同步机制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号