You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

战舰游戏:文本文件读取与舰船坐标存储技术求助

战舰游戏文件读取与坐标存储解决方案

问题回顾

你正在开发战舰(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());
        }
    }
}

关键细节解释

  1. 灵活的存储结构:用Map存储舰船数据,不管新增多少种舰船,都不需要修改代码,直接读取即可。
  2. 健壮性处理:
    • 用trim()去除字符串首尾空白,避免文件中的空格干扰解析
    • 跳过空行,防止文件中存在空白行导致错误
    • 过滤拆分后出现的空字符串(比如示例中Submarine行末尾的分号会产生空元素)
  3. 坐标解析:*是正则表达式的特殊字符,所以拆分时需要用\\*转义,才能正确拆分出行和列的数值。

可选:硬编码舰船变量(不推荐)

如果你一定要为每艘船创建单独的变量(比如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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:06:15