10x10 Battleship game 2d array issue

Hello all,

I am currently working on a C++ battleship project but this seems unique to many of the others I have seen on here. My professor never explained 2D arrays in functions but seems to want them used as function parameters, so I'm hoping for some guidance here. Here's the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  void drawGrid(char ary[][MAX_COLS])
{
	cout << " "; // Move over a space before printing the 'A'
	for (int i = 0;i < 10;i++)
		cout << i << " ";
	cout << endl;  // New line before the start of the vertical numbers
	for (int j = 0; j < 10;j++)
		cout << j << endl;
	
}

void enterShips(char ary[][MAX_COLS]) {
	char coord;
	int x;
	int y;
	cout << "You will enter 5 ships" << endl;
	cout << "For each ship, enter H for horizontal or V for Vertical" << endl;
	cout << "Followed by row/column coordinates" << endl;
	cout << "Example: H 0 0" << endl;

	cout << "Ship 1 [1]:";
	cin >> coord >> x >> y;
	if (coord = 'H') {

		drawGrid(ships[x][y]);
	}
	else if (coord = 'V') {

	}
} 



I'm trying to figure out how I can implement the drawGrid function into the enterShips function so I can let the user place their ships onto the grid like this.

0 1 2 3 4 5 6 7 8 9
1 x x
2
3 x
4 x
5 x
6
7
8
9

With the x's representing them placing the ships. in enterShips, but while I can make the grid in drawGrid, how would I implement the 2D array parameter in this function to allow enterShips to access and draw it? I already have an initialize function and a ships array is made in main, ships[10][10] = {(10 0's)}

Any guidance would greatly help me as this has been driving me crazy! Thanks!
A display function for a 2D array with column and row 'headers', and some built-in hackery for 2D arrays with dimensions greater than 9 and less than 100. Sloppy, but you should be able to understand what is going on:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

constexpr unsigned MAX_ROWS { 10 };
constexpr unsigned MAX_COLS { 10 };

void DisplayArray(int[MAX_ROWS][MAX_COLS]);

int main()
{
   int arr[MAX_ROWS][MAX_COLS] = { { } };

   DisplayArray(arr);
}

void DisplayArray(int a[MAX_ROWS][MAX_COLS])
{
   // the column header
   std::cout << "  ";
   if constexpr(MAX_COLS > 9) { std::cout << ' '; }

   for (size_t col { }; col < MAX_COLS; col++)
   {
      std::cout << col + 1 << ' ';
   }
   std::cout << '\n';

   for (size_t row { }; row < MAX_ROWS; row++)
   {
      // the individual row headers
      std::cout << row + 1 << ' ';
      if (row < 9) { std::cout << ' '; }

      for (size_t col { }; col < MAX_COLS; col++)
      {
         std::cout << a[row][col] << ' ';
      }
      std::cout << '\n';
   }
}

The if constexpr() statement requires C++17 or later. You can use a regular if, your compiler may complain with a warning.

Personally I'd use a 2D std::vector if possible, a vector 'remembers' its size, or a simulated 2D array in 1 dimension.
https://www.tutorialspoint.com/Passing-two-dimensional-array-to-a-Cplusplus-function
Last edited on
Hello tgp23,

Consider this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void enterShips(char board[][MAX_COLS])
{
    char direction;
    int row;
    int col;

    std::cout << 
        "You will enter 5 ships\n"
        "For each ship, enter H for horizontal or V for Vertical\n"
        "Followed by row/column coordinates\n"
        "Example: H 0 0\n";

    std::cout << "Ship 1 [1]:";
    std::cin >> direction >> row >> col;

    if (direction = 'H')
    {
        board[row][col] = 'x';

        //drawGrid(board[row][col]);
    }
    else if (direction = 'V')
    {

    }
}

This is a start, but there are different types of ships. Each with 2 or more positions that can be marked. You will need to account for the ship type and how many hits it will take for each ship.

I think the call to "drawGrid" should come after the if statements not in. Also you should not need the anything to the function other than "board".

Notice how I renamed the variables. It helps to understand the code easier.

Andy
Thank you for the help! However, When using drawGrid in that manner, it is claiming drawGrid cannot be used due to the parameters being of type char. drawGrid is meant to ultimately draw the grid and enterShips is supposed to set up the given input, and then use those rows and cols and where the 'x' would go on the grid (aka play board) using drawGrid.
Hello tgp23,

Let's look at the function:
1
2
3
4
5
6
7
8
9
10
11
12
void drawGrid(char ary[][MAX_COLS])
{
    cout << " "; // Move over a space before printing the 'A'

    for (int i = 0; i < 10; i++)
        cout << i << " ";

    cout << '\n';  // New line before the start of the vertical numbers

    for (int j = 0; j < 10; j++)
        cout << j << '\n';
}

Line 3 works.

Lines 5 and 6 print the row numbers. OK.

Line 8 works.

Lines 10 and 11 print the row numbers.

You send the function an array, but never use it.

This is simpler than Furry Guy's code, but should give you a better idea of what is needed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void drawGrid(char board[][MAX_COLS])
{
    std::cout << " "; // Move over a space before printing the 'A'

    for (int i = 0; i < 10; i++)
        std::cout << i << " ";

    std::cout << '\n';  // New line before the start of the vertical numbers
    
    //for (int j = 0; j < 10; j++)
    //    std::cout << j << '\n';

    for (int row = 0; row < MAX_ROWS; row++)
    {
        std::cout << row/* << ' '*/;

        for (int col = 0; col < MAX_COLS; col++)
        {
            std::cout << board[row][col] << ' ';
        }

        std::cout << '\n';
    }
}

And to give you an idea:

You will enter 5 ships
For each ship, enter H for horizontal or V for Vertical
Followed by row/column coordinates
Example: H 0 0

Ship 1 Patrol Boat position 1: h 0 2
Ship 1 Patrol Boat position 2: h 0 3

 0 1 2 3 4 5 6 7 8 9
0    x x
1
2
3
4
5
6
7
8
9
Ship 2 Submarine  position 1: h 5 0
Ship 2 Submarine  position 2: h 5 1
Ship 2 Submarine  position 3: h 5 2

 0 1 2 3 4 5 6 7 8 9
0    x x
1
2
3
4
5x x x
6
7
8
9
Ship 3 Destroyer position 1:



In the "enterShips" function I noticed if (coord = 'H'). (=) meand to set and (==) means to compare. What you are doing is setting "coord" to 'H' which makes the if condition always true. You will never reach the if else.

Andy
That helped immensely. Thank you for your input code and showing me what is not needed/ why you have it there. Also thank you for the advice!!
Hello tgp23,

Things left, commented our, are there so show why they are not need to help you learn. They are not really meant to be left there.

Thinking about the "enterShips" function there is more you could do to reduce the amount of work the user has to do.

I set up 2 variable to help out:
1
2
constexpr int shipHits[]{ 2, 3, 3, 4, 5 };
const std::string shipType[]{ "Patrol Boat", "Submarine ", "Destroyer", "Battleship", "Carrier" };

The names of the ships can be changed if you like. I got the names from:
https://en.wikipedia.org/wiki/Battleship_(game) just for something to work with.

Consider entering the direction as a single input. Then in the if statements you can enter the starting row and col. If your direction is "H" then you need to check that the start column + number of hits does not exceed the array size. The same would be true for the "V" direction, but for rows.

Once you know the direction you can let the program adjust the board for number of hits with out asking the user for each element of the board.

Just some thoughts.

Andy
Topic archived. No new replies allowed.