【GESP】C++二级真题 luogu-B4498, [GESP202603 二级] 画画
2026年3月,GESP二级真题,考察双重循环在控制台图形打印中的应用,难度★★☆☆☆。洛谷难度等级:入门。
B4498 [GESP202603 二级] 画画
题目要求
题目描述
输入一个正整数 $n$,你需要绘制一个 $n$ 行 $n$ 列的正方形,绘制规则如下:
- 正方形的四个顶点使用
+绘制; - 除顶点外,第 $1$ 行与第 $n$ 行使用
-绘制; - 除顶点外,第 $1$ 列与第 $n$ 列使用
|绘制; - 正方形内部使用
*绘制。
输入格式
一行,一个正整数 $n$。
输出格式
输出共 $n$ 行,表示对应的正方形。
输入输出样例 #1
输入 #1
1
5
输出 #1
1
2
3
4
5
+---+
|***|
|***|
|***|
+---+
说明/提示
数据范围
保证 $3 \leq n \leq 100$。
题目分析
这道题目是经典的控制台图形打印问题。在 GESP 二级中,双重循环是必考核心知识点,而图形打印是检验学生对双重循环行列坐标($i, j$ 变量)控制能力最直接的方式。
我们可以把这个 $n \times n$ 的正方形看成一个矩阵。外层循环控制行(一般用变量 i,从 1 到 $n$),内层循环控制列(一般用变量 j,也是从 1 到 $n$)。
对于矩阵中的每一个位置 $(i, j)$,我们需要根据它所在的行和列的特征,判断应该输出什么字符。题目规则非常清晰,我们可以按以下优先级进行判断:
- 判断顶点: 顶点位于四个角上。即行等于 1 或 $n$,并且 列也等于 1 或 $n$。
- 左上角:
i == 1 && j == 1 - 右上角:
i == 1 && j == n - 左下角:
i == n && j == 1 - 右下角:
i == n && j == n - 综合起来,可以写为:
(i == 1 || i == n) && (j == 1 || j == n)。属于这种情况的,打印+。
- 左上角:
判断上下边框(除顶点外): 第一行或第 $n$ 行。在前一步已经排除了顶点的情况下,只要
i == 1或者i == n,就打印-。判断左右边框(除顶点外): 第一列或第 $n$ 列。同样在排除了顶点的情况下,只要
j == 1或者j == n,就打印|。- 内部区域: 既不是顶点,也不是上下边界,也不是左右边界的区域,统统打印
*。
使用经典的 if-else if-else 结构即可完美覆盖这几种互斥的情况。
示例代码
标准双重循环解法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
int main() {
int n;
std::cin >> n;
// 外层循环控制行,i 从 1 到 n
for (int i = 1; i <= n; i++) {
// 内层循环控制列,j 从 1 到 n
for (int j = 1; j <= n; j++) {
// 规则 1:判断是否是四个顶点
// 行是第1行或第n行,同时列是第1列或第n列
if ((i == 1 || i == n) && (j == 1 || j == n)) {
std::cout << "+";
}
// 规则 2:判断是否是上下边缘(排除顶点后)
// 如果是第1行或者第n行,打印 '-'
else if (i == 1 || i == n) {
std::cout << "-";
}
// 规则 3:判断是否是左右边缘(排除顶点后)
// 如果是第1列或者第n列,打印 '|'
else if (j == 1 || j == n) {
std::cout << "|";
}
// 规则 4:正方形内部区域
// 其他所有情况,打印 '*'
else {
std::cout << "*";
}
} // 结束当前行的打印
// 这一行的内容全部横向打印完毕,输出换行符,准备打印下一行
std::cout << std::endl;
}
return 0;
}
代码解析小贴士
- 逻辑顺序很重要: 在
if-else if结构中,先判断条件最苛刻(最特殊)的,再判断泛化的条件。在这道题里,顶点是最特殊的元素,它既属于第一、$N$行,又属于第一、$N$列,必须优先用if判断并拦截掉。如果在最开始先判断i == 1画横线,那么这行两端的十字架会被错误地画成横线,从而导致输出错误。 - 坐标体系: 初学者容易搞混控制台里的“坐标系”和数学里的平面直角坐标系(笛卡尔坐标系)。在编程画图时,屏幕的最左上角才是真正的原点
(1, 1)。行变量i控制 $y$ 轴方向向下增长,列变量j控制 $x$ 轴方向向右增长。每次循环结束后记得显式输出一个换行(std::cout << std::endl或者\n)。
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
GESP 学习专题站:GESP WIKI
“luogu-”系列题目可在洛谷题库进行在线评测。
“bcqm-”系列题目可在编程启蒙题库进行在线评测。
欢迎加入:Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答
欢迎加入:C++ GESP/CSP认证学习QQ频道,考试资源总结汇总
欢迎加入:C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助
