☰
蓝桥杯六芒星打印题:从坐标规律到循环实现
2026/10/4 14:03:40 网站建设 项目流程

蓝桥杯的“打印图形”题,近几届几乎隔年就出一次。今天聊其中一道很有代表性的——六芒星。题目本身不复杂,一般形式是:输入一个整数 n,用*号打出一个由两个三角形叠起来的六芒星图案。很多人第一次看到它,容易一头扎进循环里反复改,最后图形歪了也不知道错在哪。其实这类题有个固定套路:先把图案当二维坐标网格来看,再找行列之间的偏移规律,最后用两层循环把点打出来。

我当年备赛时,第一次做这种题也是硬凑空格,凑到头晕。后来总结出一套自己的方法:不急着写代码,先在稿纸上把图形画出来,把每一行的星号位置标成坐标,找相邻行之间的关系。一旦找到“偏移量”的表达式,代码就是水到渠成的事。这篇文章我会从题目拆解、规律推导、代码实现到常见坑位,完整讲一遍六芒星打印题的解法。无论你用的是 Java、C++ 还是 Python,核心思路都一样。

1. 题目理解与整体设计思路

1.1 蓝桥杯打印图形题到底在考什么

蓝桥杯的打印图形题,表面上是“输出一个由字符组成的形状”,实际上考的是两层能力:第一层是坐标抽象,第二层是循环控制。

坐标抽象的意思是把图案放到一个虚拟的二维坐标系里。输出区域可以看成一张网格纸,每个字符占据一个格子。你要做的,就是决定哪些格子放*,哪些格子放空格。不要一上来就想着“我要画一个六芒星”,而要想“对于第 row 行第 col 列的格子,我该怎么判断它是否该显示星号”。

循环控制则是把上面的判断翻译成代码。一般套路是用外层循环控制行,内层循环控制列。关键点在于:内层循环的边界不一定是固定的,可能要根据行数变化;也可能要提前终止,避免输出多余的行尾空格。

我见过很多同学在这类题目上翻车,不是因为不会写循环,而是因为图没画明白就开始敲代码。你在脑子里觉得图形是“一个三角形加一个倒三角形”,但代码里没有“三角形”这个概念,只有行号、列号、边界条件。所以第一步永远是先把图形落到坐标上。

1.2 典型题设与样例规律

为了防止题目定义不清,我先给出一种最常见的题设,后文全部围绕它展开:

输入一个正整数 n,输出一个高度为2n-1、宽度为2n-1的六芒星轮廓。当 n=4 时,输出如下:

* * * * * * * * * * * *

这个图形你要仔细看几秒。它其实不是传统的“六角星”,而是两个三角形骨架上下对拼:上半部分是一个正三角形的两条斜边,下半部分是一个倒三角形的两条斜边。竞赛题里有时把这种简化画法直接叫六芒星,大家不必在几何定义上纠结,做题时以题目给出的样例为准。

我们先只看上半部分,也就是前 4 行:

* * * * * * *

以 0 开头编号行号,第 0 行星号在中间;第 1 行有两个星号,分别向左、向右各移一格;第 2 行继续向两边扩展;第 3 行扩展到了最左和最右。所以上半部分是一个“逐渐张开”的过程。

再看下半部分,从第 4 行开始:

* * * * *

这是上半部分的镜像,也就是“逐渐收拢”的过程。

所以整个规律其实非常清晰:每一行最多只有两个星号,它们关于中心列对称。距离中心越远,两个星号间隔越大。我们可以把两个星号的位置分别称为左边界left和右边界right,那么它们满足:

left = mid - d right = mid + d

其中mid = n - 1是中心列的编号,d是当前行距离中心行的偏移量。

1.3 用表格验证规律

为了让你更直观地看到规律,我把 n=4 时每一行的关键数据列成表格:

行号 row对称偏移 dleftright星号位置
0033中心一个
1124第2、4列
2215第1、5列
3306第0、6列
4215第1、5列
5124第2、4列
6033中心一个

你发现没有,d的取值是先增后减,从 0 到n-1,再回到 0。这就是图形上下对称的原因。只要能把d和行号row的关系找出来,这道题就解决了一大半。

2. 核心细节解析:从坐标规律到循环实现

2.1 建立坐标系:把图形当成二维网格

我们用一个行号row和一个列号col来定位每一个字符。行的范围是0到2n-2,列的范围理论上也是0到2n-2,但实际输出时,每一行的最后一个有效字符位置是right,不需要输出后面的空格。

中心列mid = n - 1代表图形的对称轴。如果某一行的星号偏移量为d,那么左星号在mid - d,右星号在mid + d。

这里要注意:当d = 0时,左星号和右星号是同一个位置,所以这一行只会出现一个*,而不是两个。写代码时如果同时判断col == left || col == right,同一个位置也只会输出一次,不会重复,因为col在循环里只会经过一次。

你可能会问:为什么列号范围是0到2n-2,而不是1到2n-1?都可以,看你习惯。蓝桥杯的判题系统只关心输出字符内容,不关心你是从 0 开始还是从 1 开始。但从 0 开始有一个好处:mid正好是n-1,偏移后的mid - d和mid + d不会出现负数。

2.2 偏移量 d 的推导:上下对称是关键

图形的高度是2n-1,中心行是row = n-1。在中心行以上,或者说row <= n-1时,行越往下,偏移量越大,偏移量就等于当前行号:

d = row

在中心行以下,行越往下,偏移量越小。从最底部往回看,底部第0行(也就是实际最后一个字符行)偏移量为0,往上第1行偏移量为1。所以如果当前行号是row,距离底部还有(2n-2 - row)行,那么偏移量就是:

d = (2n - 2) - row

用条件表达式合并一下,就是:

d = row <= n-1 ? row : (2n - 2) - row

你可以代入表格验证一下:当row=5时,d=2;当row=6时,d=0,没问题。

这个公式是整个代码最核心的部分。很多人的代码写错,就是因为在处理下半部分时把对称关系搞反了。记住一句话:上半部分看“已经走了多少行”,下半部分看“还剩多少行到底部”。

2.3 空格与行尾的处理细节

代码里输出空格也有讲究。我推荐的做法是:内层循环从col = 0一直走到col = right,遇到left或right就输出*,其他位置输出空格。这样循环到right就停止,天然不会在行尾留下一串空格。

如果你用整行宽度2n-1来循环,然后最后统一trim,技术上也可以,但不是所有在线评测系统都能接受你的字符串尾部处理方式。有些系统用System.out.print逐字符输出,多余的尾随空格可能会被当成答案的一部分,导致格式错误。

另外还有一个容易忽略的点:当n=1时,图形只有一行一个*。按照公式,h=1,mid=0,row=0,d=0,left=right=0,循环从 0 到 0 输出一个*,没有问题。所以这道题不需要单独特判n=1,公式天然覆盖了边界情况。

3. 实操过程与代码实现

3.1 Java 实现:蓝桥杯最常用的语言

蓝桥杯的 Java 组要求主类名为Main,并且不能带package。这道题完整代码可以参考下面这样:

import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int h = 2 * n - 1; int mid = n - 1; for (int row = 0; row < h; row++) { int d = row <= mid ? row : h - 1 - row; int left = mid - d; int right = mid + d; StringBuilder sb = new StringBuilder(); for (int col = 0; col <= right; col++) { if (col == left || col == right) { sb.append('*'); } else { sb.append(' '); } } System.out.println(sb.toString()); } } }

这里用StringBuilder是为了减少频繁的System.out.print调用。蓝桥杯的输入规模通常不大,直接print也能过,但养成每次输出整行的习惯,对后续做大矩阵题目有好处。

代码里d = row <= mid ? row : h - 1 - row和前面的公式等价。h-1-row就是(2n-2)-row。你可以看到,整个实现把图形拆成“行号到偏移量”的映射,剩下的就是简单的列循环。

3.2 C++ 和 Python 的对照实现

C++ 版本的思路完全一样,只是语法不同:

#include <iostream> using namespace std; int main() { int n; cin >> n; int h = 2 * n - 1; int mid = n - 1; for (int row = 0; row < h; row++) { int d = row <= mid ? row : h - 1 - row; int left = mid - d; int right = mid + d; for (int col = 0; col <= right; col++) { if (col == left || col == right) { cout << '*'; } else { cout << ' '; } } cout << endl; } return 0; }

Python 版本用列表保存每一行字符,最后再join,效率也不错:

n = int(input()) h = 2 * n - 1 mid = n - 1 for row in range(h): d = row if row <= mid else h - 1 - row left = mid - d right = mid + d line = [] for col in range(right + 1): if col == left or col == right: line.append('*') else: line.append(' ') print(''.join(line))

这三种语言的解题逻辑完全一致,区别只在 IO 和字符串拼接方式。比赛时你用最熟练的语言写就行,关键是脑子里的规律不变。

3.3 如何快速测试自己的输出

写完代码别急着交,先用几个小 n 测试。n=2 时输出应该是:

* * * *

n=3 时输出应该是:

* * * * * * * *

如果你看到中间行是最宽的那一行,而且上下完全对称,基本就对了。也可以用眼睛目测:把输出保存成 txt 文件,用文本编辑器打开,观察每一行前面空格和*的排列是否呈漂亮的三角形骨架。

我在本地测试时,会额外写一个简单脚本,把输出中的空格替换成点号再来检查:

...* ..*.* .*...* *.....* .*...* ..*.* ...*

这样更容易看出空格的数量是否均匀,特别是在终端里空格显示不明显的时候。

4. 常见问题与排查技巧

4.1 最容易踩的五个坑

我把实际做题时容易踩的坑整理成表格,方便你对照排查:

问题原因解决方法
图形左右不对称left和right公式写反检查left = mid - d和right = mid + d
下半部分偏移方向反了中心行以下的d用成了row用h - 1 - row,即“离底部还有多少行”
中间行多了一个星号没有处理left == right的情况用 `
行尾有一堆空格内层循环跑到整行宽度h循环上限改为right,写到右星号就停
图形整体偏左或偏右mid计算错误确认mid = n - 1,不是n也不是(h-1)/2

很多同学会在中间行多输出一个*,是因为他们用if (col == left) ... if (col == right) ...两个独立判断,当left == right时同一个位置输出两次。实际如果用else if或||,就不会有这个问题。

4.2 用对称性自查代码

打印图形题有一个天然优势:结果可以自查。只要你的代码写了两种对称,就应该在输出中体现出来。

第一种对称是左右对称:每一行最左侧星号到中心列的距离,等于最右侧星号到中心列的距离。第二种对称是上下对称:第i行和第h-1-i行完全相同。你可以在代码里临时加一个断言,把每一行存入数组,然后检查这两个性质。

如果发现上下不对称,问题基本出在d的表达式上。你可以打印出每一行的row, d, left, right,对照表格数据排查。

4.3 蓝桥杯 OJ 的提交细节

如果你是在蓝桥杯系统里做题,还有一些细节要注意:

Java 提交时,类名必须是Main,不要写public class Main以外的类名。C++ 提交时,确保使用using namespace std;或者写全std::cin、std::cout。Python 提交时不需要额外的装饰器,直接读输入即可。

输入可能包含多组数据。有的题目说“输入一个正整数 n”,那就只读一个;如果题目说“多组输入”,你就需要写while (cin >> n)或者while (sc.hasNext())。具体以题目要求为准。今天讨论的核心逻辑不依赖这个,拿一组数据也能跑通。

还有一点:蓝桥杯的评测环境里,输出的空格会被原样比较。所以千万不要用println输出一整行后统一trim再打印,那样会把行首空格也删掉,图形直接歪了。正确的做法是在构建每一行时就精确控制字符。

5. 进阶思路:从六芒星到复杂图形

5.1 实心六芒星的扩展写法

如果你把题目要求改成“实心”而不是轮廓,只需要把内层循环的条件改一下:

for (int col = 0; col <= right; col++) { if (col >= left && col <= right) { sb.append('*'); } else { sb.append(' '); } }

这样每一行从左边界到右边界全部填充*,最终会形成一个实心的菱形/沙漏形。很多题目会在这个基础上继续变,比如要求分成上下两个三角形,中间留一条空格带,或者要求用数字来打印。

实心写法和轮廓写法的区别,本质上就是“判断单个点”还是“判断区间”。轮廓写法判断两个边界点,实心写法判断边界之间的连续区间。解题的坐标系和偏移量完全不变。

5.2 碰到真正的“几何六芒星”怎么办

有时候题目里的图案不是这种沙漏形,而是几何学意义上的六角星,也就是两个等边三角形中心重叠、旋转 180 度后的效果。这种图形用上面的行列偏移公式也能做,但公式会复杂很多,需要区分 12 条边。

我的建议是,做题时不要死记公式。你可以在稿纸上把外轮廓的关键点坐标标出来,然后用“逐点判断”的方式:枚举画布上的每一个点,判断它是否落在六芒星轮廓上。这个方法虽然时间复杂度高一点,但在n不大的情况下完全够用,而且逻辑不容易出错。

蓝桥杯这类题目通常n不会超过 20,所以不要担心性能。追求最优解之前,先保证自己能稳定拿到分数。

5.3 相似的打印图形题都可以用同一套路

除了六芒星,蓝桥杯还考过“打印大 X”“打印十字图”“打印菱形”等题目。它们都有一个共同点:图形关于中心行和中心列对称。所以解题步骤可以通用:

  1. 算总行数和总列数。
  2. 找到中心行、中心列。
  3. 对每一行,用“偏移量”描述星号位置的范围。
  4. 写两层循环输出。

我曾经遇到一个打印“十字图”的填空题,当时就是靠这个套路反推代码填空的。所以这篇文章讲的不只是六芒星一道题,而是一类“对称图形打印题”的通用方法论。

我自己在实际操作中还有一个小习惯:先用纸笔画一个n=4的网格,在每一个非空格位置写上它的行号和列号。这个过程看起来很基础,但能帮你发现很多隐性问题。尤其是当图形不是单纯“距离中心越远越宽”时,坐标标号远比空想可靠。如果你能把六芒星的规律吃透,再去做其他打印图形题,会发现世界一下子清晰了很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询