1. 程式人生 > >L1-002 列印沙漏

L1-002 列印沙漏

L1-002 列印沙漏

本題要求你寫個程式把給定的符號列印成沙漏的形狀。例如給定17個“*”,要求按下列格式列印

*****
 ***
  *
 ***
*****

所謂“沙漏形狀”,是指每行輸出奇數個符號;各行符號中心對齊;相鄰兩行符號數差2;符號數先從大到小順序遞減到1,再從小到大順序遞增;首尾符號數相等。

給定任意N個符號,不一定能正好組成一個沙漏。要求打印出的沙漏能用掉儘可能多的符號。

輸入格式:

輸入在一行給出1個正整數N(<=1000)和一個符號,中間以空格分隔。

輸出格式:

首先打印出由給定符號組成的最大的沙漏形狀,最後在一行中輸出剩下沒用掉的符號數。

輸入樣例:

19 *

輸出樣例:

*****
 ***
  *
 ***
*****
2

個人思路:

      列印沙漏這道題我用了好幾種方法來做,最終總結出來還是以下的方法最容易理解。我們得明白沙漏是個對稱圖形,所以我們只要解決上半部分的圖形,下半部分的影象就可以迎刃而解了。

      首先先確定上半部分圖形的列數,通過一個while語句確定列數,剩下的點自然就是剩餘點;第二,定義一個輸出空格函式和輸出字元函式,輸出空格和字元。

     那麼問題來了,如何確定字元數和空格數呢?

    我們先假設第一列是一個字元,那麼第二列是3個字元,第三列是五個字元(上半部分的影象)....所以第n列的字元數就是2*n-1,字元數確定;我們再來看看第二列和第一列相差1個空格(字元後面的空格不用管,直接“\n”就可以解決),第三列和第一列相差2個字元,找規律可以得出,第n列和第m列(n>m)相差(n-m)個空格數(下半部分的圖形依舊如此)。

    只要解決空格數和字元數這道題就已經是OK了!

   不足之處望大家指出,本人一定加以改正和改進,謝謝!

原始碼:

#include<iostream>
#include<cstdio>
using namespace std;

void outputChar(int n, char c); /*輸出字元*/
void outputSpace(int n);       /*輸出空格*/
int main(){
	int n; char c; 
	cin>>n>>c; 
	if(n>1000||n<1){  /*n大於1000或者n小於1則無效*/
		return 0;
	}
	if(n<7){  /*n小於7則輸出一個符號*/
		cout<<c<<endl<<n-1;
		return 0;
	}
	int t = n-1; /*除去中間的一個字元,剩下的點賦值給t*/
	int count = 0; /*標記上半部分有多少列*/
	while(t>0){
		count++;
		/*第count+1列有(count+1)*2-1個字元,因為影象是對稱所以還要乘以2*/ 
		/*((count+1)*2-1)*2 = (4 * count + 2) */
		t -= (4 * count + 2);
	}
	t +=  (4 * count + 2);  /*當t小於0時則恢復到剩餘的點數*/
	int count2 = count; /*標記,用count2代替count*/
	
	/*輸出沙漏形狀上半部分*/
	while(count2>0){ 
		int x = count - count2; /*空格的個數*/
		outputSpace(x); /*輸出空格*/
		
		outputChar(count2*2-1, c); /*輸出字元*/ 
		cout<<endl;
		count2--; 
	} 
	
	/*輸出沙漏形狀下半部分*/
	count2 = 2;
	while(count2 <= count){
		int x = count - count2; /*空格的個數*/
		outputSpace(x); /*輸出空格*/
		
		/*第count2列有count2*2-1個字元*/
		outputChar(count2*2-1, c); /*輸出字元*/ 
		cout<<endl;
		count2++;
	} 
	cout<<t; /*輸出剩餘字元個數 */
	return 0;
}
void outputChar(int n, char c){
	for(int i=0; i<n;i++){ 
			cout<<c;  /*輸出字元*/ 
    }
} 
void outputSpace(int n){
	for(int i=0; i<n; i++){
			cout<<" ";   /*輸出空格*/
	} 
}