为二维数组制作边框的最佳方法?

问题描述

我目前正在处理 2D 数组,虽然我发现它们易于使用,但我经常面临为它们创建边界以及处理它的步骤的挑战。例如,我正在重做我用 python 制作的战舰游戏。 python版本没有边框,但是java版本我想挑战一下。

我尝试在初始化板的方法中创建边框,但是当我在主方法调用板时会导致格式问题。现在我正在使用嵌套的 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();
    }
}

解决方法

这是我整理的东西。

       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;
    }

}
,

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

───┼
 X │

截图:

almost square

输出由三部分组成:上一行字母,然后是一个包含左列数字和下边界行的字段。因此,包含船舶的整个字段可能如下所示:

   │ 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 │   │   │   │   │   │
───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

截图:

field with ships

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?