作者VictorTom (鬼翼&娃娃魚)
看板C_and_CPP
標題Re: [問題] 請問畫一個圖形
時間Tue Oct 27 01:06:20 2009
※ 引述《fjf1980 (Yes We Can!)》之銘言:
: 我今天無聊自己玩畫一個圖形,就是給定高及寬都是奇數,畫一個類似以下圖形
: 1 ***********
: 2 ***** *****
: 3 **** ****
: 4 *** ***
: 5 ** **
: 6 * *
: 7 ** **
: 8 *** ***
: 9 **** ****
: 10***** *****
: 11***********
: 花了我好久時間,寫出來一個程式,但是感覺真的是很遜的程式
: 在底下,請問有沒有高手能對這圖形有比較好的寫法
比較好的寫法小弟不清楚, 但是看到這題不知道為什麼就手很癢....
然後就寫了一個有點噁心加些惡搞的版本, 字串加遞迴胡搞瞎搞版XD
==
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTAR 79
int length = 21;
void print_star(char *StarLine, char *StarLeft, char *StarRight, int level)
{
char StarPrint[MAXSTAR] = { 0 };
int left = length/2+1, right = length/2;
strncat(StarPrint, StarLeft, left);
strncat(StarPrint, StarRight, right);
printf("%s\n", StarPrint);
if(level >= length/2) return;
else print_star(StarLine, StarLeft+1, StarRight-1, level+1);
printf("%s\n", StarPrint);
StarPrint[0] = '\0';
}
int main(void)
{
char *StarLeft, *StarRight;
char StarLine[MAXSTAR*2] = { 0 };
int i, j;
for(i=0; i<=length/2; ++i) StarLine[i] = '*';
StarLeft = &StarLine[0];
for(i=length/2+1, j=0; j<length-2; ++j) StarLine[i+j] = ' ';
StarRight = &StarLine[i+j+1];
for(i=i+j, j=0; j<length/2+1; ++j) StarLine[i+j] = '*';
StarLine[i+j] = '\0';
print_star(StarLine, StarLeft, StarRight, 0);
system("PAUSE");
return 0;
}
==
感覺應該可以再省掉幾個變數, length在不超過MAXSTAR的情況下可以改....
因為偷懶所以沒有做奇偶數檢查, 跑到console的最大奇數寬79還不會爆喔:)
==
簡單的說, main函數在產生一個特殊的char string - StarLine[];
接著設定一左一右兩個指標指著它, 然後遞迴邊印邊移動指標送....
Ex: length = 11 時....
[length-2的' '] / [左右各為length/2+1的'*']
StarLine[]內容為: "****** ******"
^ ^
左指標 右指標(右指指在右半第二個*沒錯喔)
遞迴每一輪, 從左指標印length/2+1個char, 從右指標印length/2個char....
於是就剛好印出: [左]"******"[右]"*****" => "***********"
這裡我用strncat()做是因為不用迴圈我不知道怎麼指定印N個char....Orz
print_star()裡的StarPrint正好就拿來當strncat()的temp....
自己有一份獨立的空間好處是後面下半部就可以直接印(stack沒爆的話~_~)
印完以後遞迴呼叫時, 左指標右移一個char, 右指標左移一個char....
於是第二輪會印: [左]"***** "[右]"*****" => "***** *****"
然後第三輪會印: [左]"**** "[右]" ****" => "**** ****"
印到第length/2+1層的時候遞迴就不需要再呼叫下去了....
(其實這裡也可以用右指標-左指標>=length-2來判斷, 但懶得改了^^||)
==
說惡搞, 也不過是把印的迴圈藏在strncat裡....
把上下對稱反轉的部份藏在遞迴裡cover掉啦....
一開始的發想是總覺得"****** ******"這東西好像可以利用....
然後想一想, 推一推, 畫畫圖, 還被左右*怎麼對稱與不對稱卡了好久....
最後又把遞迴給加上去就變成這付德性了, 還請大大們鞭小力一點<(_ _)>
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.132.174.98
※ 編輯: VictorTom 來自: 220.132.174.98 (10/27 01:06)
→ VictorTom:遞迴終止照文章()裡寫的有錯, 反正推一下就有了XDD 10/27 01:25
Edit: 忘了用BBSCode標色工具, 補用一下....@_@"
※ 編輯: VictorTom 來自: 220.132.174.98 (10/27 01:50)
推 fjf1980:V大真的太強了@@ 這是我無聊想到的一個圖形 想寫寫看 10/27 08:59
→ fjf1980:但我寫不出來V大 還有上面另一位高手的漂亮寫法呀 >"< 10/27 08:59
→ VictorTom:s大的寫法才是比較簡單的寫法, 小弟這寫法只是在搞怪XD 10/27 09:00
→ VictorTom:主要的想法是, 這圖形裡左右上下對稱(不考慮奇數中間), 10/27 09:01
→ VictorTom:怎麼把做印'*'與印' '判斷的地方有效率的"寫成code":) 10/27 09:02
→ VictorTom:即, 找出規律, 合併相關算式, 然後組合成像s大那樣@_@" 10/27 09:03
→ VictorTom:如果有些其他(奇怪)的idea, 就是努力實作看看如何囉^^ 10/27 09:05
推 fjf1980:我覺得這就是邏輯思考好壞的差別 我邏輯差 所以寫不好 >"< 10/27 09:06
→ VictorTom:小弟我覺得這種能力是可以訓練的, 多做多練習些題目應該 10/27 09:13
→ VictorTom:會比較有感覺(像ACM?), 雖然可能和那些聰明的不能比Q_Q~ 10/27 09:14
→ VictorTom:總覺得那些去參加比賽的人都利害到不知該崇拜還是敬畏^^ 10/27 09:16