From the free course AP Computer Science A on Lykke
4.11 2D Array Creation and Access
Key concepts: Creating a correctly sized 2D array of integers · Assigning a 2D array to the instance variable `puzzle` · Traversing a 2D array with valid row and column bounds · Accessing individual 2D array elements · Generating uniform random integers in the range [1, 9] · Updating each visited 2D array element · Avoiding out-of-bounds errors · Handling neighboring row and column locations
A two-dimensional array is a grid in which every value is located by two indices: a row index and a column index. In Java, puzzle[row][col] means “go to row row, then select column col within that row.”
4.11 2D Array Creation and Access
A two-dimensional array is a grid in which every value is located by two indices: a row index and a column index. In Java, puzzle[row][col] means “go to row row, then select column col within that row.”
The grid model: rows first, columns second
Imagine a puzzle board with $3$ rows and $4$ columns:
Column 0 |
Column 1 |
Column 2 |
Column 3 |
|
|---|---|---|---|---|
Row 0 |
puzzle[0][0] |
puzzle[0][1] |
puzzle[0][2] |
puzzle[0][3] |
Row 1 |
puzzle[1][0] |
puzzle[1][1] |
puzzle[1][2] |
puzzle[1][3] |
Row 2 |
puzzle[2][0] |
puzzle[2][1] |
puzzle[2][2] |
puzzle[2][3] |
The array has puzzle.length rows. The number of columns in a rectangular array is puzzle[0].length. The highest valid index is always one less than the array’s length; an array with length n has n valid positions indexed from 0 through n - 1.
Constructing and assigning the array
To create a correctly sized two-dimensional int array, use new int[rows][columns]. If puzzle is an instance variable, the constructor must assign the new array to this.puzzle—or simply puzzle when no local variable has the same name.
public class SumOrSameGame {
private int[][] puzzle;
public SumOrSameGame(int rows, int columns) {
puzzle = new int[rows][columns];
}
}
This statement changes the object’s actual puzzle field. A common error is writing int[][] puzzle = new int[rows][columns]; inside the constructor. That declaration creates a new local variable, leaving the instance variable unchanged.
Misconception check: Creating an array and assigning it to a local variable is not the same as updating the object’s instance variable.
Filling every cell with a random integer
A nested loop visits each cell: the outer loop controls rows, and the inner loop controls columns. The expression 1 + (int)(Math.random() * 9) produces a uniform random integer from $1$ through $9$ inclusive.
for (int row = 0; row < puzzle.length; row++) {
for (int col = 0; col < puzzle[row].length; col++) {
puzzle[row][col] = 1 + (int)(Math.random() * 9);
}
}
Why does the random expression work? Math.random() is at least $0.0$ and less than $1.0$. Multiplying by $9$ gives a value in $[0, 9)$; casting produces one of the integers $0$ through $8$, and adding $1$ shifts the result to $1$ through $9$.
The assignment must target the visited element: puzzle[row][col] = .... Merely printing the generated value, returning it, or assigning one random value outside the loops does not update every cell. Likewise, generating one value before the loops and reusing it would give every visited element the same value when distinct assignments are required.
Bounds are a safety fence
Every access must use valid row and column indices. A loop that continues while row <= puzzle.length is incorrect because puzzle.length itself is not a valid row index; the condition must be row < puzzle.length.
When the number of columns can vary by row, use puzzle[row].length rather than assuming every row has the same width. This is especially important because Java two-dimensional arrays are arrays of row arrays.
Neighbor access requires an additional check before the access occurs:
if (row + 1 < grid.length &&
col + 1 < grid[row].length) {
int below = grid[row + 1][col];
int right = grid[row][col + 1];
// Both neighboring accesses are now valid.
}
The checks use <, not >: row + 1 is valid only when it is less than the number of rows. Checking after evaluating grid[row + 1][col] is too late—the exception has already occurred.
Boundary rule: Before accessing
grid[r][c], verify0 <= r < grid.lengthand0 <= c < grid[r].length.
Worked example: initialize puzzle
Suppose a constructor must build a puzzle with rows rows and columns columns, then fill every cell independently. The complete sequence is: construct the instance variable, visit valid coordinates, generate a value, and store that value in the current cell.
public SumOrSameGame(int rows, int columns) {
puzzle = new int[rows][columns];
for (int row = 0; row < puzzle.length; row++) {
for (int col = 0; col < puzzle[row].length; col++) {
puzzle[row][col] =
1 + (int)(Math.random() * 9);
}
}
}
For a $2 \times 3$ puzzle, the loops access exactly six coordinates: rows $0$ and $1`, and columns $0$, $1$, and $2$. Each coordinate is accessed once and receives its own generated value.
Retrieval check
A puzzle has puzzle.length == 5 and puzzle[0].length == 7. Is puzzle[5][6] valid? No: row index 5 is outside the valid range $0$ through $4$, even though column index 6 is valid. Which statement updates a cell rather than merely displaying a value? puzzle[row][col] = 1 + (int)(Math.random() * 9);.

Source Materials
- AP Computer Science A Course and Exam Description
- AP Computer Science A Course and Exam Description Clarifications and Corrections
- AP Computer Science A Course Overview
- AP Computer Science A Course at a Glance
- AP Computer Science A Course at a Glance Poster
- Adopt AP Computer Science A
- AP Computer Science A
- AP Computer Science A