打印菱形
最近跟着學校的老師再重學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();
}
}
運行結果: