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

JavaScript按键检测失效求助——贪吃蛇游戏开发遇阻

问题描述

已查阅多种解决方案但均无效,目前正在开发一款贪吃蛇游戏,需要实现用户按键检测功能。将按键检测逻辑放在while循环内,也尝试过移到函数外部,但仍无法实现按键检测,希望按下按键时蛇能改变移动方向,求帮助。

while(running) {

    // 以下是我写的按键检测逻辑
    document.addEventListener("keydown", (event) => {
        if(event.keyCode == 68) {
            right = true
            up = false
            down = false
            left = false
        }
        if(event.keyCode == 83) {
            right = false
            up = false
            down = true
            left = false
        }
        if(event.keyCode == 65) {
            right = false
            up = false
            down = false
            left = true
        }
        if(event.keyCode == 87) {
            right = false
            up = true
            down = false
            left = false
        }
    })
    // 按键检测逻辑结束,下面是游戏主体代码,可能也需要修改

    if(endMap.includes(pushing) && running) {
        reset();
        running = false;
        document.getElementById("tabelle").innerHTML = "";
        begin();
    }
    if(right && running) {
        if(snakeLength < snakeLengthMax) {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
        } else {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
            document.getElementById(pushing-snakeLength).innerHTML = ""
            snakeLength --;
        }
        pushing ++;
    }
    if(left && running) {
        if(snakeLength < snakeLengthMax) {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
        } else {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
            document.getElementById(pushing-snakeLength).innerHTML = ""
            snakeLength --;

        }
        pushing --;
    }
    if(down && running) {
        if(snakeLength < snakeLengthMax) {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
        } else {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
            document.getElementById(pushing-snakeLength).innerHTML = ""
            snakeLength --;

        }
        pushing -= 21;
    }
    if(up && running) {
        if(snakeLength < snakeLengthMax) {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
        } else {
            list.push(pushing);
            indOf = list.indexOf(pushing)
            indOf --;
            list.splice(list[indOf])
            document.getElementById(pushing-snakeLength).innerHTML = ""
            snakeLength --;

        }
        pushing += 21;
    }
    document.getElementById(pushing).innerHTML = "█"
    snakeLength ++;
    await sleep(1000)

}
running = true;
解决方案

核心问题分析

  1. 重复绑定事件监听器:在while循环内每次执行都会添加新的keydown监听,导致同一按键触发多次方向修改,甚至逻辑混乱。
  2. 废弃API使用:keyCode已被标准废弃,建议使用更直观的event.key(直接判断按键字符如'w'/'a'/'s'/'d')。
  3. 无反向移动限制:当前逻辑允许蛇直接反向移动(比如向右走时直接按左),容易导致蛇撞自己,不符合贪吃蛇常规规则。
  4. splice方法调用错误:原代码中list.splice(list[indOf])参数错误,splice第一个参数应为索引,而非元素值。

修改步骤及代码示例

  1. 将keydown事件监听器移到while循环外部,只绑定一次。
  2. 替换keyCode为event.key,提升代码可读性。
  3. 添加反向移动限制,避免蛇直接掉头。
  4. 修正splice方法调用错误,提取蛇身更新逻辑为单独函数简化代码。

修改后的完整代码示例:

// 初始化方向变量,可根据需求调整初始方向
let right = false, up = false, down = false, left = true;
let running = true;

// 按键监听放在循环外,只绑定一次
document.addEventListener("keydown", (event) => {
    // 禁止反向移动:比如当前向右时,不能直接切换向左
    switch(event.key.toLowerCase()) {
        case 'd':
            if(!left) {
                right = true;
                up = false;
                down = false;
                left = false;
            }
            break;
        case 's':
            if(!up) {
                right = false;
                up = false;
                down = true;
                left = false;
            }
            break;
        case 'a':
            if(!right) {
                right = false;
                up = false;
                down = false;
                left = true;
            }
            break;
        case 'w':
            if(!down) {
                right = false;
                up = true;
                down = false;
                left = false;
            }
            break;
    }
});

// 游戏主循环
async function gameLoop() {
    while(running) {
        if(endMap.includes(pushing) && running) {
            reset();
            running = false;
            document.getElementById("tabelle").innerHTML = "";
            begin();
        }
        if(right && running) {
            updateSnakePosition(1); // 向右移动+1
        }
        if(left && running) {
            updateSnakePosition(-1); // 向左移动-1
        }
        if(down && running) {
            updateSnakePosition(-21); // 向下移动-21(假设每行21个格子)
        }
        if(up && running) {
            updateSnakePosition(21); // 向上移动+21
        }
        document.getElementById(pushing).innerHTML = "█";
        snakeLength++;
        await sleep(1000);
    }
    running = true;
}

// 提取蛇身更新逻辑为单独函数,简化代码并修正splice错误
function updateSnakePosition(offset) {
    if(snakeLength < snakeLengthMax) {
        list.push(pushing);
        const indOf = list.indexOf(pushing) - 1;
        list.splice(indOf, 1); // 从索引indOf处删除1个元素
    } else {
        list.push(pushing);
        const indOf = list.indexOf(pushing) - 1;
        list.splice(indOf, 1);
        document.getElementById(pushing - snakeLength).innerHTML = "";
        snakeLength--;
    }
    pushing += offset;
}

// 启动游戏
gameLoop();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:20:50