You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过XMLHttpRequest实现同棋盘尺寸的游戏玩家匹配?

解决方案:基于XMLHttpRequest实现同尺寸棋盘玩家匹配与游戏同步

一、先修正join方法的异步问题

你当前的join用了同步请求(xhr.open第三个参数为false),会阻塞浏览器线程,建议改成异步,并补充请求头和错误处理:

// 全局存储当前游戏ID,供后续操作使用
let currentGameId = null;
let pollInterval = null;

function join(size) {
    const joinData = {
        'group': user.group,
        'nick': user.username,
        'password': user.password,
        'size': size
    };
    
    const xhr = new XMLHttpRequest();
    console.log("JOIN");

    xhr.open("POST", url + '/join', true);
    // 必须设置请求头,确保服务器能解析JSON格式的请求体
    xhr.setRequestHeader('Content-Type', 'application/json');

    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                console.log("JOIN OK");
                const response = JSON.parse(xhr.responseText);
                currentGameId = response.gameId;
                // 拿到gameId后启动后续匹配监听流程
                startGamePolling(currentGameId);
            } else {
                console.error("JOIN FAILED", xhr.statusText);
                // 给用户显示错误提示,比如"加入游戏失败,请重试"
                showGameError('加入游戏失败,请检查输入或重试');
            }
        }
    };

    xhr.send(JSON.stringify(joinData));
}

二、轮询监听游戏匹配状态

拿到gameId后,需要定期向服务器查询游戏是否已凑齐2名玩家,这是XMLHttpRequest下实现"等待匹配"的核心方式:

function startGamePolling(gameId) {
    // 显示等待界面,比如"正在寻找同尺寸的玩家..."
    showWaitingUI();
    // 每秒查询一次游戏状态
    pollInterval = setInterval(() => {
        checkGameStatus(gameId);
    }, 1000);
}

function checkGameStatus(gameId) {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url + `/game/status/${gameId}`, true);
    
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            const gameStatus = JSON.parse(xhr.responseText);
            // 检查是否已有2名玩家加入
            if (gameStatus.players.length === 2) {
                // 匹配成功,停止轮询,初始化游戏棋盘
                clearInterval(pollInterval);
                initGameBoard(gameStatus);
            } else {
                // 继续等待,可更新UI提示"等待另一名玩家加入..."
                updateWaitingText();
            }
        } else if (xhr.readyState === 4 && xhr.status !== 200) {
            // 请求失败,停止轮询并提示
            clearInterval(pollInterval);
            showGameError('获取游戏状态失败,请重新加入');
        }
    };
    
    xhr.send();
}

三、游戏内操作同步

当两名玩家都进入游戏后,所有棋盘操作(比如落子)都需要通过gameId同步到服务器,同时继续轮询获取最新状态更新UI:

// 玩家落子时调用
function makeMove(position) {
    if (!currentGameId) return;
    
    const moveData = {
        gameId: currentGameId,
        playerNick: user.username,
        position: position // 比如{x: 2, y: 3}
    };
    
    const xhr = new XMLHttpRequest();
    xhr.open("POST", url + '/game/move', true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            // 落子成功,立即刷新游戏状态
            checkGameStatus(currentGameId);
        } else if (xhr.readyState === 4) {
            showGameError('落子失败,请重试');
        }
    };
    
    xhr.send(JSON.stringify(moveData));
}

// 初始化游戏棋盘,渲染状态
function initGameBoard(gameStatus) {
    // 隐藏等待界面,显示棋盘
    hideWaitingUI();
    // 根据gameStatus渲染初始棋盘、玩家信息等
    renderBoard(gameStatus.board);
    renderPlayerInfo(gameStatus.players);
}

四、清理与异常处理

在游戏结束、玩家退出或发生错误时,需要清理定时器,避免无效请求:

// 退出游戏时调用
function exitGame() {
    if (pollInterval) {
        clearInterval(pollInterval);
        pollInterval = null;
    }
    currentGameId = null;
    // 重置UI到初始状态
    resetGameUI();
}

内容的提问来源于stack exchange,提问作者miguelcgo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:50:21