战舰游戏开发:如何检测棋盘船只周边合法性并统计船只数量?
战舰棋盘校验问题解决方案
现有代码已知bug修正
- 输入转换错误:你当前读取棋盘行时直接将char赋值给int数组,
'0'和'1'的ASCII码分别为48、49,会导致后续==1判断完全失效,修改输入代码:
// 原代码 board[x][y] = temp.charAt(x); // 修改为 board[x][y] = temp.charAt(x) - '0';
- 循环硬编码错误:
checkType方法中遍历棋盘写死了y<5和x<5,需替换为动态的size参数:
for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) {
- 数组越界风险:当前代码直接访问
x-1/y+1等坐标,未判断是否在棋盘边界内,会触发ArrayIndexOutOfBoundsException。
跨方法计数方案
Java为值传递,基础类型int无法直接在方法间修改原值,可用两种方案实现:
- 使用长度为1的int数组传递:数组为引用类型,方法内修改数组元素会同步到原变量
// 调用方定义 int[] shipCount = new int[1]; // 传入各个校验方法 horizontalBoat(board, size, x, y, shipCount); // 方法内计数 shipCount[0]++; - 将校验逻辑封装为独立类,使用成员变量存储计数,适合功能更复杂的后续迭代。
校验逻辑优化实现
你当前的方向校验逻辑存在重复识别、边界未处理的问题,推荐使用「标记已访问+全周边校验」的思路:
- 遍历棋盘每个格子,遇到未访问的船身(值为1)时,先识别整艘船的方向与所有点位
- 将该船所有点位标记为已访问,避免后续重复计数
- 遍历该船所有点位的8个相邻格,只要存在未访问的船身即判定为触碰,校验不通过
- 每识别完一艘合法船只,计数器加1
- 遍历完成后对比计数器值与预设船只数,一致则棋盘合法。
核心参考代码
// 8个方向偏移量,覆盖上下左右、四个对角 private static final int[][] DIRS = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}}; static boolean checkBoard(int[][] board, int size, int expectShipNum) { int[][] visited = new int[size][size]; // 也可以直接修改原board标记为2,节省内存 int shipCount = 0; for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { if (board[x][y] == 1 && visited[x][y] == 0) { // 先判断船的方向,L型船不合法 boolean hasRight = x+1 < size && board[x+1][y] == 1; boolean hasDown = y+1 < size && board[x][y+1] == 1; if (hasRight && hasDown) return false; // 识别整艘船的所有点位 int len = 0; if (hasRight) { // 水平船 while (x + len < size && board[x+len][y] == 1) { visited[x+len][y] = 1; len++; } } else if (hasDown) { // 垂直船 while (y + len < size && board[x][y+len] == 1) { visited[x][y+len] = 1; len++; } } else { // 长度为1的单船 visited[x][y] = 1; len = 1; } // 校验整艘船周边是否有其他船 for (int i = 0; i < len; i++) { int cx = hasRight ? x + i : x; int cy = hasDown ? y + i : y; for (int[] dir : DIRS) { int nx = cx + dir[0]; int ny = cy + dir[1]; if (nx >=0 && nx < size && ny >=0 && ny < size) { if (board[nx][ny] == 1 && visited[nx][ny] == 0) { return false; // 周边有其他船,触碰违规 } } } } shipCount++; } } } return shipCount == expectShipNum; }
直接在main方法中调用checkBoard(board, size, ships_num),返回true则棋盘合法,false则不合法。
内容的提问来源于stack exchange,提问作者Ceri Barnes
相关产品推荐
相关产品推荐

