战舰游戏开发Bug求助:4格战舰重复生成问题
解决战舰游戏中4格战舰重复/重叠的问题
嘿,我看了你的代码,找到几个导致4格战舰有时看起来重复的关键问题,咱们一步步来解决:
核心问题分析
- 重叠判断的语法错误:你在
generateBoat4里用$("#nID")检查元素是否有boat类,但这里的nID是变量,你实际是在找ID为字符串"nID"的元素(根本不存在),导致重叠判断完全失效,所以4格战舰经常和5格战舰重叠,看起来就像重复了。 - 递归调用的不合理性:当生成位置不合适时,你直接调用
generateBoats(),这会清空所有已生成的战舰并重新整个流程,不仅效率低,还可能因为重复触发导致意外生成多艘战舰。 - 无位置占用记录:每次生成都是随机碰运气,没有记录哪些格子已经被占用,判断起来效率低还容易出错。
分步修复方案
1. 修复重叠判断的语法错误
把generateBoat4里的判断语句改成用变量拼接选择器,比如:
// 原来的错误写法 if (($("#nID").hasClass("boat")) || ($("#nID2").hasClass("boat"))...) // 正确写法 if ($("#" + nID).hasClass("boat") || $("#" + nID2).hasClass("boat")...)
2. 优化递归逻辑,避免重复生成整个舰队
当位置不合适时,只重新生成当前战舰,而不是整个舰队。比如generateBoat5里的错误分支:
// 原来的写法 } else { generateBoats(); // 清空所有战舰重新来 } // 改成 } else { generateBoat5(); // 只重新生成5格战舰 }
generateBoat4里同理,改成调用generateBoat4()而不是generateBoats()。
3. 推荐:用集合记录已占用位置(更高效)
创建一个全局Set来存储已被战舰占用的格子ID,这样可以快速判断位置是否可用,不用每次去DOM里查找:
// 全局变量存储已占用的格子ID const occupiedCells = new Set(); function generateBoats() { console.log("func"); $("tr").children().removeClass("boat"); occupiedCells.clear(); // 清空集合 generateBoat5(); generateBoat4(); }
然后在generateBoat5和generateBoat4里,先生成所有需要的格子ID,检查是否在集合中,再决定是否生成或重新尝试。
完整修复后的代码
替换你原来的<script>部分即可:
<script> $(document).ready(function(){ for (var vr = 0; vr < 11; vr++) { var vrsta = document.getElementById('tabela').insertRow(vr); for (var st = 0; st < 11; st++) { var okvir = vrsta.insertCell(st); okvir.id = "x=" + st + "&y=" + vr; okvir.setAttribute("onclick", "koord(this.id)"); okvir.innerHTML = "x-" + st + " y-" + vr; } } }); const occupiedCells = new Set(); function generateBoats() { console.log("func"); $("tr").children().removeClass("boat"); occupiedCells.clear(); generateBoat5(); generateBoat4(); } function generateBoat5() { var rotation = Math.floor((Math.random() * 2)); var randX = Math.floor((Math.random() * 11)); var randY = Math.floor((Math.random() * 11)); const cells = []; if (rotation == 0) { if (randX > 6) { generateBoat5(); return; } for (let i=0; i<5; i++) { cells.push(`x=${randX+i}&y=${randY}`); } } else if (rotation == 1) { if (randY > 6) { generateBoat5(); return; } for (let i=0; i<5; i++) { cells.push(`x=${randX}&y=${randY+i}`); } } // 检查是否已被占用 for (const cell of cells) { if (occupiedCells.has(cell)) { generateBoat5(); return; } } // 标记占用并添加样式 cells.forEach(cell => { occupiedCells.add(cell); $(`#${cell}`).addClass("boat"); }); } function generateBoat4() { var rotation = Math.floor((Math.random() * 2)); var randX = Math.floor((Math.random() * 11)); var randY = Math.floor((Math.random() * 11)); const cells = []; if (rotation == 0) { if (randX > 7) { generateBoat4(); return; } for (let i=0; i<4; i++) { cells.push(`x=${randX+i}&y=${randY}`); } } else if (rotation == 1) { if (randY > 7) { generateBoat4(); return; } for (let i=0; i<4; i++) { cells.push(`x=${randX}&y=${randY+i}`); } } // 检查是否已被占用 for (const cell of cells) { if (occupiedCells.has(cell)) { generateBoat4(); return; } } // 标记占用并添加样式 cells.forEach(cell => { occupiedCells.add(cell); $(`#${cell}`).addClass("boat"); }); } function koord(id) { // 可以在这里添加点击后的逻辑,比如判断是否击中 console.log("Clicked cell:", id); } </script>
这样修改后,4格战舰就不会再和5格战舰重叠,也不会出现看起来重复的情况啦!
内容的提问来源于stack exchange,提问作者progg24
相关产品推荐
相关产品推荐

