Reputation: 37
I am currently working with 2D arrays, and while I find them simple to work with, I often face challenges with creating borders for them and the steps to approach it. For example, I'm redoing a Battleship game I made in python. The python version doesn't have a border, but for the java version, I want to tackle the challenge.
I have tried creating the border in the method that initializes the board, but that lead to formatting issues when I called the board in the main method. Now I'm handling the border in the main with a nested for-loop, and while the results have gotten better, the border is still incomplete. I'm trying to create this border I found online:
+---+
| |
+---+
But I haven't been successful. Here is my code:
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();
}
}
Upvotes: 1
Views: 1729
Reputation:
You can represent each cell of the field as an almost square, consisting of two rows: an upper border and an element with a right border, using the box-drawing characters:
───┼
X │
Screenshot:
The output consists of three parts: upper row of letters, then a field with a left column of numbers and a lower border row. As a result, the entire field with ships may look like this:
│ 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 │ │ │ │ │ │
───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
Screenshot:
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);
}
See also:
• Formatting 2d array of numbers
• How to draw a staircase with Java?
Upvotes: 1
Reputation: 51445
Here's something I put together.
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 + + + + + + + + + + + +
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
I created a two-dimensional char
grid to hold the ship's position, hits, misses, and water.
I used several StringBuilders
to create the display of the grid. The display of the grid is made up of Strings
. The actual grid array is the logical model.
I put one ship in the grid so you can see what it looks like.
I broke the displayGrid
method into three subordinate methods. Divide the work and you can focus on each part of the display separately.
In Java, class names start with an upper-case letter. Field and method names start with a lower-case letter. Class names are usually noun-verb combinations. Method names are usually verb-noun combinations. Generally, it's a good idea to get out of the static world as quickly as you can.
Here's the complete runnable code.
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;
}
}
Upvotes: 2