Search code examples
c++multidimensional-arrayvisual-studio-2013consoleenumerator

2D array won't display correct contents in console grid


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

Solution

  • 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 ifs). 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<>.