10 矩阵与图形输出(一)
正在加载视频播放器…
GESP C++ 二级:矩阵与图形输出综合精讲
核心目标:掌握矩阵与图形输出的“万能三步法”,熟练用双重循环+条件判断解决矩形、三角形、对角线、边框、字母矩阵、数字矩阵等常见题型。
外层循环控制行,内层循环控制列;在每个坐标(i, j)判断该输出什么字符;边界条件优先级最高,判断顺序不能乱。
一、矩阵与图形输出的本质
所有控制台图形打印题,都可以抽象为一个二维矩阵的输出问题。每一行字符对应程序中的一个输出序列,核心是建立行索引(i)、列索引(j)与输出字符之间的逻辑关系。
最根本的代码框架是双重循环:
for (int i = 1; i <= n; i++) { // 控制行
for (int j = 1; j <= n; j++) { // 控制列
// 判断这里打印什么字符
}
cout << endl; // 每行结束后换行
}
理解这一点至关重要:外层循环控制纵向的行数,内层循环控制横向的列数。所有的工作,就是根据题目要求,在内层循环中编写条件判断,决定在特定的(i, j)坐标上应该打印什么。
二、图形打印的通用框架
第一步:找边界
判断当前坐标是否处于图形的边界位置。常见的边界条件包括:
- 左右边界:
j == 0 || j == n-1 - 上下边界:
i == 0 || i == n-1 - 中间行:
i == n/2(n为奇数时)
第二步:找规律
判断当前坐标是否处于图形的特殊规律位置。常见规律包括:
- 主对角线:
i == j - 副对角线:
i + j == n-1(从0开始)或i + j == n+1(从1开始) - 行号与列号的关系:如
j <= i形成三角形
第三步:其他情况
以上条件都不满足时,输出填充字符(空格、小写字母等)。
关键原则:边界条件优先级最高,判断顺序不能乱。以“日字矩阵”为例,如果先判断横线行,第一行两边的字符就会变成-而不是|,所以必须先判断边框列。
三、常见图形模板速查
1. 矩形与正方形
实心矩形(n行m列):
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << "*";
}
cout << endl;
}
空心矩形:
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i == 1 || i == n || j == 1 || j == m)
cout << "*";
else
cout << " ";
}
cout << endl;
}
2. 三角形系列
左下实心三角形:内层循环条件 j <= i
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << "*";
}
cout << endl;
}
倒直角三角形:
for (int i = n; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
cout << "*";
}
cout << endl;
}
等腰三角形:先打印空格,再打印星号
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n - i; j++) cout << " "; // 空格
for (int j = 1; j <= 2 * i - 1; j++) cout << "*"; // 星号
cout << endl;
}
3. 对角线系列
主对角线(左上到右下):规律是 i == j
if (i == j) cout << "*";
else cout << "-";
副对角线(右上到左下):规律是 i + j == n - 1(从0开始计数时)
X形:主对角线和副对角线的结合
if (i == j || i + j == n + 1) cout << "*";
else cout << " ";
4. 字母/字符矩阵
[GESP样题 二级] 画正方形 :第i行的第一个字母是字母表中第i个字母(A=1,B=2...超过Z后循环回到A)。
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
char ch = 'A' + (i - 1 + j - 1) % 26;
cout << ch;
}
cout << endl;
}
5. 数字矩阵
[GESP202503 二级] 等差矩阵 :在矩阵的第i行第j列填入整数 i * j,使得每一行与每一列均是等差数列。
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << i * j << " ";
}
cout << endl;
}
数字三角形:
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << j << " ";
}
cout << endl;
}
数字金字塔:
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n - i; j++) cout << " ";
for (int j = 1; j <= i; j++) cout << j;
for (int j = i - 1; j >= 1; j--) cout << j;
cout << endl;
}
6. 蛇形/填充矩阵
[GESP202409 二级] 小杨的 N 字矩阵 :行索引为偶数时从左到右顺序填充,行索引为奇数时从右到左逆序填充。
int num = 1;
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
for (int j = 0; j < n; j++) {
cout << num++ << " ";
}
} else {
for (int j = n - 1; j >= 0; j--) {
// 需要用数组暂存或反向计算
}
}
cout << endl;
}
N字矩阵的奇数行需要从右往左输出,可以用数组暂存后反向输出,或用数学公式直接计算每个位置的值。
四、真题示例精讲
真题1:[GESP202403 二级] 小杨的日字矩阵
题目要求:输入奇数n,输出n×n的“日”字矩阵。最左列和最右列全部输出|,第一行、最后一行、中间一行全部输出-(但两端仍为|),其他位置输出x。
解题代码:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
char ch;
if (j == 0 || j == n - 1) {
ch = '|'; // 第一步:边框列优先
} else if (i == 0 || i == n - 1 || i == n / 2) {
ch = '-'; // 第二步:特殊横线行
} else {
ch = 'x'; // 第三步:其他情况
}
cout << ch;
}
cout << endl;
}
return 0;
}
核心要点:判断顺序不能乱。必须先判断边框列,否则第一行两边的字符会变成-而不是|。
真题2:[GESP202312 二级] 小杨的 H 字矩阵
题目要求:最左列、最右列都是|,中间一行(第(n-1)/2行)的输出都是-,其余所有字符都是小写字母a。
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (j == 0 || j == n - 1)
cout << '|';
else if (i == (n - 1) / 2)
cout << '-';
else
cout << 'a';
}
cout << endl;
}
真题3:[GESP202309 二级] 小杨的 X 字矩阵
题目要求:输出n×n矩阵,主对角线和副对角线位置输出+,其他位置输出-。
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j || i + j == n + 1)
cout << "+";
else
cout << "-";
}
cout << endl;
}
真题4: [GESP202603 二级] 画画
题目要求:n行n列的正方形。四个顶点使用+,除顶点外第1行与第n行使用-,除顶点外第1列与第n列使用|,内部使用*。
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if ((i == 1 || i == n) && (j == 1 || j == n))
cout << "+";
else if (i == 1 || i == n)
cout << "-";
else if (j == 1 || j == n)
cout << "|";
else
cout << "*";
}
cout << endl;
}
关键:顶点判断必须放在最前面,优先级最高。
五、易错点与调试技巧
常见易错点
-
判断顺序错误:边界条件优先级最高。如果先判断横线行,边框列的字符就会被覆盖。
-
行列索引从0还是从1开始:从0开始时,副对角线条件为
i + j == n - 1;从1开始时,为i + j == n + 1。务必根据代码统一。 -
换行位置错误:
cout << endl;必须放在内层循环结束后、外层循环内,否则每打印一个字符就换行。 -
空格处理:题目要求输出空格时,不要漏掉,也不要用其他字符替代。
-
n为偶数的情况:部分题目保证n为奇数(如日字矩阵、H字矩阵),但如果不保证,需要额外处理中间行/列。
-
输出格式:不要添加多余的空格、标点或空行。GESP评测系统要求输出与标准答案完全一致。
-
边界值:注意n=1、n=2等最小情况是否正常输出。
调试技巧
打印坐标辅助调试:在循环内临时输出行号和列号,观察判断逻辑是否覆盖了所有情况。
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cout << "(" << i << "," << j << ")";
}
cout << endl;
}
用表格分析:在纸上画出n×n的表格,逐格标出每个位置应该输出的字符,再归纳i和j的条件关系。
六、速查表
| 图形 | 核心条件 | 说明 |
|---|---|---|
| 实心矩形 | 无条件 | 全部输出同一字符 |
| 空心矩形 | `i==1 | |
| 左下三角形 | j <= i |
内层循环条件 |
| 倒三角形 | j <= n - i + 1 |
|
| 等腰三角形 | 空格 n-i + 星号 2*i-1 |
两个内层循环 |
| 主对角线 | i == j |
从1开始 |
| 副对角线 | i + j == n + 1 |
|
| X形 | `i==j | |
| 日字矩阵 | 边框列` | + 三横线- + 内部x` |
| H字矩阵 | 左右列` | + 中间行- + 其余a` |
| 等差矩阵 | i * j |
直接输出乘积 |
| 字母正方形 | 'A' + (i-1+j-1) % 26 |
循环字母 |
八、总结
矩阵与图形输出是GESP二级编程题的必考题型,解题思路高度固定,核心是双重循环遍历行列,按i/j的关系判断输出字符。
- 所有图形题都是二维矩阵输出问题。
- 外层循环控制行,内层循环控制列。
- 万能三步法:找边界 → 找规律 → 其他情况。
- 边界条件优先级最高,判断顺序不能乱。
- 对角线核心条件:主对角线
i==j,副对角线i+j==n+1(从1开始)。 - 三角形核心条件:
j <= i或j <= n-i+1。 - 换行放在内层循环结束后、外层循环内。
- 输出必须与标准答案完全一致,不多空格、不多换行。
复习建议:先把正方形、三角形、对角线三类基础模板写熟,再练日字矩阵、H字矩阵、X字矩阵等真题,最后挑战N字矩阵、蛇形矩阵等填充类题目。做题时先在纸上画出目标图形,逐格分析i和j的关系,再尝试写代码。