如何优化函数让玩家快速抵达/越过XY目标点(Code vs Zombies场景)
优化Code vs Zombies的speedup函数实现
在Codingame的Code vs Zombies谜题场景中,玩家移动速度与目标点的坐标差直接相关——目标过近时移动会变得极慢。为了让玩家始终保持最快速度移动(允许越过目标点),我们可以对现有的speedup函数进行大幅简化,替代原有的循环遍历逻辑。
原代码分析
原代码通过循环逐步放大位移量,逻辑繁琐且可读性差,同时存在边界条件判断不够直观的问题:
let p = parseInt let speedup = (destination,playerPosition) =>{ let [destX,destY] = destination.split(" "); let [playerX,playerY] = playerPosition.split(" "); destX = p(destX);destY=p(destY);playerX=p(playerX);playerY=p(playerY) let [xDist,yDist] = [destX-playerX,destY-playerY] let i=1 do { if ((xDist*i)+playerX<0 || (yDist*i)+playerY<0 || xDist> 20000 || yDist > 20000){ xDist = (xDist*(i-1))+playerX; yDist = (yDist*(i-1))+playerY; return xDist + " " + yDist; } else if(i==19){ xDist = (xDist*i)+playerX; yDist = (yDist*i)+playerY; return xDist + " " + yDist; } i++ } while (i<20); }
优化后的实现
通过数学计算直接推导最大允许的位移放大倍数,替代循环逻辑,代码更简洁高效:
const speedup = (destination, playerPosition) => { // 解析坐标字符串为数字数组 const parseCoords = (str) => str.split(' ').map(Number); const [destX, destY] = parseCoords(destination); const [playerX, playerY] = parseCoords(playerPosition); // 计算位移向量 const dx = destX - playerX; const dy = destY - playerY; // 初始最大放大倍数为原代码的上限19 let maxK = 19; // 确保放大后的坐标不小于0(地图无负值) if (dx < 0) { // dx为负时,计算最大允许倍数避免x坐标为负 const maxKX = Math.floor(playerX / (-dx)); maxK = Math.min(maxK, maxKX); } if (dy < 0) { // dy为负时,计算最大允许倍数避免y坐标为负 const maxKY = Math.floor(playerY / (-dy)); maxK = Math.min(maxK, maxKY); } // 保留原代码中位移超过20000时不放大的逻辑(若需调整可修改此处) if (dx > 20000 || dy > 20000) { maxK = 0; } // 确保倍数不小于0 maxK = Math.max(maxK, 0); // 计算最终目标坐标 const targetX = playerX + dx * maxK; const targetY = playerY + dy * maxK; return `${targetX} ${targetY}`; };
优化点说明
- 简化坐标解析:用函数式方法一次性完成字符串拆分和类型转换,减少重复代码
- 替代循环逻辑:通过数学计算直接得到最大允许的放大倍数,避免不必要的遍历,提升执行效率
- 清晰的边界处理:将每个边界条件(坐标非负、最大放大倍数、位移上限)单独处理,逻辑更直观,便于后续调整
- 鲁棒性提升:主动确保放大倍数不小于0,避免出现异常计算结果
注意事项
原代码中xDist>20000或yDist>20000时直接返回原位置的逻辑可能存在不合理性(比如目标在玩家右侧超过20000时完全不移动),如果需要调整位移上限的判断逻辑,可将该条件修改为判断放大后的位移绝对值,例如:
// 示例:调整为放大后的位移绝对值不超过20000 if (Math.abs(dx * maxK) > 20000 || Math.abs(dy * maxK) > 20000) { // 重新计算最大允许倍数 const maxKX = Math.floor(20000 / Math.abs(dx)) || 0; const maxKY = Math.floor(20000 / Math.abs(dy)) || 0; maxK = Math.min(maxK, maxKX, maxKY); }
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

