java怎么打印沙漏
- 后端开发
- 2025-08-19
- 5
va打印沙漏需先确定有效符号数,用循环控制每行空格与符号数量,上半部递减、下半部递增实现对称结构
Java中打印沙漏形状是一个经典的编程练习题,它结合了数学计算、循环结构和字符串操作等多种技能,下面将详细介绍如何实现这一功能,包括算法思路、具体步骤以及完整的代码示例。
核心概念解析
所谓“沙漏形状”,是指满足以下条件的图形:
- 每行输出奇数个符号;
- 各行符号中心对齐;
- 相邻两行符号数差2;
- 符号数量先从大到小顺序递减到1,再从小到大顺序递增;
- 首尾行的符号数相等。
当输入为17个星号()时,应形成如下结构:
实现步骤详解
确定最大可用层数n
我们需要找到一个最大的整数n,使得总消耗的符号数不超过给定的N,根据等差数列求和公式,一个完整的沙漏所需的符号总数为4n²−1
(上半部分三角区+下半部分倒置三角区),可以通过求解不等式4k²−1≤N
来获得最大的k值,实际处理中,可以使用数学函数Math.sqrt((N+1)/4)
并向下取整得到初始猜测值,然后逐步验证调整。
计算实际使用的符号总数used
一旦确定了层数n,就可以精确计算出该沙漏实际需要的符号数量:used = 4nn 1
,这代表了上下两个等腰三角形叠加后的总字符数。
分层打印逻辑
整个打印过程分为两部分:上半部分(正立的等腰三角形)和下半部分(倒置的等腰三角形),每一行的打印都需要考虑前导空格的数量和当前行的符号个数。
行类型 | 范围 | 前导空格数 | 当前行符号数 | 说明 |
---|---|---|---|---|
上半部分 | i从n降到1 | n−i | 2i−1 | 随着i减小,宽度逐渐变窄 |
下半部分 | i从2升到n | n−i | 2i−1 | 随着i增大,宽度再次扩展 |
处理边界情况
特别注意中间那一行的特殊处理——它是连接上下两部分的关键节点,此时i=1,对应只有一个中心点,还要确保所有行的居中效果一致,即通过添加适当数量的前导空格实现视觉上的对齐。
Java完整实现代码
以下是符合上述逻辑的Java程序:
import java.util.Scanner; public class PrintHourglass { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); // 读取总符号数 String ch = sc.next(); // 读取要打印的符号 // 计算最大可能的层数n int n = (int) Math.sqrt((N + 1) / 4.0); while (4 n n 1 > N) { n--; } int used = 4 n n 1; // 实际使用的符号数 System.out.println("剩余符号数:" + (N used)); // 打印上半部分(包括中间一行) for (int i = n; i >= 1; i--) { // 打印前导空格 for (int j = 0; j < n i; j++) { System.out.print(" "); } // 打印符号 for (int j = 0; j < 2 i 1; j++) { System.out.print(ch); } System.out.println(); } // 打印下半部分 for (int i = 2; i <= n; i++) { // 打印前导空格 for (int j = 0; j < n i; j++) { System.out.print(" "); } // 打印符号 for (int j = 0; j < 2 i 1; j++) { System.out.print(ch); } System.out.println(); } } }
代码解释
- 输入处理:使用
Scanner
类获取用户输入的两个参数——总符号数N和指定符号ch。 - 层数计算:基于平方根函数初步估算层数n,并通过循环确保不会超出可用符号限制。
- 用量统计:变量
used
存储了构成沙漏所需的全部符号数目,便于后续输出剩余量。 - 上半部分绘制:外层循环控制行数变化,内层第一个循环负责生成左侧空白区域,第二个循环填充相应数量的目标符号。
- 下半部分绘制:类似上半部分的逻辑,但起始值为2以避免重复打印中间行。
- 自动换行:每次完成一行后调用
System.out.println()
实现自动换行。
示例运行结果
若输入为17
,则输出如下:
剩余符号数:0
FAQs
Q1: 如果输入的N不足以构成完整的沙漏怎么办?
A: 程序会自动选择最大的可行层数n,使得4n²−1≤N
成立,未被使用的符号会在最后单独显示其数量,若N=10,则只能构建一个小规模的沙漏,并提示剩余若干符号未被使用。
Q2: 能否修改代码以支持不同的字符作为填充材料?
A: 当然可以!只需更改输入阶段的第二个参数即可,当前的实现已经接受任意单个字符作为填充符,如, 等,只需在运行程序时传入相应的字符即可看到效果