I'm working on a simple, text-based Battle Ship game in C++. I'm currently trying to make a grid/board show properly in the console. I had the formatting correct, but I found that the elements of the 2D array wouldn't be right. Below is an example. I've set all elements in the 2D grid to Z, but they all show up as Y, for some reason. Why is it changing the variable?
#include <iostream>
using namespace std;
enum Grid {X, Y, Z};
const int GRID_SIZE = 10;
Grid grid[GRID_SIZE][GRID_SIZE] = {Z};
void displayGrid();
int main()
{
displayGrid();
cin.get();
return 0;
}
void displayGrid()
{
// Display top column of the grid, containing numbers.
cout << "\t |";
for (int i = 0; i < GRID_SIZE; i++)
cout << i << "|";
cout << endl;
Grid gridContent;
for (int y = 0; y < GRID_SIZE; y++)
{
cout << "\t" << y << "|";
for (int x = 0; x < GRID_SIZE; x++)
{
gridContent = grid[y][x];
if (gridContent = X)
cout << "X|";
else if (gridContent = Y)
cout << "Y|";
else if (gridContent = Z)
cout << "Z|";
}
cout << "\n";
}
}
First:
Grid grid[GRID_SIZE][GRID_SIZE] = {Z}
initializes only the first element of the array grid
with Z
(and the rest of the elements to 0, see aggregate initialization). You need a nested loop inside main
that initializes all elements to Z
, like
for(int i = 0; i < GRID_SIZE; ++i)
for(int j = 0; j < GRID_SIZE; ++j)
grid[i][j] = Z;
Second:
if (gridContent = X)
sets the gridContent
to X
(this mistake also occurs in the other if
s). To test for equality, need to use ==
instead.
Third: If you really want to understand why Y
was displayed before, that's because the condition in
if(gridContent = X)
evaluates to false
, since X
converts to 0
, which is then assigned to gridContent
. Therefore, the program goes into the other
if(gridContent = Y)
in which it sets gridContent
to Y
, and because the latter is non-zero, the if
condition evaluates to true
. You do this in a loop, so you end up displaying all elements as Y
. Not quite what you wanted.
Best practices
One way of avoiding these mistakes is to compile with all warnings on. For example, g++ -Wall -Wextra test.cpp
spits out
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (gridContent = X)
and clang++ is a bit more helpful
warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
so you definitely know something is wrong.
Another approach is to always put the rvalue on the left of the equality test, like
if(X == gridContent)
Here X
is a rvalue, and if by mistake you type =
instead ==
, then the compiler will issue an error, such as
error: lvalue required as left operand of assignment
since you can not assign to a rvalue.
Finally, try using standard containers instead of raw arrays, like std::vector<>
.