打印菱形
最近跟着学校的老师再重学Java,又遇到一个十分熟悉的题目:要求在控制台打印出如图所示的菱形。但是都大四了,至少要能实现根据用户的输入,来确定打印菱形的行数吧?
看到题目的第一眼就知道是用for循环来做,关键在于循环停止的条件。依稀记得以前做这题时是分为上下两部分来分别打印,同时用for循环打印每一行的字符时,嵌套两个循环来打印制表符(\t)和星型字符(*)。
有了初步的思路后,就要靠找规律来得出循环条件。
首先是打印菱形的上半部分。因为菱形是奇数行,所以暂且把第三行归为上半部分。菱形一共有5行,上半部分的行数3就可以等于(5+1)/2;依此类推,若有x行,则为(x+1)/2。为方便计算,若用户输入的行数为偶数需要进行转换。
1.进行奇偶判断
/**
* 奇偶判断
*
* @param x
* @return false为偶,true为奇
*/
public static boolean determineOddOrEven(int x) {
boolean flag;
if (x % 2 == 0) {
flag = false;
} else {
flag = true;
}
return flag;
}
2.计算菱形上半部分的行数
int i = 0; // 菱形上半部分的行数
/*
* 调用determineOddOrEven(x)方法,判断输入的值为奇还是偶,
* 由于菱形总行数应为奇数,故打印上半部分时为:(行数+1)/2
*/
if (!determineOddOrEven(x)) {
i = x / 2;
System.out.println("你输入的数为偶数,程序已将其转换为小1的奇数");
} else {
i = (x + 1) / 2;
}
接着是打印用来空位的制表符,从上半部分的图形可以看出,第一行空了2位,第二行空了1位,第三行空了0位,不难得出空位数是3-line(line为该行的行数,从1开始计数);依此类推,若菱形有x行,那么上半部分每行的空位数应为(x+1)/2-line,即i-line。
下面就要打印每行的星型字符(*),星型字符的个数为1、3、5,易得其个数为首项是1,公差是2的等差数列,即*的个数为(1+2*(line-1) => 2*line-1。
/*
* 逐行打印菱形上半部分,以5行的菱形为例 上半部分有3行,即i=(总行数+1)/2
*/
for (int line = 1; line <= i; line++) {
// 打印制表符,以上半部分为例,可见第一行有2个空位(3-1),
// 第二行有1个(3-2),第三行有0个(3-3),
// 可得上半部分每行的空位数为(i-line),line为该行的行数
for (int n = 0; n < i - line; n++) {
System.out.print("\t");
}
// 打印*,不难看出每行*的个数为为1、3、5,易得
// 每行*的个数为((2*line)-1),line为该行的行数
for (int n = 0; n < 2 * line - 1; n++) { // 打印字符
System.out.print("*\t");
}
System.out.println();
}
打印完菱形的上半部分还有下半部分需要打印,首先要算的还是下半部分的行数。因为共有x行,上半部分已经打印了i行,所以下半部分为(x-i),又因为i=(x+1)/2 => x=2*i-1,所以这里的(x-i)与(i-1)等价。
接着还是要打印制表符,可以看出下半部分的第1行有1个空位,第2行有2个,故其个数可表现为首项为1,公差为1,项数为其所在行行数的等差数列,即1+1*(n-1) => n。
下面打印星型字符*,易得其个数为首项为(x-2),公差为-2的等差数列,即(x-2)+(-2)*(n-1) => x-2n。
// 逐行打印菱形下半部分,下半部分共有i-1行
for (int n = 1; n <= i - 1; n++) {
// 打印制表符
// 与上半部分相反,下半部分每行的空位成递增
// 且与该行在下半部分的行数相等
for (int k = 0; k < n; k++) {
System.out.print("\t");
}
// 打印*,下半部分的*个数,仍为奇数,却成递减
// 该处的2*(i-n)-1与x-2*n等价
// x-2*n即菱形左右两侧各少了m个,m又与从下半部分看的行数n相等,故还剩x-2*n个
// x-2*n亦可视为首项为(x-2),公差为-2的等差数列
for (int k = 0; k < 2 * (i - n) - 1; k++) {
System.out.print("*\t"); // 打印字符
}
System.out.println();
}
至此,整个菱形都打印出来了,下面贴上完整的代码。
package day01;
import java.util.Scanner;
public class Work03 {
/**
* 奇偶判断
*
* @param x
* @return false为偶,true为奇
*/
public static boolean determineOddOrEven(int x) {
boolean flag;
if (x % 2 == 0) {
flag = false;
} else {
flag = true;
}
return flag;
}
/**
* 打印菱形
*/
public static void printRhombus() {
System.out.println("请输入你要打印菱形的行数(请输入奇数):");
Scanner scanner = new Scanner(System.in);// 实例化Scanner,用于接收键盘输入
int x = scanner.nextInt(); // 获取输入的行数值
int i = 0; // 菱形上半部分的行数
/*
* 调用determineOddOrEven(x)方法,判断输入的值为奇还是偶, 由于菱形总行数应为奇数,故打印上半部分时为:(行数+1)/2
*/
if (!determineOddOrEven(x)) {
i = x / 2;
System.out.println("你输入的数为偶数,程序已将其转换为小1的奇数");
} else {
i = (x + 1) / 2;
}
/*
* 逐行打印菱形上半部分,以5行的菱形为例 上半部分有3行,即i=(总行数+1)/2
*/
for (int line = 1; line <= i; line++) {
// 打印制表符,以上半部分为例,可见第一行有2个空位(3-1),
// 第二行有1个(3-2),第三行有0个(3-3),可得上半部分每行的空位数为(i-line),line为该行的行数
for (int n = 0; n < i - line; n++) {
System.out.print("\t");
}
// 打印*,不难看出每行*的个数为为1、3、5,也就是奇数的等差数列,易得
// 每行*的个数为((2*line)-1),line为该行的行数
for (int n = 0; n < 2 * line - 1; n++) { // 打印字符
System.out.print("*\t");
}
System.out.println();
}
// 逐行打印菱形下半部分,下半部分共有i-1行
for (int n = 1; n <= i - 1; n++) {
// 打印制表符
// 与上半部分相反,下半部分每行的空位成递增
// 且与该行在下半部分的行数相等
for (int k = 0; k < n; k++) {
System.out.print("\t");
}
// 打印*,下半部分的*个数,仍为奇数,却成递减
// 该处的2*(i-n)-1与x-2*n等价
// x-2*n即菱形左右两侧各少了m个,m又与从下半部分看的行数n相等,故还剩x-2*n个
// x-2*n亦可视为首项为(x-2),公差为-2
for (int k = 0; k < 2 * (i - n) - 1; k++) {
System.out.print("*\t"); // 打印字符
}
System.out.println();
}
scanner.close();
}
public static void main(String[] args) {
printRhombus();
}
}
运行结果:
打印空心菱形
该题目的后续是打印空心菱形,其实实心的已经打印出来了,空心的也就不难了。对于空心菱形来说,其菱形外围的空位与实心的并没有区别,需要修改的只有打印星型字符的部分。其之所以是空心的,是因为每行只有首位两个*是打印出来的,故只要在打印*时添加一个判断条件,只有他在每行的第一个或者最后一个的时候才打印*,否则就用制表符来占位。
以菱形上半部分为例:
for (int line = 1; line <= i; line++) { // 逐行打印菱形上半部分
for (int n = 0; n < i - line; n++) { // 打印制表符
System.out.print("\t");
}
for (int n = 0; n < 2 * line - 1; n++) { // 打印字符
if((n==0)||(n==2*line-2)) {
System.out.print("*\t");
}else {
System.out.print("\t");
}
}
System.out.println();
}
下面贴上打印空心菱形的完整代码:
package day04;
import java.util.Scanner;
public class Work02 {
// 输入菱形的行数,如果行数非法则重新输入。根据行数打印一个空心菱形
public static int determineOddOrEven(int x) { // 奇偶判断,0为偶,1为奇
int m;
if (x % 2 == 0) {
m = 0;
} else {
m = 1;
}
return m;
}
public static void printRhombus() {
System.out.println("请输入你要打印菱形的行数(请输入奇数):");
Scanner scanner = new Scanner(System.in);
int x = scanner.nextInt();
int i = 0;
switch (determineOddOrEven(x)) {
case (0):
i = x / 2;
System.out.println("你输入的数为偶数,程序已将其转换为小1的奇数");
break;
case (1):
i = (x + 1) / 2;
break;
}
for (int line = 1; line <= i; line++) { // 逐行打印菱形上半部分
for (int n = 0; n < i - line; n++) { // 打印制表符
System.out.print("\t");
}
for (int n = 0; n < 2 * line - 1; n++) { // 打印字符
if((n==0)||(n==2*line-2)) {
System.out.print("*\t");
}else {
System.out.print("\t");
}
}
System.out.println();
}
for (int n = 1; n <= i - 1; n++) { // 逐行打印菱形下半部分
for (int k = 0; k < n; k++) { // 打印制表符
System.out.print("\t");
}
for (int k = 0; k < 2 * (i - n) - 1; k++) {
if((k==0)||(k==2*(i-n)-2)) {
System.out.print("*\t"); // 打印字符
}else {
System.out.print("\t");
}
}
System.out.println();
}
}
public static void main(String[] args) {
printRhombus();
}
}
运行结果: