1. 程式人生 > >數字菱形圖案(繪製圖形題的通用思路解法)(C++)

數字菱形圖案(繪製圖形題的通用思路解法)(C++)

數字菱形圖案(雙重迴圈)(C++)

//找到一道比較有代表性的,較為全面的繪製圖形,並且控制繪製字元在變化的題目,驚喜。

【問題描述】
程式設計列印用數字構成的菱形圖案,菱形上半部分的行數n( 1<n<10 )從鍵盤輸入,總行數為2n-1。圖案的樣式按下面的樣例。

【輸入形式】
從鍵盤輸入包括中間一行在內的菱形上半部分的行數n ( 1<n<10 )。

【輸出形式】
輸出用數字構成的菱形圖案,樣式按下面的樣例,其中各數字間用1個空格間隔,中間一行的起始數字1位於第1列。

【樣例輸入】
4

【樣例輸出】

      1
    1 2 1
  1 2 3 2 1
1 2 3 4 3 2 1
  1 2 3 2 1
    1 2 1
      1

解題思路(繪製圖形的題套用)

  1. 把圖形分塊:(不是唯一分塊法)

           1|
         1 2| 1
       1 2 3| 2 1
     1 2 3 4| 3 2 1
     ——————————————
       1 2 3| 2 1
         1 2| 1
           1|
    
  2. 把分成四塊的菱形,每塊三角形單獨寫出程式碼(通用迴圈格式:for迴圈,i表示行數,j表示列數)

左上三角形:
TIP:先行提醒一下setw()的用法,不是呼叫setw(6)就空6個空格,而是表示設域寬為6個字元,如果後面連續輸出其他字元,這會在域寬中從右到左覆蓋“空格”)

//可以自己用以下這個程式碼自行體驗測試
#include <iostream>
#include <iomanip>
using namespace std;
main()
{
    int a=6;
    cout<<setw(1)<<a<<endl;
    cout<<setw(2)<<a<<endl;
}
#include <iostream>
#include <iomanip>//使用控制符時,要在程式的頭上加專門的標頭檔案
using namespace std;

int main()
{
    int n;
    cin>>n;//接下來以使用者輸入的n是4,即樣例輸出的菱形來做說明
    for(int i=1;i<=n;i++)//作為左上三角形,行數明顯與n一樣,所以使i迴圈n次
    {
        cout<<setw(2*n-2*i+1);//setw()即設域寬為()個字元,數格子找規律
        //(找規律的詳解見程式碼結束後的表格)
for(int j=1;j<=i;j++)//定義列數j和每列輸出的字元 { cout<<" "<<j;//注意題目要求是每個字元之間都有空格 } cout<<endl;//換行不能在for j 的迴圈裡面,應該是每完全輸出一行,才考慮換行 } }

以n=4為例:

行數i 空格數
1 7
2 5
3 3
4 1

普遍推廣到n:
(注意:空格數肯定是跟n和i有聯絡的,就往這上面湊)

行數i 空格數
1(1=n-(n-1)) 2*(n-1)+1
2(2=n-(n-2)) 2*(n-2)+1
n-2 5
n-1 3
n 1

概括的規律:
空格數=2*(n-i)+1
即setw(2*(n-i)+1)
(後面幾個找規律都是按這樣的思路來一一列表找,之後就不再如此反覆地解釋)

右上三角形:

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

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)//行數迴圈
    {
        //注意,以左上的三角形為參考,則右上的三角形第一行不能輸出東西,在第二行才開始輸出
            for(int j=i-1;j>0;j--)//列數j迴圈,而且我不想再多設定一個變數,就直接把j當作輸出的東西一起來迴圈
            //首先要保證迴圈的列數是從1到i-1,其次要保證輸出的字元是左邊三角形最大的數減1的那個數(即i-1)
            {
                cout<<" "<<j;
            }
            cout<<endl;
        }
    }
}

左下三角形:

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

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n-1;i++)//只要輸出n-1行
    {
        cout<<setw(2*i+1);//每行前面的“空格”找規律(肯定是一個與i有關的式子)
        for(int j=1;j<=n-i;j++)
        {
            cout<<" "<<j;
        }
        cout<<endl;
    }
}

右下三角形:

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

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n-1;i++)
    {
        for(int j=n-i-1;j>0;j--)//同右上三角形,不僅j控制列數迴圈次數,而且控制輸出字元,找個規律就很容易得答案了
        {
            cout<<" "<<j;
        }
        cout<<endl;
    }
}
  1. 模組組合:我們把以上四個小塊組合在一起,就很容易得到完整的菱形了。
    **思路:**上下關係的模組在main()函式內按順序並列排,左右關係的模組在for i 迴圈內按順序並列排,先內左右,後外上下,刪除相同的程式碼,保留不同的部分。

模組關係解釋:

左上為 ① 右上為②
左下為③ 右下為④

則①②為左右關係,③④也為左右關係,①②與③④則為上下關係。

以下給出組合好的完整程式碼:

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

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)//① ②為左右關係,則巢狀在for i 迴圈內
    {
        cout<<setw(2*n-2*i+1);
        for(int j=1;j<=i;j++)//左上 ①
        {
            cout<<" "<<j;
        }

        for(int j=i-1;j>0;j--)//右上 ②
        {
            cout<<" "<<j;
        }

        cout<<endl;//注意這個空行仍然在for j 迴圈的外層,並且① ②的兩個相同的語句合併為一個
    }

    for(int i=1;i<=n-1;i++)//③ ④為左右關係,則巢狀在for i 迴圈內
    {
        cout<<setw(2*i+1);
        for(int j=1;j<=n-i;j++)//左下 ③
        {
            cout<<" "<<j;
        }

        for(int j=n-i-1;j>0;j--)//右下 ④
        {
            cout<<" "<<j;
        }

        cout<<endl;
    }
}

PS:這樣就搞定了
推廣用法,菱形是比較全面的模型:

  1. 如果只是輸出左上三角,左下三角,怎麼組合程式碼呢?
  2. 如果不輸出數字,而全部用“#”代替會變化的數字輸出,怎麼改程式碼呢?
  3. 如果每個輸出字元之間不要留空格,怎麼尋找迴圈規律呢?
  4. 如果打九九乘法表,怎麼組合模組呢?