應網友要求, 這次把中空凌形說明和原始碼放上來..
由於說明過長,在看說明時,
建議先把圖形長相先畫在紙上,避免不便閱讀。
現在我們考慮以下圖形。
如圖所示,我將圖形分成 A 部份和 B 部份分別做分析
而使用者輸入 9 時,凌形高度的對半剛好就等於9
為方便說明,此處我分析時,9 到時會用 n 代替
現在只考慮 A 部份(為1~n行)..
1. 考慮 A 部份之紅色三角型部份(即第一個數字前之空白數)
觀查行數和空白數的關係,我們可以觀查出下列規則
第 1 行-> 8 個空白
第 2 行-> 7 個空白
第 3 行-> 6 個空白
...
第 i 行 -> n-i 個空白
第一段的 code 出來了
// A Part
for(i=1; i<=n; i++){ // 共 n 行
// 1. 印出 第1個數字 之前的空白數
for(j=1; j<=n-i; j++) printf(" ");
..........
}
2. 印出第一個數字部份
第 1 行 -> 印出 1
第 2 行 -> 印出 2
....
第 i 行 -> 印出 i
接著又可以寫下來..
// A Part
for(i=1; i<=n; i++){ // 共 n 行
// 1. 印出 第1個數字 之前的空白數
for(j=1; j<=n-i; j++) printf(" ");
// 2. 印出 第1個數字
printf("%d", i);
..........
}
3. 考慮 A 部份之亮綠色三角型部份(即第二個數字前之空白數)
第 1 行-> 0 個空白(事實上這行可以不用考慮,因為就算印出100個空白,也不會印出第二個數字)
第 2 行-> 1 個空白
第 3 行-> 3 個空白
.....
第 i 行 -> 2i-3 個空白
關於這部份, 有人說看不出規則性,
於是在此提供下列方法
假設第 x 行印出 y 個空白
我們便可假設 y = ax + b... (1)式
現在要求的是 a, b 值
代入第2行有1個空白 -> x=2, y=1 , 代入 (1) 式 -> 1 = 2a+b.... (2)式
代入第3行有3個空白 -> x=3, y=3 , 代入 (1) 式 -> 3 = 3a+b.... (3)式
接著解 (2), (3) 式連立, 可以得到 a=2, b=-3
即 y=2x-3
於是可以得到以下結論:
第 x 行有 2x-3 個空白數, 即 第 i 行有 2i-3 個空白數
這種連立方程式的方式畫*問題幾乎都可這麼分析
於是第3段code 出來了..
// A Part
for(i=1; i<=n; i++){ // 共 n 行
// 1. 印出 第1個數字 之前的空白數
for(j=1; j<=n-i; j++) printf(" ");
// 2. 印出 第1個數字
printf("%d", i);
// 3. 印出 第2個數字 之前的空白數
for(j=1; j<=2*i-3; j++) printf(" ");
........
}
4. 印出第二個數字並換行
第 1 行 -> 不印數字, 換行
第 2 行 -> 印出 2, 換行
第 2 行 -> 印出 3, 換行
...
第 i 行 -> 印出 i, 換行
在這裡可以發現一個規律, 和第2點很像
只是第 1 行只印1個數字1,不印第二個數字
其它的都是第 i 行印出 i, 於是用 if-else 控制後如下所述..
// A Part
for(i=1; i<=n; i++){ // 共 n 行
// 1. 印出 第1個數字 之前的空白數
for(j=1; j<=n-i; j++) printf(" ");
// 2. 印出 第1個數字
printf("%d", i);
// 3. 印出 第2個數字 之前的空白數
for(j=1; j<=2*i-3; j++) printf(" ");
// 4. 印出第2個數字, 並予以換行
// 如果數字是 1 的話就不再印數字,直接換行
if(i==1) printf("\n");
else printf("%d\n", i);
}
到底為止,以上 A part 部份已完成,
接下來 B part 部份與 A part 極為相似
5. B part 部份
有心者請再從 step1~step4 重覆一次步驟
發現唯一有差的是 i 的變化..
數字到9後,又從8, 7, 6...., 1 一路降一
於是B part 外回圈的 i 便設成
for(i=n-1; i>0; i--)
接著其它的分析都一樣, 甚至連紅色三角形、綠色三角形與 i 值的關係都一樣
於是 B Part 的 code 便長這樣...
// B Part
for(i=n-1; i>=; i--){ // 共 n 行
// 1. 印出 第1個數字 之前的空白數
for(j=1; j<=n-i; j++) printf(" ");
// 2. 印出 第1個數字
printf("%d", i);
// 3. 印出 第2個數字 之前的空白數
for(j=1; j<=2*i-3; j++) printf(" ");
// 4. 印出第2個數字, 並予以換行
// 如果數字是 1 的話就不再印數字,直接換行
if(i==1) printf("\n");
else printf("%d\n", i);
}
6. A part 與 B part 結合
最後 A part 與 B part 結合後
完整程式碼便如下所示...
#include <stdio.h>
int main()
{
int i, j, n;
printf("請輸入n(n<10):");
scanf("%d", &n);
// A Part, 上半段
for(i=1; i<=n; i++){ // 共 n 行
// 1. 印出 第1個數字 之前的空白數
for(j=1; j<=n-i; j++) printf(" ");
// 2. 印出 第1個數字
printf("%d", i);
// 3. 印出 第2個數字 之前的空白數
for(j=1; j<=2*i-3; j++) printf(" ");
// 4. 印出第2個數字, 並予以換行
// 如果數字是 1 的話就不再印數字,直接換行
if(i==1) printf("\n");
else printf("%d\n", i);
}
// B Part, 下半段
for(i=n-1; i>=; i--){ // 共 n 行
// 1. 印出 第1個數字 之前的空白數
for(j=1; j<=n-i; j++) printf(" ");
// 2. 印出 第1個數字
printf("%d", i);
// 3. 印出 第2個數字 之前的空白數
for(j=1; j<=2*i-3; j++) printf(" ");
// 4. 印出第2個數字, 並予以換行
// 如果數字是 1 的話就不再印數字,直接換行
if(i==1) printf("\n");
else printf("%d\n", i);
}
return 0;
}
以上,分析至此
再次強調,方法非唯一,
這種分析法執行速度並不算快
但所有的圖形問題,也跑不過這種分析方式
感謝各位收聽!!