1.1 What Is a 2D Array?
A two-dimensional (2D) array is a data structure that stores elements in rows and columns, forming a grid-like structure. Each element is uniquely identified by two indices: its row index and its column index. If a 1D array is a list, a 2D array is a table.
- Declaration specifies two index ranges separated by a comma:
DECLARE matrix : ARRAY[1:3, 1:5] OF INTEGER. - The first range
1:3is the rows (1 to 3); the second range1:5is the columns (1 to 5). - Total elements = rows × columns =
3 × 5 = 15. - Typical uses: game boards (chess, tic-tac-toe), seating plans, spreadsheets and matrices.
Example: declare a 3 × 5 grid of integers
DECLARE matrix : ARRAY[1:3, 1:5] OF INTEGER
// 3 rows (1..3) and 5 columns (1..5) — 15 cells in totalKey idea: The first index is always the row, the second is always the column. Read matrix[2, 3] aloud as “matrix row 2, column 3” to keep them straight — this matches how you would describe a cell in a spreadsheet.
What Is a 2D Array?
1.2 Single Element Assignment & Access
Once a 2D array is declared, every cell starts empty. You can write a value into a single cell using an assignment statement, or read a value out of a cell into a variable.
- Assign:
matrix[2, 4] <- 1985writes 1985 into the cell at row 2, column 4. - Access:
value <- matrix[2, 3]reads the cell at row 2, column 3 and stores it invalue. - Row index always comes first, column index second — exactly the same order as the declaration.
Example: assign to one cell, then read from another
DECLARE matrix : ARRAY[1:3, 1:5] OF INTEGER
DECLARE value : INTEGER
matrix[2, 4] <- 1985 // Write 1985 into row 2, column 4
value <- matrix[2, 3] // Read row 2, column 3 into 'value'
OUTPUT value // Outputs whatever was stored at [2, 3]Assign to row 3, column 5
matrix[3, 5] <- 42Read from row 1, column 2
value <- matrix[1, 2]Common mistake: Swapping the indices — writing matrix[4, 2] <- 1985 when you meant row 2, column 4. Always remember: row first, column second. The cell matrix[4, 2] is a completely different position from matrix[2, 4].
Single Element Assignment & Access
1.3 Populating with Nested Loops
To populate every cell of a 2D array, use nested loops: an outer FOR loop walks through the rows, and an inner FOR loop walks through the columns of each row. The classic worked example builds a multiplication table by storing row * column in each cell.
Example: fill a 3 × 5 grid with a multiplication table
DECLARE matrix : ARRAY[1:3, 1:5] OF INTEGER
DECLARE row, col : INTEGER
FOR row <- 1 TO 3
FOR col <- 1 TO 5
matrix[row, col] <- row * col
NEXT col
NEXT rowAfter the loops, the array holds the grid:
| × | Col 1 | Col 2 | Col 3 | Col 4 | Col 5 |
|---|---|---|---|---|---|
| Row 1 | 1 | 2 | 3 | 4 | 5 |
| Row 2 | 2 | 4 | 6 | 8 | 10 |
| Row 3 | 3 | 6 | 9 | 12 | 15 |
Trace Table — every step of the nested loops
This trace table shows each step of execution. There are 15 steps in total — one for every cell in the 3 × 5 grid.
| Step | row | column | row × column | value stored in matrix[row, column] |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 × 1 | 1 |
| 2 | 1 | 2 | 1 × 2 | 2 |
| 3 | 1 | 3 | 1 × 3 | 3 |
| 4 | 1 | 4 | 1 × 4 | 4 |
| 5 | 1 | 5 | 1 × 5 | 5 |
| 6 | 2 | 1 | 2 × 1 | 2 |
| 7 | 2 | 2 | 2 × 2 | 4 |
| 8 | 2 | 3 | 2 × 3 | 6 |
| 9 | 2 | 4 | 2 × 4 | 8 |
| 10 | 2 | 5 | 2 × 5 | 10 |
| 11 | 3 | 1 | 3 × 1 | 3 |
| 12 | 3 | 2 | 3 × 2 | 6 |
| 13 | 3 | 3 | 3 × 3 | 9 |
| 14 | 3 | 4 | 3 × 4 | 12 |
| 15 | 3 | 5 | 3 × 5 | 15 |
How the nested loops work
- Row 1 starts → column goes
1 → 2 → 3 → 4 → 5→ Row 1 is now fully complete. - Row 2 starts → column again goes
1 → 2 → 3 → 4 → 5→ Row 2 is now fully complete. - Row 3 starts → column again goes
1 → 2 → 3 → 4 → 5→ Row 3 is now fully complete. - Only when Row 3 finishes does the program stop.
Key question: How many times does the assignment statement matrix[row, col] <- row * col run? Answer: 3 × 5 = 15 times (rows × columns). The body of the inner loop runs once for every (row, column) pair in the grid.
Populating with Nested Loops & Trace Tables
1.4 Traversal — Outputting Every Element
Traversal is the operation of visiting every element of a 2D array in turn. We use the same nested-loop pattern as for populating — outer loop for rows, inner loop for columns — but the body of the inner loop outputs each cell instead of writing to it.
- Use an outer
FORloop for rows and an innerFORloop for columns. - In the inner loop,
OUTPUT matrix[row, col], " "prints the current cell followed by a space. - After the inner loop, an empty
OUTPUT ""moves the cursor to a new line — so each row appears on its own line. - This is called row-major traversal: all of row 1 is printed before any of row 2.
Example: print a 3 × 5 grid as a grid
DECLARE matrix : ARRAY[1:3, 1:5] OF INTEGER
DECLARE row, col : INTEGER
// ... (assume matrix is already filled) ...
FOR row <- 1 TO 3
FOR col <- 1 TO 5
OUTPUT matrix[row, col], " "
NEXT col
OUTPUT ""
NEXT rowIf matrix holds the multiplication table from section 1.3, the output is:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15Print row 2 (loop columns)
DECLARE col : INTEGER
FOR col <- 1 TO 5
OUTPUT matrix[2, col], " "
NEXT colPrint column 3 (loop rows)
DECLARE row : INTEGER
FOR row <- 1 TO 3
OUTPUT matrix[row, 3], " "
NEXT rowExam tip: When the question asks you to “print row K” or “print column K”, decide which index is fixed. The fixed index stays a literal; the changing index is the loop variable.
Traversal & Outputting a Grid
1.5 Random Population — RANDOM vs RAND
A common task is to fill a 2D array with random numbers. The syntax differs between IGCSE / O Level and AS Level — make sure you use the right one for your syllabus.
IGCSE / O Level — RANDOM()
DECLARE Marks : ARRAY[1:3, 1:5] OF REAL
DECLARE x, y : INTEGER
FOR x <- 1 TO 3
FOR y <- 1 TO 5
Marks[x, y] <- RANDOM() * 100
NEXT y
NEXT xRANDOM() returns a real in 0 ≤ x < 1. Multiplying by 100 scales it to 0 ≤ x < 100 — a real value in the range 0 to 100 (exclusive of 100). Use INT(RANDOM() * 100) if you need an integer.
AS Level — RAND(n)
DECLARE Marks : ARRAY[1:3, 1:5] OF INTEGER
DECLARE x, y : INTEGER
FOR x <- 1 TO 3
FOR y <- 1 TO 5
Marks[x, y] <- RAND(101)
NEXT y
NEXT xRAND(n) returns an integer in the range 0 to n-1. So RAND(101) returns an integer 0..100 inclusive (101 possible values). It returns an INTEGER directly — no need to wrap with INT().
Important difference: RANDOM() (IGCSE) takes no argument and returns a real 0..<1. RAND(n) (AS Level) takes an integer n and returns an integer 0..n-1. The classic off-by-one trap is using RAND(100) when you wanted 0..100 — that gives you 0..99. To include 100, use RAND(101).
Random Population — RANDOM vs RAND
1.6 Searching in 2D Arrays & Worked Tasks
A linear search of a 2D array uses two nested loops to scan every cell. A BOOLEAN flag called found records whether the target has been located. Initialise it to FALSE before the loops; if any cell matches, set it to TRUE and output the row and column. After the loops, if found is still FALSE, output a “not found” message.
Example: search a 5 × 5 array for a target value
DECLARE array : ARRAY[1:5, 1:5] OF INTEGER
DECLARE targetValue : INTEGER
DECLARE found : BOOLEAN
DECLARE row, col : INTEGER
targetValue <- 10
found <- FALSE
// Nested loops to search for the target value
FOR row <- 1 TO 5
FOR col <- 1 TO 5
IF array[row, col] = targetValue THEN
found <- TRUE
OUTPUT "Found at ROW ", row, " COLUMN: ", col
END IF
NEXT col
NEXT row
IF NOT found THEN
OUTPUT "Target value not found in the array"
END IFWorked task: Contacts search
A 2D array Contacts stores the names and phone numbers of 250 contacts. Column 1 stores the contact name and column 2 stores the contact number. Write a pseudocode algorithm to input a contact name, search the array, and output the matching contact number. If the contact name is not found, output “Contact not found”.
DECLARE Contacts : ARRAY[1:250, 1:2] OF STRING
DECLARE SearchName : STRING
DECLARE found : BOOLEAN
DECLARE i : INTEGER
OUTPUT "Enter contact name to search: "
INPUT SearchName
found <- FALSE
FOR i <- 1 TO 250
IF Contacts[i, 1] = SearchName THEN
found <- TRUE
OUTPUT "Phone number: ", Contacts[i, 2]
END IF
NEXT i
IF NOT found THEN
OUTPUT "Contact not found"
END IFActivity: Treasure Hunt
An 8 × 8 two-dimensional array named map represents a grid of locations in a treasure-hunt game. Some cells contain the word “Treasure” while others contain “Empty”. Write a program to search the grid for the treasure and output the first location where it is found in the format Treasure found at Row X, Column Y. If no treasure is found, output No treasure found on the map.
DECLARE map : ARRAY[1:8, 1:8] OF STRING
DECLARE found : BOOLEAN
DECLARE row, col : INTEGER
found <- FALSE
FOR row <- 1 TO 8
FOR col <- 1 TO 8
IF map[row, col] = "Treasure" THEN
found <- TRUE
OUTPUT "Treasure found at Row ", row, ", Column ", col
END IF
NEXT col
NEXT row
IF NOT found THEN
OUTPUT "No treasure found on the map."
END IFActivity: Find the word “Start”
You are given a 2D array words with three rows and five columns, filled with various words. The word “Start” is hidden in one of the positions within this array. Write a program that navigates through the array to locate and output the position of the word “Start” in the format Start found at Row X, Column Y.
DECLARE words : ARRAY[1:3, 1:5] OF STRING
DECLARE found : BOOLEAN
DECLARE row, col : INTEGER
found <- FALSE
FOR row <- 1 TO 3
FOR col <- 1 TO 5
IF words[row, col] = "Start" THEN
found <- TRUE
OUTPUT "Start found at Row ", row, ", Column ", col
END IF
NEXT col
NEXT row
IF NOT found THEN
OUTPUT "Start not found in the array"
END IFKey Points Summary
A 2D array stores elements in rows and columns, forming a grid.
Declare with two index ranges: ARRAY[1:R, 1:C] OF Type.
Total elements = rows × columns.
matrix[row, col] — row index first, column index second.
Populate and traverse with two nested FOR loops.
Outer loop = rows, inner loop = columns (row-major order).
OUTPUT "" after the inner loop moves printing to a new line.
IGCSE: RANDOM() * 100 gives a real 0..100. AS Level: RAND(101) gives an integer 0..100.
Linear search uses nested loops + a BOOLEAN found flag.
RAND(n) returns integers 0..n-1, so use RAND(K+1) for 0..K inclusive.
Exam tip: Whenever an exam question mentions a “grid”, “matrix”, “board”, “table” or “map”, reach for a 2D array and nested loops. When it asks you to “search for the first occurrence”, use a BOOLEAN found flag and stop scanning as soon as found becomes TRUE.