Skip to content

15. 二维数组:矩阵与棋盘

前置学习:一维数组嵌套循环

一维数组像是一排连续的储物柜,只能处理“线”上的数据。 但如果是电影院的座位表、象棋的棋盘、或者是游戏里的迷宫地图,这种拥有“行”和“列”的二维平面数据,我们就必须祭出二维数组了。

1. 什么是二维数组?

你可以把二维数组想象成一张 Excel 表格,或者一个围棋棋盘。

cpp
// 语法:数据类型 数组名[行数][列数];
int map[3][4];

这行代码向电脑申请了一个 3 行 4 列的表格,总共有 $3 \times 4 = 12$ 个格子。

2. 坐标法则:行优先

和一维数组一样,二维数组的“行号”和“列号”也是从 0 开始的! 我们用两个方括号来精确定位一个格子:数组名[行标][列标]

第 0 列第 1 列第 2 列第 3 列
第 0 行map[0][0]map[0][1]map[0][2]map[0][3]
第 1 行map[1][0]map[1][1]map[1][2]map[1][3]
第 2 行map[2][0]map[2][1]map[2][2]map[2][3]

如果要给第 1 行、第 2 列的格子赋值为 99,代码就是:

cpp
map[1][2] = 99;

3. 黄金搭档:嵌套循环遍历

处理二维数组时,必定会用到嵌套循环。外层循环控制走到了哪一“行”,内层循环控制这一行的每一“列”。

经典实战:批量读取一个 $3 \times 3$ 的矩阵,并原样打印输出。

cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    int a[3][3];
    
    // 1. 嵌套循环输入
    for (int i = 0; i < 3; i++) {       // i 代表当前是第几行
        for (int j = 0; j < 3; j++) {   // j 代表当前是第几列
            cin >> a[i][j];
        }
    }
    
    // 2. 嵌套循环输出
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            cout << a[i][j] << " ";
        }
        cout << endl; // 极易忘:每一行打印完后,必须要换行!
    }
    return 0;
}

4. 💀 致命陷阱:行与列的数学直觉错乱

在数学坐标系中,我们习惯用 $(x, y)$ 来表示一个点,其中 $x$ 是横坐标(列),$y$ 是纵坐标(行)。 但在 C++ 的二维数组中,顺序是颠倒的! a[行][列] 相当于数学里的 $(y, x)$。 在做迷宫寻路、地图搜索的算法题时,千万不要把行和列写反,否则会直接越界导致 RE(运行错误)!

5. 动手实践

md
1. 打开左下角的代码沙盒。
2. 声明一个 3 行 3 列的二维数组,利用嵌套循环读入 9 个数字。
3. 挑战:求出这个矩阵的“主对角线”上元素的和(即左上角到右下角那条线,想想对角线上的元素的 `i``j` 有什么共同特征?)
   *(提示:对角线上的元素,它的行号和列号是相等的,比如 a[0][0], a[1][1])*
💻 运行代码

C++ 在线评测沙盒

📥 标准输入 (cin):
📤 终端输出 (cout):