Чтение строк из текстового файла и разделение его содержимого

#java #java.util.scanner #delimiter #readfile

#java #java.util.scanner #разделитель #readfile

Вопрос:

Для игры в Battleship я хочу считывать значения из текстового файла и сохранять их в переменные. Пример файла .txt:

     8
    Carrier;3*2;3*3;3*4;3*5;3*6
    Battleship;5*6;6*6;7*6;8*6
    Submarine;5*2;6*2;7*2;
    Destroyer;1*7;1*8
 

Первая строка обозначает размер моей доски.

Структура следующих строк обозначает корабль, то есть его название вместе с его координатами на доске. Например: Перевозчик имеет координаты: (3,2),(3,3),(3,4),(3,5)(3,6).

Количество координат, связанных с кораблем, фиксировано. Однако линия, на которой представлен корабль, может измениться.

Прямо сейчас я пытаюсь создать массив int[][] с именем Carrier, где int[0][0] равно 3, int[0][1] равно 2, … , и делаю это для каждого корабля.

Позже размер доски, который всегда помещается в первую строку, должен быть сохранен в переменной int size; .

Пока у меня есть этот код.

 public void ReadFile(File f) throws FileNotFoundException {
    Scanner scanner = new Scanner(f);
    int lineNumber = 1;

    while(scanner.hasNextLine()){
        String line = scanner.nextLine();
        if(lineNumber==1){ // Skipping board size for now.
            lineNumber  ;
            continue;

        }
        String[] coordinates = line.split(";");
        String ship = coordinates[0];
        System.out.println(ship);
        lineNumber  ;

    }

    scanner.close();

}
 

Я пробовал использовать разделители, разделение, .. но мне не удалось найти решение.. Спасибо за вашу помощь!

Комментарии:

1. В чем именно проблема? Разделение на; кажется прекрасным, и вы будете знать, какой корабль вы анализируете. После этого вы можете разделить каждую дополнительную строку в массиве координат[] на *, чтобы получить отдельные части (столбец и строку?). Поскольку я не знаю, какая структура данных вам нужна для сохранения данных, я не могу дать больше советов.

2. Вы говорите, что «пытаетесь создать массив int[][]», но этого нигде нет в вашем коде. Даже если ваш код не работает, он должен показывать, где вы хотите что-то сделать, при необходимости с помощью комментариев.

Ответ №1:

Кроме того, размер платы, который всегда помещается в первую строку, должен храниться в переменной int size;

Итак, почему ваш код просто пропускает первую строку и ничего с ней не делает?

Ваша логика должна быть изменена, чтобы добавить что-то вроде следующего, чтобы прочитать размер платы:

 int size = scanner.nextInt();
scanner.nextLine(); // to skip to the next line of data
 

Затем вы используете свой цикл для чтения всей информации о корабле:

 while(scanner.hasNextLine()){
    String line = scanner.nextLine();
    String[] coordinates = line.split(";");
    String ship = coordinates[0];
    System.out.println(ship);
}
 

Редактировать:

этот массив строк имеет нулевые значения, потому что длина (#координаты) различна для каждого корабля.

Массив строк из кода, опубликованного в вашем вопросе, НЕ будет иметь нулевых значений. Он будет содержать только данные, которые были проанализированы из каждой строки данных.

Если вы попытаетесь скопировать данные из этого массива в другой 2D-массив фиксированного размера, то ваша логика неверна. Зачем вам создавать массив фиксированного размера, если вы знаете, что длина данных отличается?

По сути, мне нужно сохранить все координаты из carrier в один отдельный 2D-массив

Я бы НЕ стал использовать 2D-массив. Вместо этого я бы создал ArrayList, содержащий все координаты для одного корабля. Затем вам нужен ArrayList для хранения всех кораблей. Таким образом, логика будет примерно такой:

 ArrayList<ArrayList<Point>> ships = new ArrayList<>();

while(scanner.hasNextLine())
{
    ...
    ArrayList<Point> ship = new ArrayList<>();

    for (int i = 1; i < coordinates.length; i  )
    {
        // split the value in the coordinates array at the given index
        // use the two values to create a Point object
        Point point = new Point(...);
        ship.add( point );
    }

    ships.add( ship );
}
 

Комментарии:

1. Спасибо за ваш ответ. Я попробовал ваше решение, однако оно создает массив со строками, где coordinate[0] содержит все названия кораблей (что здорово), но coordinate [1] содержит все первые координаты. По сути, мне нужно сохранить все координаты из carrier в один отдельный 2D-массив, battleship в другом,… Кроме того, этот массив строк имеет нулевые значения, поскольку длина (#координаты) различна для каждого корабля. Спасибо за ваше время, camickr!

2. Большое спасибо. Учитывая, что моя логика в других классах построена на 2D-структуре для моих координат, я вынужден продолжать ее использовать (из-за нехватки времени для назначения). Спасибо за вашу помощь!

Ответ №2:

Попробуйте этот код :

     public static void ReadFile(File f) throws FileNotFoundException {
        Scanner scanner = new Scanner(f);
        int lineNumber = 1;
        int size_board;
        int [][] boards=new int[4][0];
        int index=0;
        while(scanner.hasNextLine()){
            String line = scanner.nextLine();
            
            if(lineNumber==1){
                line=line.replaceAll("[\n\t ]", "");
                size_board=Integer.parseInt(line);
                System.out.println(size_board);
                lineNumber  ;
                continue;

            }
            
            int[] board=new int[0];
            String[] coordinates = line.split(";");
            String ship = coordinates[0];
            System.out.println(ship);
            int z=0;
            for (int i=1;i<coordinates.length ; i  ) {
                board = Arrays.copyOf(board, board.length 2);
                String[] coords=coordinates[i].split("\*");
                board[z  ]=Integer.parseInt(coords[0]);
                board[z  ]=Integer.parseInt(coords[1]);
            }

            lineNumber  ;
            boards[index]=Arrays.copyOf(boards[index], board.length);
            boards[index  ]=board;

        }

        scanner.close();

    }
 

Ответ №3:

Вот еще один вариант для вас. Это собирает корабли и координаты в карту <Строка, список>, где строковый ключ содержит либо «board», либо название корабля, а список содержит массив массивов с координатами или размером сетки.

   public static void ReadFile(File f) throws FileNotFoundException {
    Scanner scanner = new Scanner(f);
    int lineNumber = 1;
    Map<String, List> gameData = new HashMap<>();
    List board = new ArrayList();

    while (scanner.hasNextLine()) {
      String line = scanner.nextLine();
      if (lineNumber == 1) {
        String[] gridSize = { line };
        gameData.put("boardSize", Arrays.asList(gridSize));
        lineNumber  ;
        continue;

      }
      List<String> values = Arrays.asList(line.split(";"));
      List<String[]> coordinates = new ArrayList();
      values.subList(1, values.size()).forEach(in -> {
        coordinates.add(in.split("(?<![*])[*](?![*])"));
      });
      gameData.put(values.get(0), coordinates);
      lineNumber  ;
    }

    gameData.forEach((k, v) -> {
      System.out.print(k);
      System.out.println(Arrays.deepToString(v.toArray()));
    });
    scanner.close();

  }
}


 

и вот рабочий repl:
https://repl.it/@randycasburn/GlaringSoulfulNet