Multidimensional Arrays

Multidimensional arrays are simply arrays of other arrays. As an example, here’s how an array with two dimensions can be created:

int main() {
  int array2D[2][3] = {
    {5, 6, 2},
    {3, 9, 1}
  };
  return 0;
}

This 2D array consists of two rows (indicated by the “[2]“) and three columns (indicated by the “[3]“). In other words, it’s an array containing two arrays, each with three values. Note that indicating the size of multidimensional arrays (by using the [] after the array name) is required.

Here’s what a three-dimensional array would look like:

#include <iostream>

int main() {
  int array3D[4][3][2] = {
    {
      {3, 6},
      {5, 1},
      {7, 9}
    },
    {
      {2, 1},
      {8, 0},
      {1, 5}
    },
    {
      {7, 6},
      {9, 9},
      {3, 0}
    },
    {
      {4, 4},
      {2, 8},
      {7, 7}
    },
  };
  return 0;
}

This array contains four arrays that each contain three arrays of two values (hence the [4][3][2]). What a mouthful!

Accessing Multidimensional Array Elements

Just like with normal arrays, we can use the square brackets (“[” and “]”) to access elements from a multidimensional array. This time, however, we use a new set of square brackets for each array dimension. For example:

#include <iostream>

int main() {
  int array2D[2][3] = {
    {5, 6, 2},
    {3, 9, 1}
  };
  std::cout << "First row, first column: " << array2D[0][0] << "\n";
  std::cout << "Second row, first column: " << array2D[1][0] << "\n";
  std::cout << "First row, third column: " << array2D[0][2] << "\n";
  std::cout << "Second row, second column: " << array2D[1][1] << "\n";
  return 0;
}

Program output:

First row, first column: 5
Second row, first column: 3
First row, third column: 2
Second row, second column: 9

We can also modify multidimensional array elements as we did with normal arrays:

#include <iostream>

int main() {
  int array2D[2][3] = {
    {5, 6, 2},
    {3, 9, 1}
  };
  std::cout << "Original: " << array2D[0][2] << "\n";
  array2D[0][2] = 4; //Modifying first row, third column
  std::cout << "Updated: " << array2D[0][2] << "\n";
  return 0;
}

Program output:

Original: 2
Updated: 4

Using Loops with Multidimensional Arrays

To access every element in a multidimensional array, we can use loops within other loops (referred to as “nesting” loops). Outer loops typically use a variable named i for indexing, followed by j, k, etc. for inner loops. The program below outputs every element of a 2D array to the console:

#include <iostream>

int main() {
  int array2D[2][3] = {
    {5, 6, 2},
    {3, 9, 1}
  };
  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      std::cout << array2D[i][j] << " ";
    }
    std::cout << "\n";
  }
  return 0;
}

Program output:

5 6 2 
3 9 1 

To better visualize what exactly this is doing, let’s “unroll” these loops and go step-by-step through the process:

#include <iostream>

int main() {
  int array2D[2][3] = {
    {5, 6, 2},
    {3, 9, 1}
  };

  int i = 0;
  int j = 0;

  //First row
  std::cout << array2D[i][j] << " "; //i = 0, j = 0
  ++j;
  std::cout << array2D[i][j] << " "; //i = 0, j = 1
  ++j;
  std::cout << array2D[i][j] << " "; //i = 0, j = 2
  std::cout << "\n";

  //Second row
  ++i;
  j = 0;
  std::cout << array2D[i][j] << " "; //i = 1, j = 0
  ++j;
  std::cout << array2D[i][j] << " "; //i = 1, j = 1
  ++j;
  std::cout << array2D[i][j] << " "; //i = 1, j = 2
  std::cout << "\n";

  return 0;
}

Hopefully you can see that the outer loop (indexed with the variable i) goes through each row in the 2D array, and the inner loop (indexed with the variable j) goes through each column for every row. Doing this allows us to access every element from the array.

How can these be useful?

2D arrays can be used in lots of places! For example, maze-style games may use 2D arrays to represent maps:

#include <iostream>

int main() {
  const int MAP_SIZE = 10;
  bool map[MAP_SIZE][MAP_SIZE] = {
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 0, 1, 1, 0, 1},
    {0, 0, 0, 1, 1, 0, 1, 1, 0, 1},
    {1, 1, 0, 1, 0, 0, 0, 1, 0, 1},
    {1, 1, 0, 1, 0, 1, 0, 1, 0, 1},
    {1, 1, 0, 1, 0, 1, 0, 1, 1, 1},
    {1, 1, 0, 0, 0, 1, 0, 0, 0, 0},
    {1, 1, 1, 1, 1, 1, 1, 0, 1, 1},
    {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
  };
  for (int i = 0; i < MAP_SIZE; ++i) {
    for (int j = 0; j < MAP_SIZE; ++j) {
      if (map[i][j]) {
        std::cout << "#";
      }
      else {
        std::cout << " ";
      }
    }
    std::cout << "\n";
  }
  return 0;
}

Program output:

##########
#        #
##### ## #
   ## ## #
## #   # #
## # # # #
## # # ###
##   #    
####### ##
##########

Or they may be used to represent a tic-tac-toe board:

#include <iostream>

int main() {
  char board[3][3] = {
    {'O', 'X', 'O'},
    {'O', 'X', ' '},
    {'X', ' ', ' '}
  };
  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 3; ++j) {
      std::cout << board[i][j] << " ";
    }
    std::cout << "\n";
  }
  return 0;
}

Program output:

O X O 
O X   
X