| 学习指南 EN
College Board · cb-cs-a · AP Computer Science A · 2D Arrays / 二维数组 · 阅读约 15 分钟 · 更新于 2026-05-07

二维数组 (2D Arrays) — AP Computer Science A CS A 学习指南

适合谁:AP Computer Science A 参加 AP Computer Science A 的考生。

覆盖内容:二维数组声明、行优先遍历、求和/搜索/翻转等常用操作模式、边界条件处理,以及游戏板、矩阵等实际应用场景。

前置知识:基础 Java 或任何其他过程式语言编程。

关于练习题:下文「练习题」一节的所有题目均为我们按 AP Computer Science A 风格编写的原创题目 (original problems),仅用于教学。它们不是 College Board 真题的复制,措辞、数值或语境可能不同。请把它们当作练手用;评分细则请对照 College Board 官方 mark scheme。


1. 什么是二维数组 (2D Arrays)?

二维数组是存储同类型数据的二维表格结构,本质是「数组的数组」,是AP CS A CED Unit 8的唯一核心考点。它由若干行 (row) 和列 (column) 组成,每个位置的元素 (element) 通过「行索引+列索引」唯一访问,索引默认从0开始计数。二维数组常被用来实现矩阵、游戏棋盘、学生成绩表等需要二维映射的场景,是AP CS A FRQ大题的高频考察载体。

2. 二维数组声明 (2D Array Declaration)

Java中二维数组的声明有三种常用形式,考官特别喜欢考察声明时行列参数的顺序、以及锯齿数组的定义规则:

  1. 指定行列数声明:适用于初始值未定的场景,第一个参数为行数,第二个为列数:
// 声明一个3行4列的整数数组,存储3个班级各4名学生的成绩
int[][] scores = new int[3][4];
  1. 直接初始化声明:适用于已知初始值的场景,大括号嵌套对应每行的元素:
// 声明并初始化3行3列的矩阵
int[][] matrix = {{1,2,3}, {4,5,6}, {7,8,9}};
  1. 锯齿数组 (ragged array) 声明:每行的列数可以不同,仅指定行数,后续单独给每行分配空间:
// 声明3行的锯齿数组,第一行2列,第二行3列,第三行4列
int[][] raggedArr = new int[3][];
raggedArr[0] = new int[2];
raggedArr[1] = new int[3];
raggedArr[2] = new int[4];

3. 行优先遍历 (Row-major Traversal)

行优先遍历是AP CS A要求的标准遍历方式,指先遍历完一行的所有列元素,再进入下一行遍历,和Java二维数组的内存存储顺序一致,遍历效率最高。

标准遍历代码(支持普通数组和锯齿数组):

// 外层循环控制行,i为行索引
for (int i = 0; i < matrix.length; i++) {
 // 内层循环控制列,j为列索引,用matrix[i].length适配锯齿数组的不同列数
 for (int j = 0; j < matrix[i].length; j++) {
 // 访问元素 matrix[i][j]
 System.out.print(matrix[i][j] + " ");
 }
 System.out.println(); // 每行结束换行
}

注意:如果仅需要读取元素不需要修改,可以使用增强for循环,但增强for循环对基本类型的元素是值拷贝,修改不会影响原数组,考官常在此设置陷阱题。

4. 常用操作模式:求和、搜索、翻转

这三类是AP考试中最常出现的二维数组操作模板,要求考生能快速写出无bug的代码:

① 求和

对数组中所有元素累加求和,公式为: 其中为行数,为第行的列数。

② 搜索

查找数组中是否存在目标值,找到后返回对应坐标,否则返回(-1,-1)

public static int[] search(int[][] arr, int target) {
 for (int i = 0; i < arr.length; i++) {
 for (int j = 0; j < arr[i].length; j++) {
 if (arr[i][j] == target) return new int[]{i, j};
 }
 }
 return new int[]{-1, -1};
}

③ 水平翻转

将每行的元素左右颠倒,交换位置jn_i-1-j的元素即可,为第行的列数。

5. 边界条件 (Boundary Conditions)

二维数组的索引必须满足两个条件:,违反则会抛出ArrayIndexOutOfBoundsException,这是选择题和FRQ的高频丢分点。 常见需要判断边界的场景:

  1. 访问数组边缘元素(第一行、最后一行、第一列、最后一列)
  2. 访问元素的上下左右相邻元素(比如扫雷游戏中统计周围地雷数量)

相邻元素访问的边界判断示例:

// 判断位置(i,j)的上方元素是否存在
if (i - 1 >= 0) { int up = arr[i-1][j]; }
// 判断位置(i,j)的右方元素是否存在
if (j + 1 < arr[i].length) { int right = arr[i][j+1]; }

6. 实际应用场景:游戏棋盘、矩阵运算

二维数组的实际应用是FRQ大题的常见出题背景,考生需要快速对应到基础操作:

① 游戏棋盘

比如3x3的井字棋 (Tic-Tac-Toe) 棋盘,用二维数组存储每个格子的状态('X'/'O'/'-'代表空):

char[][] ticTacToe = {{'-','-','-'}, {'-','-','-'}, {'-','-','-'}};

② 矩阵运算

  • 矩阵加法:两个相同大小的矩阵对应位置元素相加,公式为
  • 矩阵转置:将行和列互换,公式为,常用于图像处理、线性代数计算场景。

7. 常见陷阱 (Common Pitfalls)

  1. 错误做法:混淆行和列的索引顺序,把arr[i][j]写成arr[j][i]原因:对「数组的数组」本质理解不深,误以为第一个索引是列。正确做法:记住arr.length返回的是行数,arr[0].length返回的是第一行的列数,访问永远先写行索引再写列索引。
  2. 错误做法:遍历锯齿数组时用固定列数arr[0].length作为内层循环上限。原因:默认所有行的列数相同,忽略锯齿数组的存在。正确做法:内层循环永远用arr[i].length作为当前行的列数上限。
  3. 错误做法:用增强for循环修改基本类型元素的值。原因:对Java的值传递机制不熟悉,以为增强for循环的变量是元素引用。正确做法:需要修改元素时用普通for循环通过索引访问。
  4. 错误做法:访问相邻元素时不做边界判断,导致数组越界。原因:忽略边缘元素没有完整的四个方向邻居。正确做法:每次访问非当前索引位置的元素前,都先判断索引是否在合法范围内。

8. 练习题 (AP Computer Science A 风格)

题1

题干:已知二维数组scores存储了多个班级的学生考试成绩,行数为班级数量,列数为对应班级的学生人数,请编写方法getClassAverage,参数为scores和班级索引classIndex,返回该班级的平均分,结果保留两位小数。 解答

public static double getClassAverage(int[][] scores, int classIndex) {
 int sum = 0;
 int[] classScores = scores[classIndex];
 for (int score : classScores) {
 sum += score;
 }
 // 强制类型转换为double避免整数除法
 return (double) sum / classScores.length;
}

说明:先获取对应班级的一维数组,遍历求和后除以班级人数即可,注意整数除法的陷阱。

题2

题干:给定n行n列的正方形矩阵matrix,请编写方法isSymmetric判断矩阵是否为对称矩阵(即对所有i,j满足matrix[i][j] == matrix[j][i])。 解答

public static boolean isSymmetric(int[][] matrix) {
 int n = matrix.length;
 // 仅遍历上三角区域,避免重复判断
 for (int i = 0; i < n; i++) {
 for (int j = i + 1; j < n; j++) {
 if (matrix[i][j] != matrix[j][i]) {
 return false;
 }
 }
 }
 return true;
}

说明:不需要遍历所有i和j,仅判断上三角区域即可,时间复杂度为,比全遍历效率高一倍。

题3

题干:扫雷游戏中,给定rowcol列的二维数组board,元素为1代表有地雷,0代表无地雷,请编写方法countMine,参数为board、坐标xy,返回该坐标周围8个方向的地雷总数。 解答

public static int countMine(int[][] board, int x, int y) {
 int count = 0;
 // 遍历8个方向的偏移量
 int[][] dirs = {{-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}};
 for (int[] dir : dirs) {
 int nx = x + dir[0];
 int ny = y + dir[1];
 // 边界判断+地雷判断
 if (nx >=0 && nx < board.length && ny >=0 && ny < board[nx].length && board[nx][ny] == 1) {
 count++;
 }
 }
 return count;
}

9. 速查表 (Quick Reference Cheatsheet)

操作 核心规则/代码
二维数组声明 int[][] arr = new int[行数][列数]; 第一个参数为行数
行优先遍历 外层循环控制行:for(int i=0;i<arr.length;i++),内层控制列:for(int j=0;j<arr[i].length;j++)
边界判断 行索引范围:,列索引范围:
矩阵转置 新矩阵newArr[j][i] = oldArr[i][j]
增强for循环 仅用于读取元素,不能修改基本类型元素值
对称矩阵判断 仅遍历上三角区域,判断arr[i][j] == arr[j][i]

10. 接下来怎么学

二维数组是AP CS A Unit 8的核心内容,后续会和ArrayList、递归等知识点结合考察,比如二维网格的DFS/BFS遍历、路径搜索等复杂算法题,也是FRQ大题的固定出题点之一,掌握本章的基础操作和避坑技巧,是攻克后续复杂考点的核心前提。 如果你在练习二维数组相关题目时遇到任何问题,随时可以到小欧提问,我们会为你提供针对性的讲解和练习指导。

← 返回章节主页

某道题卡住了?
拍照或粘贴题目 — 小欧(我们的 AI 学习助手)会一步步讲解并配示意图。
免费试用小欧 →