202603-画画(luogu-B4498)

202603-画画(luogu-B4498)

2026年3月,GESP二级真题,考察双重循环在控制台图形打印中的应用,难度★★☆☆☆。洛谷难度等级:入门

B4498 [GESP202603 二级] 画画

题目要求

题目描述

输入一个正整数 nn,你需要绘制一个 nnnn 列的正方形,绘制规则如下:

  • 正方形的四个顶点使用 + 绘制;
  • 除顶点外,第 11 行与第 nn 行使用 - 绘制;
  • 除顶点外,第 11 列与第 nn 列使用 | 绘制;
  • 正方形内部使用 * 绘制。

输入格式

一行,一个正整数 nn

输出格式

输出共 nn 行,表示对应的正方形。

输入输出样例 #1

输入 #1

5

输出 #1

+---+
|***|
|***|
|***|
+---+

说明/提示

数据范围

保证 3n1003 \leq n \leq 100


题目分析

这道题目是经典的控制台图形打印问题。在 GESP 二级中,双重循环是必考核心知识点,而图形打印是检验学生对双重循环行列坐标(i,ji, j 变量)控制能力最直接的方式。

我们可以把这个 n×nn \times n 的正方形看成一个矩阵。外层循环控制行(一般用变量 i,从 1 到 nn),内层循环控制列(一般用变量 j,也是从 1 到 nn)。

对于矩阵中的每一个位置 (i,j)(i, j),我们需要根据它所在的行和列的特征,判断应该输出什么字符。题目规则非常清晰,我们可以按以下优先级进行判断:

  1. 判断顶点: 顶点位于四个角上。即行等于 1 或 nn并且 列也等于 1 或 nn

    • 左上角:i == 1 && j == 1
    • 右上角:i == 1 && j == n
    • 左下角:i == n && j == 1
    • 右下角:i == n && j == n
    • 综合起来,可以写为:(i == 1 || i == n) && (j == 1 || j == n)。属于这种情况的,打印 +
  2. 判断上下边框(除顶点外): 第一行或第 nn 行。在前一步已经排除了顶点的情况下,只要 i == 1 或者 i == n,就打印 -

  3. 判断左右边框(除顶点外): 第一列或第 nn 列。同样在排除了顶点的情况下,只要 j == 1 或者 j == n,就打印 |

  4. 内部区域: 既不是顶点,也不是上下边界,也不是左右边界的区域,统统打印 *

使用经典的 if-else if-else 结构即可完美覆盖这几种互斥的情况。


示例代码

标准双重循环解法

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

代码解析小贴士

  1. 逻辑顺序很重要:if-else if 结构中,先判断条件最苛刻(最特殊)的,再判断泛化的条件。在这道题里,顶点是最特殊的元素,它既属于第一、NN行,又属于第一、NN列,必须优先用 if 判断并拦截掉。如果在最开始先判断 i == 1 画横线,那么这行两端的十字架会被错误地画成横线,从而导致输出错误。
  2. 坐标体系: 初学者容易搞混控制台里的“坐标系”和数学里的平面直角坐标系(笛卡尔坐标系)。在编程画图时,屏幕的最左上角才是真正的原点 (1, 1)。行变量 i 控制 yy 轴方向向下增长,列变量 j 控制 xx 轴方向向右增长。每次循环结束后记得显式输出一个换行std::cout << std::endl 或者 \n)。

本文由coderli.com原创,按照CC BY-NC-SA 4.0 进行授权

所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code

luogu-”系列题目可在 洛谷题库 在线评测。

bcqm-”系列题目可在 编程启蒙题库 在线评测。

GESP/CSP认证交流QQ群: 688906745

GESP/CSP 认证学习微信公众号
GESP/CSP 认证学习微信公众号
最后更新于