I am trying to make a program that plays battleship. I have a 2D array that is printed to the console with nested for loops to display a 10x10 grid of dots that represent the grid. I would like to be able to have the user input an x and y coord for the ship and have it displayed on the grid with a different character like a " " for example and have it stored every time I "re-draw" the grid.
char playerBoard[][]
is initialized earlier in the global scope.
void drawPlayerBoard()
{
int yLabel = 0;
char xLabel = 65;// ascii
for (int i = 0; i < rows; i )
{
for (int j = 0; j < columns; j )
{
playerBoard[i][j] = 46;// ascii
}
}
cout << " ";
for (xLabel = 65; xLabel < 75; xLabel )
{
cout << xLabel << " ";
}
cout << "\n";
for (int i = 0; i < rows; i )
{
yLabel ;
if (yLabel >= 10)
{
cout << yLabel << " ";
}
else
{
cout << yLabel << " ";
}
for (int j = 0; j < columns; j )
{
cout << playerBoard[i][j] << " ";
}
cout << "\n";
}
}
CodePudding user response:
You can make this a lot easier on yourself. For instance, initializing every value of playerBoard
to '.'
can be as simple as:
std::fill_n((char*)playerBoard, rows * columns, '.');
You probably don't want to do that in the drawPlayerBoard
function, because you'll erase your board whenever you want to display it. Make a separate function:
#include <algorithm>
const int rows = 10;
const int cols = 10;
char playerBoard[rows][cols];
void clearPlayerBoard()
{
std::fill_n((char*)playerBoard, rows * cols, '.');
}
For outputting X-labels, similarly avoid using magic numbers representing ASCII values. For instance, you can write char('A' i)
to get the letter you want.
To manage your spacing, use I/O manipulators to control the output width. This avoids ugly code like you're doing with your yLabel
tests right now. Simply use std::setw
, and avoid cluttering your code with strings of spaces.
Putting this together:
#include <iomanip>
#include <iostream>
void drawPlayerBoard()
{
const int colWidth = 2;
const int rowLabelWidth = 3;
// Draw X labels
std::cout << std::setw(rowLabelWidth) << "";
for (int col = 0; col < cols; col )
{
std::cout << std::setw(colWidth) << char('A' col);
}
std::cout << '\n';
// Draw rest of board
for (int row = 0; row < rows; row )
{
std::cout << std::setw(rowLabelWidth) << row 1;
for (int col = 0; col < cols; col )
{
std::cout << std::setw(colWidth) << playerBoard[row][col];
}
std::cout << '\n';
}
}
Notice how you can now control the layout with those two "width" values. The most useful here would be the rowLabelWidth
value, which effectively controls how much indentation your board has.
To test, just some simple driver code from main
:
int main()
{
clearPlayerBoard();
drawPlayerBoard();
}
And you get the output:
A B C D E F G H I J
1 . . . . . . . . . .
2 . . . . . . . . . .
3 . . . . . . . . . .
4 . . . . . . . . . .
5 . . . . . . . . . .
6 . . . . . . . . . .
7 . . . . . . . . . .
8 . . . . . . . . . .
9 . . . . . . . . . .
10 . . . . . . . . . .
Now you can write a simple function to add your ships:
void placeShip(int row, int col, int size, bool horizontal, char player)
{
if (horizontal)
{
for (int i = 0; i < size; i ) playerBoard[row][col i] = player;
}
else
{
for (int i = 0; i < size; i ) playerBoard[row i][col] = player;
}
}
Example:
char player = '#';
placeShip(3, 2, 5, false, player);
placeShip(2, 4, 4, true, player);
placeShip(0, 9, 3, false, player);
placeShip(6, 6, 3, true, player);
placeShip(8, 7, 2, true, player);
drawPlayerBoard();
Output:
A B C D E F G H I J
1 . . . . . . . . . #
2 . . . . . . . . . #
3 . . . . # # # # . #
4 . . # . . . . . . .
5 . . # . . . . . . .
6 . . # . . . . . . .
7 . . # . . . # # # .
8 . . # . . . . . . .
9 . . . . . . . # # .
10 . . . . . . . . . .