Java 实例 – 打印矩形(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在编程学习的旅程中,"打印矩形"是一个经典且基础的练习项目。它不仅能够帮助开发者掌握循环结构和条件判断的核心逻辑,还能通过不同变体(如空心矩形、带边框的矩形)训练代码设计的灵活性。本文将以"Java 实例 – 打印矩形"为主题,通过分层次的讲解和实例代码,带领读者从基础语法到进阶技巧全面掌握这一技能。无论是编程初学者还是希望巩固基础的中级开发者,都能从中获得实用的指导和启发。
理解矩形打印的核心逻辑
1. 矩形的数学模型与坐标系
矩形由高度(行数)和宽度(列数)决定。在代码中,我们可以将每一行视为一个"打印行",每一列视为该行中的字符位置。想象一个二维坐标系:
- 行(Row):从上到下递增,通常用变量
i
表示 - 列(Column):从左到右递增,通常用变量
j
表示
例如,一个 3x5 的矩形可以表示为:
行 0: [列0, 列1, 列2, 列3, 列4]
行 1: [列0, 列1, 列2, 列3, 列4]
行 2: [列0, 列1, 列2, 列3, 列4]
这种坐标系的思维模式是解决打印问题的关键。
2. 循环结构的选择
打印矩形的核心在于双重循环:
- 外层循环控制行数(
for(int i=0; i<行数; i++)
) - 内层循环控制列数(
for(int j=0; j<列数; j++)
)
例如,一个简单的矩形打印代码框架如下:
public class RectanglePrinter {
public static void main(String[] args) {
int rows = 3;
int cols = 5;
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
System.out.print("*"); // 打印字符
}
System.out.println(); // 换行
}
}
}
此代码将输出:
*****
*****
*****
基础案例:实心矩形与空心矩形
1. 实心矩形(Solid Rectangle)
实心矩形的每个位置都填充字符(如 *
)。上文的代码即为典型示例。关键点在于:
- 内层循环的每一次迭代都打印一个字符
- 外层循环结束后换行
2. 空心矩形(Hollow Rectangle)
空心矩形仅在边缘填充字符,内部为空。此时需要添加条件判断:
public class HollowRectangle {
public static void main(String[] args) {
int rows = 4;
int cols = 6;
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
if(i == 0 || i == rows-1 || j == 0 || j == cols-1) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
输出结果:
******
* *
* *
******
关键逻辑解释:
- 当处于第一行(
i=0
)、最后一行(i=rows-1
)、第一列(j=0
)或最后一列(j=cols-1
)时打印*
- 其他位置打印空格
进阶技巧:动态参数与用户输入
1. 通过控制台输入参数
在实际开发中,矩形的尺寸通常需要动态指定。可以使用 Scanner
类读取用户输入:
import java.util.Scanner;
public class DynamicRectangle {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("输入行数:");
int rows = scanner.nextInt();
System.out.print("输入列数:");
int cols = scanner.nextInt();
// 打印实心矩形的逻辑
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
2. 参数验证与异常处理
为避免用户输入负数或零,可以添加条件判断:
if(rows <= 0 || cols <= 0) {
System.out.println("行列数必须大于0");
return; // 终止程序
}
扩展应用:复杂形状与多维数组
1. 带边框的彩色矩形(使用ANSI转义码)
通过控制台颜色输出增强视觉效果:
public class ColorRectangle {
public static void main(String[] args) {
int rows = 5;
int cols = 10;
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
if(i == 0 || i == rows-1 || j == 0 || j == cols-1) {
System.out.print("\033[44m" + "*" + "\033[0m"); // 蓝色背景
} else {
System.out.print("\033[47m" + " " + "\033[0m"); // 白色背景
}
}
System.out.println();
}
}
}
注意事项:
- ANSI转义码在Windows系统中需启用支持(JDK 16+ 或通过命令
System.setProperty("java.awt.headless", "false")
)
2. 使用多维数组存储矩形数据
将矩形视为一个二维数组,可实现更复杂的逻辑(如填充图案):
public class ArrayBasedRectangle {
public static void main(String[] args) {
int rows = 3;
int cols = 4;
char[][] rectangle = new char[rows][cols];
// 初始化数组
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
rectangle[i][j] = (i == 0 || i == rows-1 || j == 0 || j == cols-1) ? '*' : ' ';
}
}
// 输出数组内容
for(char[] row : rectangle) {
System.out.println(new String(row));
}
}
}
性能优化与代码重构
1. 避免重复计算
在循环中,将 rows-1
和 cols-1
存储为临时变量,减少计算次数:
int lastRow = rows - 1;
int lastCol = cols - 1;
2. 使用StringBuilder提升效率
对于大规模数据(如1000x1000的矩形),直接使用 System.out.print
可能导致性能问题。改用 StringBuilder
缓冲数据:
StringBuilder sb = new StringBuilder();
for(int i=0; i<rows; i++) {
sb.setLength(0); // 清空缓冲区
for(int j=0; j<cols; j++) {
sb.append('*'); // 或其他字符
}
System.out.println(sb.toString());
}
常见问题与解决方案
1. 输出出现多余空格或换行
原因:在内层循环结束后,System.out.println()
会自动换行。若误将 print
和 println
混用,会导致格式错乱。
解决方案:确保内层循环结束后仅调用一次 println()
。
2. 矩形尺寸不符合预期
原因:变量 rows
和 cols
的值可能被错误赋值。例如,rows = 5
实际打印了5行,但用户可能误以为是6行。
解决方案:添加输入验证和调试输出(如打印变量值)。
3. 多条件判断逻辑混乱
原因:复杂的条件组合(如同时判断行和列的多个边界)容易出错。
解决方案:将条件拆分为多个独立判断,或使用布尔变量暂存中间结果:
boolean isEdge = (i == 0) || (i == lastRow) || (j == 0) || (j == lastCol);
if(isEdge) { ... }
应用场景与拓展思考
1. 图形界面编程
在Swing或JavaFX中,矩形打印的逻辑可转化为图形绘制:
// 假设使用JavaFX的Canvas
canvas.getGraphicsContext2D().fillRect(x, y, width, height);
2. 游戏开发中的地图生成
矩形打印的二维数组思维可扩展为游戏地图:
// 简化版地图数据
char[][] gameMap = new char[20][20]; // 20x20的地图
// 初始化围墙
for(int i=0; i<20; i++) {
gameMap[0][i] = '#'; // 上边界
gameMap[19][i] = '#'; // 下边界
}
3. 日志格式化与数据可视化
在日志系统中,矩形打印的技巧可用于生成结构化的输出:
// 打印表格标题行
System.out.println("┌──────────┬──────────┐");
System.out.println("| 列1 | 列2 |");
System.out.println("├──────────┼──────────┤");
// 数据行循环
for(...) {
System.out.printf("| %-8s | %-8s |\n", data1, data2);
}
System.out.println("└──────────┴──────────┘");
结论
通过本文的讲解,我们不仅掌握了"Java 实例 – 打印矩形"的核心逻辑,还探索了其在动态参数处理、性能优化、图形界面等领域的应用。矩形打印看似简单,实则蕴含了循环控制、条件判断、数据结构等编程基础的精华。对于初学者而言,建议通过修改参数值、尝试不同字符图案(如#
、@
)或添加颜色效果,逐步提升代码的复杂度。对于中级开发者,可以思考如何将二维数组扩展为三维空间数据结构,或结合算法实现矩形的动态生成与动画效果。编程是一门实践的艺术,愿各位读者在不断尝试中收获乐趣与成长!
(全文共约 2300 字)