基于math.random的方块游戏:定时器与点击事件异常问题
问题分析与解决方案
嘿,我来帮你搞定这两个问题,咱们一步步拆解:
问题1:方块无规则乱跳(多实例定时器/重复事件绑定)
你的代码核心问题是重复执行初始化逻辑,导致多个定时器和事件绑定同时运行:
- 你把
test函数作为$(document).ready()的回调,又用setInterval(test, 2000)每隔2秒调用一次test。这意味着每次调用test,都会重新绑定点击事件、创建新的定时器,旧的定时器却没被清理——多个定时器同时触发移动逻辑,方块自然会乱跳。 - 另外,
randPosX和randPosY只在初始化时生成一次,所有移动都会用同一个固定位置,完全不符合"随机位移"的需求。
问题2:第二次点击无响应
点击事件里的clearInterval(fire)无法彻底清理定时器:因为fire是test函数内部的局部变量,每次调用test都会重新创建一个fire,点击时只能清除当前这个fire对应的定时器,之前的定时器还在后台运行,干扰后续的点击逻辑;再加上重复绑定的点击事件,整个逻辑就彻底混乱了。
修复后的完整代码
$(document).ready(function() { // 统一管理定时器实例,避免多实例冲突 var timerId = null; var autoMoveTimer = null; var timeLeft = 2; var elem = document.getElementById('time'); // 封装随机位置生成逻辑,每次移动都生成新位置 function getRandomPosition() { var containerWidth = $("#playArea").width(); var containerHeight = $("#playArea").height(); // 用0.9比例限制位置,避免方块超出容器 return { x: Math.floor(Math.random() * (containerWidth * 0.9)), y: Math.floor(Math.random() * (containerHeight * 0.9)) }; } // 封装方块移动逻辑,复用代码 function moveTarget() { var pos = getRandomPosition(); $('#target').css({ left: `${pos.x}px`, top: `${pos.y}px` }); } // 倒计时逻辑 function countdown() { if (timeLeft === 0) { moveTarget(); timeLeft = 5; } else { elem.innerHTML = `${timeLeft} seconds remaining`; timeLeft--; } } // 只绑定一次点击事件,避免重复绑定 $(document).on('click', '#target', function() { moveTarget(); // 重置倒计时 timeLeft = 2; // 清理并重启倒计时定时器 if (timerId) clearInterval(timerId); timerId = setInterval(countdown, 1000); // 清理并重启自动移动定时器 if (autoMoveTimer) clearInterval(autoMoveTimer); autoMoveTimer = setInterval(moveTarget, 2000); }); // 初始化启动定时器 timerId = setInterval(countdown, 1000); autoMoveTimer = setInterval(moveTarget, 2000); });
关键修复点说明
- 统一管理定时器:把定时器实例放在ready回调的作用域内,确保每次清理的是同一个定时器,彻底避免多实例冲突。
- 复用核心逻辑:把生成随机位置和移动方块的逻辑封装成独立函数,每次需要移动时调用,保证每次都是全新的随机位置。
- 单次事件绑定:点击事件只在页面初始化时绑定一次,避免重复绑定导致的逻辑混乱。
- 清晰的变量命名:把
fire改成autoMoveTimer,让代码可读性更强,减少歧义。
内容的提问来源于stack exchange,提问作者keano-
相关产品推荐
相关产品推荐

