JS实现Canvas贪吃蛇 方向控制与蛇身绘制问题修复
贪吃蛇代码Bug修复方案
问题根因汇总
蛇身绘制不符合预期(要求3方块宽度)
- 遍历蛇身的for循环存在语法错误:一是数组长度属性拼写错误,把
length写成了lenght;二是for循环括号后多写了一个分号,导致循环体和遍历逻辑脱钩,根本不会逐块绘制整个蛇身 - 初始化蛇身时传入的数组长度为5,要满足3方块宽度的要求,初始化body参数改为3个坐标元素即可
蛇无法响应方向键移动
- 键盘事件绑定方式错误:
addEventListener是DOM方法,不能直接给它赋值函数来绑定事件,必须传入事件名和回调函数作为参数才能生效 - 作用域错误:原代码把键盘回调函数写在
window.onload代码块外面,无法访问onload内部定义的snakee实例,调用转向方法时会直接报变量未定义错误 - 方向键键值映射完全写反:上箭头(keyCode 38)、右箭头(keyCode 39)对应的方向赋值错误,按键后触发的方向完全不对
- 移动逻辑存在拼写错误:向左移动的分支里把
nextPosition拼成了nexPosition,触发引用错误直接中断移动逻辑 - 上下移动的坐标逻辑写反:Canvas坐标系中y轴向下为正方向,向下移动时y坐标应该+1、向上移动时y坐标应该-1,原代码逻辑完全颠倒
- 方向校验存在拼写错误:允许转向的方向列表里把
down拼成了donw,导致水平移动时无法切换到向下方向 - 构造函数冗余问题:定义Snake时传入了
_direction参数但未使用,直接硬编码初始方向为right,不影响运行但属于无效参数
修复后完整代码
window.onload = function() { var canvasWidth = 900; var canvasHeight = 600; var blockSize = 30; var ctx; var delay = 100; var snakee; init(); function init() { var canvas = document.createElement('canvas') canvas.width = canvasWidth; canvas.height = canvasHeight; canvas.style.border = "1px solid" document.body.appendChild(canvas); ctx = canvas.getContext('2d'); // 初始化蛇身改为3个方块,满足宽度要求 snakee = new Snake([[6,4],[5,4],[4,4]], "right"); // 正确绑定键盘事件 document.addEventListener('keydown', handleKeyDown); refreshCanvas(); } function refreshCanvas() { ctx.clearRect (0,0,canvasWidth, canvasHeight); snakee.draw(); snakee.advance(); setTimeout(refreshCanvas, delay); } function drawBlock(ctx, position) { var x = position[0] * blockSize; var y = position[1] * blockSize; ctx.fillRect(x ,y , blockSize , blockSize ); } function Snake(body, direction) { this.body = body; // 使用传入的初始方向参数,而非硬编码 this.direction = direction; this.draw = function () { ctx.save(); ctx.fillStyle = "#ff0000"; // 修正length拼写错误,去掉for循环后多余的分号 for(var i = 0; i < this.body.length; i++) { drawBlock(ctx, this.body[i]); } ctx.restore(); }; this.advance = function() { var nextPosition = this.body[0].slice(); switch(this.direction) { case "left": // 修正变量拼写错误 nextPosition[0] -= 1; break; case "right": nextPosition[0] += 1; break; case "down": // 修正上下移动坐标逻辑,down对应y+1 nextPosition[1] += 1; break; case "up": // 修正up对应y-1 nextPosition[1] -= 1; break; default: throw("Invalid Direction"); } this.body.unshift(nextPosition); this.body.pop(); }; this.setDirection = function(newDirection) { var allowedDirections; switch(this.direction) { case "left": case "right": // 修正down拼写错误 allowedDirections = ["up", "down"]; break; case "down": case "up": allowedDirections = ["left","right"] break; default: throw("Invalid Direction"); } if(allowedDirections.indexOf(newDirection) > -1 ) { this.direction = newDirection; } }; } function handleKeyDown(e) { const key = e.keyCode; var newDirection; switch(key) { case 37: newDirection = "left"; break; case 38: // 修正上箭头对应up方向 newDirection = "up"; break; case 39: // 修正右箭头对应right方向 newDirection = "right"; break; case 40: // 修正下箭头对应down方向 newDirection = "down"; break; default: return; } snakee.setDirection(newDirection); } }
内容的提问来源于stack exchange,提问作者Joefab
相关产品推荐
相关产品推荐

