战舰游戏:文本文件读取与舰船坐标存储技术求助
战舰游戏文件读取与坐标存储解决方案
问题回顾
你正在开发战舰(Battleship)游戏,需要从指定格式的文本文件中读取数据:
- 第一行是棋盘尺寸,需存入
int类型变量 - 后续每行对应一艘舰船,格式为
舰船名称;坐标1;坐标2;...,每个坐标用*分隔行列,需为每艘舰船创建int[][]数组存储坐标(比如Carrier数组中int[0][0]=3、int[0][1]=2)
你已经写出了基础的文件读取代码,但还没完成坐标解析和存储的核心逻辑,接下来我会帮你完善这部分内容。
完整实现代码
这里推荐使用Map<String, int[][]>来存储所有舰船数据,这种方式扩展性更强,无需提前硬编码每艘船的变量:
import java.io.File; import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class BattleshipReader { // 存储棋盘尺寸 private int boardSize; // 存储所有舰船:键是舰船名称,值是坐标二维数组 private Map<String, int[][]> ships = new HashMap<>(); public void readFile(File f) throws FileNotFoundException { Scanner scanner = new Scanner(f); int lineNumber = 1; while (scanner.hasNextLine()) { String line = scanner.nextLine().trim(); // 跳过空行,避免文件空白内容干扰解析 if (line.isEmpty()) { continue; } if (lineNumber == 1) { // 读取并解析棋盘尺寸 boardSize = Integer.parseInt(line); lineNumber++; continue; } // 拆分舰船行的各个部分 String[] lineParts = line.split(";"); String shipName = lineParts[0].trim(); // 统计有效坐标的数量(过滤末尾分号导致的空字符串) int validCoordCount = 0; for (int i = 1; i < lineParts.length; i++) { if (!lineParts[i].trim().isEmpty()) { validCoordCount++; } } // 初始化当前舰船的坐标数组 int[][] shipCoordinates = new int[validCoordCount][2]; int coordIndex = 0; // 遍历所有坐标字符串,解析为整数并存入数组 for (int i = 1; i < lineParts.length; i++) { String coordStr = lineParts[i].trim(); if (coordStr.isEmpty()) { continue; } // 拆分坐标的行和列:*是正则特殊字符,需要用\\转义 String[] coordParts = coordStr.split("\\*"); int row = Integer.parseInt(coordParts[0]); int col = Integer.parseInt(coordParts[1]); shipCoordinates[coordIndex][0] = row; shipCoordinates[coordIndex][1] = col; coordIndex++; } // 将当前舰船存入Map ships.put(shipName, shipCoordinates); lineNumber++; } scanner.close(); } // 提供外部获取数据的方法 public int getBoardSize() { return boardSize; } public Map<String, int[][]> getShips() { return ships; } // 测试代码,验证读取效果 public static void main(String[] args) { try { BattleshipReader reader = new BattleshipReader(); reader.readFile(new File("battleship.txt")); System.out.println("棋盘尺寸:" + reader.getBoardSize()); for (Map.Entry<String, int[][]> entry : reader.getShips().entrySet()) { System.out.println("\n舰船名称:" + entry.getKey()); int[][] coords = entry.getValue(); for (int[] coord : coords) { System.out.printf("(%d, %d) ", coord[0], coord[1]); } } } catch (FileNotFoundException e) { System.err.println("未找到文件:" + e.getMessage()); } } }
关键细节解释
- 灵活的存储结构:用
Map存储舰船数据,不管新增多少种舰船,都不需要修改代码,直接读取即可。 - 健壮性处理:
- 用
trim()去除字符串首尾空白,避免文件中的空格干扰解析 - 跳过空行,防止文件中存在空白行导致错误
- 过滤拆分后出现的空字符串(比如示例中Submarine行末尾的分号会产生空元素)
- 用
- 坐标解析:
*是正则表达式的特殊字符,所以拆分时需要用\\*转义,才能正确拆分出行和列的数值。
可选:硬编码舰船变量(不推荐)
如果你一定要为每艘船创建单独的变量(比如int[][] carrier),可以在类中预先定义变量,然后通过判断舰船名称赋值:
// 在类中定义变量 private int[][] carrier; private int[][] battleship; private int[][] submarine; private int[][] destroyer; // 在处理舰船行时替换Map存储的逻辑 switch(shipName.toLowerCase()) { case "carrier": carrier = shipCoordinates; break; case "battleship": battleship = shipCoordinates; break; case "submarine": submarine = shipCoordinates; break; case "destroyer": destroyer = shipCoordinates; break; }
不过这种方式扩展性很差,新增舰船时必须修改代码,所以更推荐使用Map的方案。
内容的提问来源于stack exchange,提问作者Cedric
相关产品推荐
相关产品推荐

