2D Array Neighbors AP CSA
2D Array Neighbors and Diagonals in AP CSA: Complete Guide (2025-2026)
Working with 2D array neighbors is one of the most challenging Unit 4 topics and a consistent FRQ target. Tasks include counting orthogonal neighbors, checking diagonals, processing borders, and building neighbor-based computations. The critical skill: writing correct bounds checks that prevent ArrayIndexOutOfBoundsException on edge and corner cells.
Table of Contents
2D Array Indexing Recap
-
grid[r][c]— row r, column c - Valid rows: 0 to
grid.length - 1 - Valid columns: 0 to
grid[0].length - 1 - Row 0 is top; larger row = further down
Neighbor Directions and Bounds
-
Up:
grid[r-1][c]— requiresr > 0 -
Down:
grid[r+1][c]— requiresr < grid.length - 1 -
Left:
grid[r][c-1]— requiresc > 0 -
Right:
grid[r][c+1]— requiresc < grid[r].length - 1
Offset-array technique for all 8 neighbors:
int[] DR = {-1,-1,-1,0,0,1,1,1};
int[] DC = {-1,0,1,-1,1,-1,0,1};
Loop through both arrays with a single bounds check per iteration.
Code Examples
Example 1: Count Orthogonal Neighbors Equal to a Value
public class GridCount {
public static int countAdjacent(int[][] grid, int r, int c, int val) {
int count = 0;
if (r > 0 && grid[r-1][c] == val) {
count++; // up
}
if (r < grid.length-1 && grid[r+1][c] == val) {
count++; // down
}
if (c > 0 && grid[r][c-1] == val) {
count++; // left
}
if (c < grid[r].length-1 && grid[r][c+1] == val) {
count++; // right
}
return count;
}
public static void main(String[] args) {
int[][] grid = {{0,1,0},{1,0,1},{0,1,0}};
System.out.println(countAdjacent(grid, 1, 1, 1)); // interior
System.out.println(countAdjacent(grid, 0, 0, 1)); // corner
}
}
Example 2: All 8 Neighbors via Offset Arrays
public class GridAll8 {
static int[] DR = {-1,-1,-1,0,0,1,1,1};
static int[] DC = {-1,0,1,-1,1,-1,0,1};
public static int countPositive(int[][] g, int r, int c) {
int cnt = 0;
for (int d = 0; d < DR.length; d++) {
int nr = r + DR[d], nc = c + DC[d];
if (nr >= 0 && nr < g.length && nc >= 0 && nc < g[0].length)
if (g[nr][nc] > 0) {
cnt++;
}
}
return cnt;
}
public static void main(String[] args) {
int[][] g = {{2,0,3},{1,4,0},{0,5,1}};
System.out.println(countPositive(g, 1, 1));
}
}
Example 3: Counting Border Cells
public class BorderCells {
public static int countBorder(int[][] grid) {
int count = 0;
for (int r = 0; r < grid.length; r++)
for (int c = 0; c < grid[r].length; c++)
if (r==0 || c==0 || r==grid.length-1 || c==grid[r].length-1)
count++;
return count;
}
public static void main(String[] args) {
System.out.println("3x3: " + countBorder(new int[3][3]));
System.out.println("4x5: " + countBorder(new int[4][5]));
}
}
Common Pitfalls
Down requires r < grid.length - 1, NOT r < grid.length. The latter allows r+1 = grid.length (AIOOB).
Always bounds-check BEFORE accessing. Java short-circuits &&: if the left side is false, the right is never evaluated, preventing AIOOB.
Left/right changes the COLUMN index; up/down changes the ROW index. Do not swap them.
Corners: 2 orthogonal neighbors. Edges: 3. Interior: 4. Your bounds checks must handle all three automatically.
Check for Understanding
grid[r][c], WHICH expression accesses its left neighbor?grid[r][c]. WHICH condition is missing?if (r > 0 && c > 0 && r < grid.length - 1) {{ ... }}
grid[0][0] have in a 3x3 grid?if (r > 0 && grid[r-1][c]==1) {
count++; // up
}
if (r < grid.length && grid[r+1][c]==1) {
count++; // L2: down
}
if (c > 0 && grid[r][c-1]==1) {
count++; // left
}
if (c < grid[0].length && grid[r][c+1]==1) {
count++; // L4: right
}
public static int diagSum(int[][] g) {{
int total = 0;
for (int r = 0; r < g.length - 1; r++)
for (int c = 0; c < g[r].length - 1; c++)
total += g[r+1][c+1];
return total;
}}
int[][] grid?Frequently Asked Questions
grid.length is the number of rows. grid[0].length is the number of columns. For a rectangular grid they are consistent across all rows.
Use offset arrays: int[] dr = {-1,1,0,0}; int[] dc = {0,0,-1,1}; Then loop through both with one bounds check. This is cleaner and less error-prone.
Yes. Always put the bounds check BEFORE the array access. Java short-circuits: if r > 0 is false, grid[r-1][c] is never evaluated, preventing AIOOB. Never reverse the order.
2n + 2m - 4. For a 5x5: 2*5 + 2*5 - 4 = 16. Subtract 4 to avoid double-counting corners.
Yes. The typical pattern: read from the original grid, write to a NEW result grid of the same size. Never read from and write to the same grid in one pass, or you'll corrupt values mid-computation.
1-on-1 Expert Support
2D array neighbor problems are among the hardest FRQ types. Get targeted practice with an AP CSA instructor whose students achieve a 54% five-rate.
View Tutoring OptionsRelated Topics
Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
Prefer email? Reach me directly at [email protected]