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;
}

关键:顶点判断必须放在最前面,优先级最高。

五、易错点与调试技巧

常见易错点

  1. 判断顺序错误:边界条件优先级最高。如果先判断横线行,边框列的字符就会被覆盖。

  2. 行列索引从0还是从1开始:从0开始时,副对角线条件为 i + j == n - 1;从1开始时,为 i + j == n + 1。务必根据代码统一。

  3. 换行位置错误:cout << endl; 必须放在内层循环结束后、外层循环内,否则每打印一个字符就换行。

  4. 空格处理:题目要求输出空格时,不要漏掉,也不要用其他字符替代。

  5. n为偶数的情况:部分题目保证n为奇数(如日字矩阵、H字矩阵),但如果不保证,需要额外处理中间行/列。

  6. 输出格式:不要添加多余的空格、标点或空行。GESP评测系统要求输出与标准答案完全一致。

  7. 边界值:注意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的关系判断输出字符。

  1. 所有图形题都是二维矩阵输出问题。
  2. 外层循环控制行,内层循环控制列。
  3. 万能三步法:找边界 → 找规律 → 其他情况。
  4. 边界条件优先级最高,判断顺序不能乱。
  5. 对角线核心条件:主对角线 i==j,副对角线 i+j==n+1(从1开始)。
  6. 三角形核心条件:j <= i 或 j <= n-i+1。
  7. 换行放在内层循环结束后、外层循环内。
  8. 输出必须与标准答案完全一致,不多空格、不多换行。

复习建议:先把正方形、三角形、对角线三类基础模板写熟,再练日字矩阵、H字矩阵、X字矩阵等真题,最后挑战N字矩阵、蛇形矩阵等填充类题目。做题时先在纸上画出目标图形,逐格分析i和j的关系,再尝试写代码。