What Is a 2D Array in Programming? Rows and Columns of Tiles
If you have ever wondered what is a 2D array in programming, the short answer is a grid of values you reach with two numbers: a row and a column. This guide covers rows and columns of tiles, how to create one, how to read and change a tile, how to loop over the whole grid, and the mistakes that trip people up. The examples come from a tile map, because that is where 2D arrays are easiest to see.
What is a 2D array in programming?
A 1D array is a row of boxes. You ask for box number 3 and you get what is inside. A 2D array is a row of rows. You ask for a row number and a column number, and you get what is inside that one cell.
Every cell holds the same type of value. It could be a number, a letter, a true/false flag or a small label. The size is fixed when you make the array. A grid with 13 rows and 13 columns has 169 cells, and that count does not change.
Rows and columns: picturing a grid of tiles
Picture graph paper. Rows run left to right, and you count them from the top. Columns run top to bottom, and you count them from the left. Each square where a row and a column cross is one tile.
Now picture a game map built from tiles. Each tile is one of a few kinds: empty floor, a breakable wall, a hard wall, water. The map is the grid, and each tile is a cell with a small value that says which kind it is.
In Tank City Reboot, each map is 13 by 13 tiles. The enemy gates are at the top left, top middle and top right, your tank starts just left of the CPU core, and the core sits at the bottom middle. All of it sits on that grid.
Counting starts at zero in most languages. So the rows of a 13 row grid are numbered 0 to 12, and so are the columns. The top left tile is row 0, column 0. The bottom right tile is row 12, column 12.

One tile is picked out by its row and its column.
How to create a 2D array (with code examples)
The exact syntax depends on the language, but the pattern is the same: say the type, the number of rows and the number of columns.
In C#, which is the language behind the game files here, a true rectangular 2D array looks like this: int[,] map = new int[13, 13];. That makes 13 rows and 13 columns, and every cell starts at 0.
To fill it with starting values, you can write them out: int[,] small = { {0, 1, 0}, {1, 1, 1}, {0, 1, 0} };. That is a 3 by 3 grid. Read it as three rows, each with three values. The 1s form a plus sign if you treat 1 as "wall" and 0 as "empty".
In Python you usually build a list of lists: grid = [[0] * 13 for _ in range(13)]. Write it with the loop, not as [[0] * 13] * 13. The shorter version repeats the same row 13 times, so changing one cell seems to change a whole column.
Reading and changing a tile with [row][column] indexing
You reach one cell by giving its row first, then its column. In C# that is map[row, col]. In Python or JavaScript it is map[row][col].
Say you use 0 for empty, 1 for firewall and 2 for silicon. To read the tile in row 4, column 6, write int tile = map[4, 6];. To break a firewall block there, write map[4, 6] = 0;.
That second line is the idea behind a destructible wall. A shot hits a tile, the code checks whether the value is firewall, and if so it writes the empty value into that cell. The next frame is drawn from the changed grid, and the wall is gone.
A pair like (row, column) is also a handy thing to pass around. If you want to return "the tile where the shot landed" from a function, you return two numbers together. That is what a tuple is for.
Looping through every tile and how it sits in memory
To visit every cell, you need one loop inside another. The outer loop walks the rows. The inner loop walks the columns of the current row.
In words: for each row from 0 to 12, for each column from 0 to 12, look at map[row, col]. The inner loop finishes all 13 columns before the outer loop moves to the next row. So the cells are visited left to right, top to bottom, like reading a page.
Here is a worked task. You want to count how many firewall tiles a map has. Start a counter at 0. Run the nested loops. Inside, if the tile equals the firewall value, add 1 to the counter. When both loops end, the counter holds your answer.
Computer memory is one long line, so a 2D array is stored flattened, row by row. This is called row-major order. That gives you a formula. For a grid with width columns, the cell at (row, col) sits at position row * width + col in the flat line. For a 13 wide grid, row 2, column 5 is at 2 * 13 + 5 = 31.
Many programmers store a grid as a plain 1D array and do this math themselves. It is the same trick used when a binary heap is laid out in an array: a shape that looks like a tree or a grid is kept in a simple line, and arithmetic finds your way around.
Real uses: tile maps and boards
Tank City Reboot is a good place to see both uses at once, because it keeps its field in a grid at more than one scale.
- Tile maps. Each stage is a 13 by 13 map. Stage 3, COOLANT, has two coolant rivers across the map, each with one gap on the left and one on the right. In a grid, that is a pair of rows of "coolant" values with a couple of "empty" ones in each.
- Boards with finer detail. The first game's field is 208 by 208 pixels, stored as 52 by 52 squares of 4 by 4 pixels. Each square is one byte that names what is there, one of seven kinds such as empty, firewall, silicon, coolant, encrypted zone, data bus or the core. A 13 tile map is 52 squares wide because each tile is 4 squares across.
Zero Day adds another grid. Its arena is a 25 by 25 grid of cells that enemy tanks use to find their way. The route search over those cells counts a step as 1 and a step onto firewall as 4, because a tank has to shoot through it first. A grid of cells like that is a 2D array of numbers, doing real work.
Common mistakes: off-by-one errors and mixing up x and y
Off-by-one errors. A grid with 13 rows has valid row numbers 0 to 12. Row 13 does not exist. If your loop says row <= 13 instead of row < 13, you read past the end and the program crashes or, in some languages, reads junk. When you write a loop, say the last valid index out loud.
Mixing up x and y. On a screen, x goes across and y goes down. In a grid, the row is the vertical position and the column is the horizontal one. So map[row, col] means map[y, x]. Writing map[x, y] by habit flips the grid on its side. On a square map you may not even notice until a wall shows up in the wrong place. On a rectangular map it crashes.
Frequently asked questions
Is a 2D array the same as an array of arrays?
Almost. In Python and JavaScript, a 2D array is an array of arrays, so rows can even differ in length. C# has both that kind (jagged) and a true rectangular int[,], where every row has the same length.
Which comes first, the row or the column?
The row comes first in almost every language, so you write grid[row][col]. Think of it as y first, then x.
How do you find the number of rows and columns?
For a list of lists, the number of rows is the length of the outer list and the number of columns is the length of one row. In C#, map.GetLength(0) gives the rows and map.GetLength(1) gives the columns.
When should I use a 1D array instead of a 2D array?
Use a 1D array when you want one block of memory or fast copying, and you do not mind doing row * width + col yourself. Use a 2D array when clear code matters more and the grid is small.
Get started: build a tile grid in Tank City Reboot
Open Tank City Reboot. It is free, plays in your browser on a computer or a phone, and needs no account to play. Start stage 1, then look at the field as a 13 by 13 grid. Find the three gates at the top and the core at the bottom middle.
Then try this exercise on paper. Draw a 13 by 13 grid for stage 3, COOLANT. Mark the two rivers and their gaps. Write the grid as a 2D array, with 0 for floor and 3 for coolant. Finally, write the nested loop that counts the coolant tiles. If your count and your drawing agree, you have the idea.
Comments
No comments yet.
Sign in or make an account to comment.