【问题标题】:Best way to make a border for a 2D array?为二维数组制作边框的最佳方法?
【发布时间】:2021-06-16 06:14:20
【问题描述】:

我目前正在使用 2D 数组,虽然我发现它们使用起来很简单,但我经常面临为它们创建边框和处理它的步骤的挑战。例如,我正在重做一个用 python 制作的 Battleship 游戏。 python版本没有边框,但是java版本我想挑战一下。

我尝试在初始化板的方法中创建边框,但是当我在 main 方法中调用板时会导致格式问题。现在我正在使用嵌套的 for 循环处理 main 中的边框,虽然结果变得更好,但边框仍然不完整。我正在尝试创建我在网上找到的这个边框:

+---+
|   |
+---+

但我没有成功。这是我的代码:

public static String[][] Battlefield() {
    int row;
    int col;
    int cap_start = 65;

    //Makes board
    String[][] BattleBoard = new String[11][11];

    for (row = 0; row < BattleBoard.length; row++) {
        for (col = 0; col < BattleBoard[row].length; col++) {
            if (row == 0) {
                //System.out.print(
                //      "  " + Character.toString((char) cap_start) + "   ");
                BattleBoard[row][col] =
                        "  " + Character.toString((char) cap_start) + "   ";
                cap_start++;
            } else if (col == 0) {
                //Gives us 0-9
                //System.out.print(Integer.toString(row - 1) + " ");
                BattleBoard[row][col] = (Integer.toString(row - 1)) + "   ";
            } else {
                //System.out.print(" ");
                BattleBoard[row][col] = "   ";
            }
        }
    }
    return BattleBoard;
}
public static void main(String[] args) {
    Scanner userInput = new Scanner(System.in);
    Scanner colInput = new Scanner(System.in);
    Scanner rowInput = new Scanner(System.in);

    String player_col = "";
    String player_row = "";
    String[][] gameBoard = Battlefield();

    for (int row = 0; row < gameBoard.length; row++) {
        for (int col = 0; col < gameBoard[row].length; col++) {
            System.out.print(gameBoard[row][col] + "  |");
            if (row <= gameBoard.length - 1)
                System.out.print("+---+");
        }
        System.out.println();
    }
}

【问题讨论】:

  • 为什么网格上的每个点都需要 5 个字符(“+---+”)?一个点要么是空白(水),要么是一艘船的一部分,要么是一个射击过的地方。通常,您使用二维 int 数组或 char 数组创建网格模型。当你在控制台上显示它时,你将它转换为字符串。

标签: java arrays string multidimensional-array ascii-art


【解决方案1】:

这是我整理的。

       A     B     C     D     E     F     G     H     I     J     K     
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  1 +     +     +     +     +     +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  2 +     +     +     +     +     +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  3 +     +     +     +     +     +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  4 +     +     +     +     +  S  +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  5 +     +     +     +     +  S  +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  6 +     +     +     +     +  S  +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  7 +     +     +     +     +  S  +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  8 +     +     +     +     +  S  +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
  9 +     +     +     +     +     +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 10 +     +     +     +     +     +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
 11 +     +     +     +     +     +     +     +     +     +     +     +
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

我创建了一个二维char 网格来保存船的位置、命中、未命中和水。

我使用了几个StringBuilders 来创建网格的显示。网格的显示由Strings 组成。实际的网格数组就是逻辑模型。

我将一艘船放在网格中,这样你就可以看到它的样子。

我将displayGrid 方法分解为三个从属方法。划分工作,您可以分别专注于展示的每个部分。

在 Java 中,类名以大写字母开头。字段和方法名称以小写字母开头。类名通常是名词-动词组合。方法名称通常是动词-名词组合。一般来说,尽快离开静态世界是个好主意。

这是完整的可运行代码。

public class BattleshipDisplay {

    public static void main(String[] args) {
        BattleshipDisplay bd = new BattleshipDisplay();
        char[][]  grid = bd.createGrid();
        System.out.println(bd.displayGrid(grid));
    }

    public char[][] createGrid() {
        char[][] grid = new char[11][11];
        
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                grid[i][j] = ' ';
            }
        }
        
        grid[3][4] = 'S';
        grid[4][4] = 'S';
        grid[5][4] = 'S';
        grid[6][4] = 'S';
        grid[7][4] = 'S';
        
        return grid;
    }
    
    public String displayGrid(char[][] grid) {
        StringBuilder builder = new StringBuilder();
        String section = "+-----";
        
        builder.append(printHeaderLine(grid));
        builder.append(printDashedLine(grid, section));
        builder.append(printGrid(grid, section));
        
        return builder.toString();
    }

    private StringBuilder printHeaderLine(char[][] grid) {
        StringBuilder builder = new StringBuilder();
        
        builder.append("       ");
        for (int i = 0; i < grid.length; i++) {
            builder.append((char) ((int) 'A' + i));
            builder.append("     ");
        }
        
        builder.append(System.lineSeparator());
        return builder;
    }

    private StringBuilder printGrid(char[][] grid, String section) {
        StringBuilder builder = new StringBuilder();
        
        for (int i = 0; i < grid.length; i++) {
            builder.append(String.format("%3d", (i + 1)));
            builder.append(" ");
            for (int j = 0; j < grid[i].length; j++) {
                builder.append("+  ");
                builder.append(grid[i][j]);
                builder.append("  ");
            }
            
            builder.append("+");
            builder.append(System.lineSeparator());
            builder.append(printDashedLine(grid, section));
        }
        
        return builder;
    }
    
    private StringBuilder printDashedLine(char[][] grid, String section) {
        StringBuilder builder = new StringBuilder();
        
        builder.append("    ");
        for (int i = 0; i < grid.length; i++) {
            builder.append(section);
        }
        
        builder.append("+");
        builder.append(System.lineSeparator());
        
        return builder;
    }

}

【讨论】:

    【解决方案2】:

    您可以将字段的每个单元格表示为一个几乎是正方形,由两行组成:一个上边框和一个带右边框的元素,使用box-drawing characters:

    ───┼
     X │
    

    截图:

    输出由三部分组成:上排字母,然后是左列数字和下边框行的字段。因此,带有船只的整个字段可能如下所示:

       │ A │ B │ C │ D │ E │ F │ G │ H │ I │ J │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     1 │   │   │ X │   │   │   │ X │ X │ X │   │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     2 │ X │   │   │   │   │   │   │   │   │   │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     3 │   │   │ X │ X │ X │ X │   │   │   │   │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     4 │   │   │   │   │   │   │   │   │   │ X │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     5 │   │   │   │   │   │   │   │   │   │ X │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     6 │   │   │ X │   │   │   │ X │   │   │ X │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     7 │ X │   │   │   │   │   │ X │   │   │   │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     8 │ X │   │   │   │   │   │   │   │   │   │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
     9 │   │   │   │   │ X │   │   │   │   │ X │
    ───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
    10 │   │   │   │   │ X │   │   │   │   │   │
    ───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
    

    截图:

    Try it online!

    public static String[] outputField(String[][] field, int n) {
        return Stream.of(
                // upper row of letters
                Stream.of(IntStream.range(-1, n)
                    // first an empty square
                    .mapToObj(i -> i < 0 ? "   │" :
                        // then squares with letters
                        " " + Character.toString('A' + i) + " │")
                    .collect(Collectors.joining())),
                // field with a left column of numbers
                IntStream.range(0, n)
                    // row of the field, line of squares
                    .mapToObj(i -> IntStream.range(0, n)
                        // first a square with a number, then squares of the field
                        .mapToObj(j -> new String[]{
                            // upper row of square with an upper border
                            (j == 0 ? "───┼" : "")
                                    + "───" + (j < n - 1 ? "┼" : "┤"),
                            // lower row of square with element and right border
                            (j == 0 ? String.format("%2d", (i + 1)) + " │" : "")
                                    + " " + field[i][j] + " │"})
                        // reduce Stream<String[]> to a single array String[]
                        .reduce((arr1, arr2) -> IntStream.range(0, 2)
                            .mapToObj(j -> arr1[j] + arr2[j])
                            .toArray(String[]::new))
                        .orElse(new String[]{}))
                    .flatMap(Arrays::stream),
                // lower border row
                Stream.of(IntStream.range(-1, n)
                    .mapToObj(i -> i < n - 1 ? "───┴" : "───┘")
                    .collect(Collectors.joining())))
                .flatMap(Function.identity())
                .toArray(String[]::new);
    }
    
    public static void main(String[] args) {
        int n = 10;
        String[][] field = IntStream.range(0, n)
                .mapToObj(i -> new String[n])
                .peek(row -> Arrays.fill(row, " "))
                .toArray(String[][]::new);
    
        // four-pipe ship
        field[2][2] = field[2][3] = field[2][4] = field[2][5] = "X";
        // three-pipe ships
        field[0][6] = field[0][7] = field[0][8] = "X";
        field[3][9] = field[4][9] = field[5][9] = "X";
        // two-pipe ships
        field[5][6] = field[6][6] = "X";
        field[8][4] = field[9][4] = "X";
        field[6][0] = field[7][0] = "X";
        // one-pipe ships
        field[0][2] = "X";
        field[1][0] = "X";
        field[5][2] = "X";
        field[8][9] = "X";
    
        // output
        Arrays.stream(outputField(field, n)).forEach(System.out::println);
    }
    

    另见:
    • Formatting 2d array of numbers
    • How to draw a staircase with Java?

    【讨论】:

      猜你喜欢
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多