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;
解决方案
核心问题分析
- 重复绑定事件监听器:在while循环内每次执行都会添加新的
keydown监听,导致同一按键触发多次方向修改,甚至逻辑混乱。 - 废弃API使用:
keyCode已被标准废弃,建议使用更直观的event.key(直接判断按键字符如'w'/'a'/'s'/'d')。 - 无反向移动限制:当前逻辑允许蛇直接反向移动(比如向右走时直接按左),容易导致蛇撞自己,不符合贪吃蛇常规规则。
- splice方法调用错误:原代码中
list.splice(list[indOf])参数错误,splice第一个参数应为索引,而非元素值。
修改步骤及代码示例
- 将
keydown事件监听器移到while循环外部,只绑定一次。 - 替换
keyCode为event.key,提升代码可读性。 - 添加反向移动限制,避免蛇直接掉头。
- 修正
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
相关产品推荐
相关产品推荐

