--- title: 迴圈印星星 tags: 程式設計基礎,迴圈印星星,php,html,loop --- # 迴圈印星星 印星星是一個經典的程式迴圈應用範例,透過印出各式的形狀,來呈現出迴圈應用上的變化。 ### 直角三角形 ``` * ** *** **** ***** ``` 我們先從最直覺的方式來思考這個問題,如果只是要印出五列星星,每列多一顆,那麼我們使用echo就可以快速的完成了。 ```php= echo "*"; echo "**"; echo "***"; echo "****"; echo "*****"; ``` 在這個範例中,我們觀察星星的狀況得知: 1. 每列多一顆,等於是每列要重覆執行印星星n次。 如果要寫成迴圈的程式,我們先以一層迴圈來寫,大概會得到如下的程式碼: ```php= for($i=1;$i<=1;$i++){ echo "*"; } echo "<br>"; for($i=1;$i<=2;$i++){ echo "*"; } echo "<br>"; for($i=1;$i<=3;$i++){ echo "*"; } echo "<br>"; for($i=1;$i<=4;$i++){ echo "*"; } echo "<br>"; for($i=1;$i<=5;$i++){ echo "*"; } echo "<br>"; ``` 同樣的思考邏輯,這五個迴圈有著許多類似的地方,唯一有變化的地方就是需要印的星星數不同的問題,因此我們開始研究如何簡化這五個迴圈,是否能有一個變數來代表每列的星星數? 因此我們一樣採用兩層迴圈的方式來處理,外圈控制列數,內圈控制星星數,而外圈所控制的圈數又剛好可以當成內圈需要印出的星星數,因此我們把程式改成如下的內容: ```php= for($i=1;$i<=5;$i++){ for($j=1;$j<=$i;$j++){ //在內圈中,我們把外圈的變數$i當成內圈次數的限制 echo "*"; } echo "<br>"; } ``` 在簡化後,我們可以注意到,只要修改外圈條件限制中的值,就可以印出不同列數的星星,而不需要自己去計算列數及星星數是否符合規範。 ### 正三角形 ``` * *** ***** ******* ********* ``` 觀察正三角形,我們歸納幾點: 1. 每列的星星數差2顆 2. 每列會插入不同數目的空白來將星星定位到中間的位置 3. 觀察每列的星星數和列的關係,為2n-1,n從1開始 4. 觀察每列的空白數和列的關係,為5-n,n從1開始 綜合以上的分析,我們撰寫一個正三角形的程式碼如下: ```php= for($i=1 ; $i <= 5 ;$i++){ for($k=1; $k <=(5-$i);$k++){ echo "&nbsp;"; } for($j=1 ; $j <= (2*$i-1) ; $j++){ echo "*"; } echo "<br>"; } ``` ### 菱形 ``` * *** ***** ******* ********* ******* ***** *** * ``` 同樣的,我們先觀察菱形有沒有什麼特別或有規則的地方,做為我們分析的重點: 1.每列差2顆星星,和正三角形一樣,會需要加入空白做定位。 2.菱形的列數一定要是奇數的,才會有中間最長的那一列星星,中間列可以用(n+1)/2來表示 3.超過中間列後的星星數則以每列少兩顆的方式遞減, 4.整個菱形就是一個正三角形和一個倒三角形的組合 所以我們可以考慮用一個n列的正三角形的程式加上一個n-1列的倒三角形來完成菱形,但在這個範例中,我們希望採用一支程式來完成菱形的繪製,而不是拆成兩個獨立的程式。 因此最關鍵的地方在於判斷何時要遞增,何時要遞減;從上述的分析,我們可以知道,中間列是遞增和遞減的關鍵,而中間列的表示法為(n+1)/2(n需為奇數)。 因此我們決定使用一個雙層迴圈,再加上對中間列的判斷來完成這個菱形的繪製,程式碼如下: ```php= $temp=0; for($i=1;$i<=9;$i++){ if($i>5){ $temp=$temp-1; }else{ $temp=$i; } for($j=1;$j<=(4+$temp);$j++){ if($j<=(5-$temp)){ echo "&nbsp;"; }else{ echo "*"; } } echo "<br>"; } ``` ### 矩形 ``` ******** * * * * * * * * * * ******** ``` 矩形相較前面的幾個形狀,並沒有很直覺的遞增遞減關係存在,因為它只是一個空心的矩形,中間則是連續的空白;經觀察後,我們大致分析如下: 1. 第一列及最後一列為連續的星星印製 2. 第二列及倒數第二列則只有頭尾需要印星星,其它的位置都是印空白 根據以上兩條簡單的觀察,我們可以得出一個方向;重點在於判斷出目前要印的是那一列,才能決定是要印出一整列的星星還是包含空白的內容,如果判斷出來不是第一列及最後一列,則需要以迴圈來印製空白,而頭尾的星星則以判斷式來判斷即可。 綜合以上的描述,我們撰寫出來的矩形程式碼如下: ```php= for($i=1 ; $i<=9 ; $i++){ for( $j=1 ; $j<=9 ; $j++ ){ if($i==1 || $i==9){ echo "*"; }else if($j==1 || $j==9){ echo "*"; }else{ echo "&nbsp;"; } } echo "<br>"; } ``` ### 矩形對角線 ``` ********* ** ** * * * * * * * * * * * * * * * * * * * ** ** ********* ``` 承矩形的基礎,我們觀察對角線的特徵後,得出以下的分析: 1. 對角線的星星位置是以x=y,及x=n-y+1的關係得出的 2. 比如第二列的第二顆星星,會對應到第二列的第八顆星星(9-2+1) 透過以上的分析,我們可以得知,在程式碼的撰寫上,可以基於矩形的基礎上,再增加對於對角線位置的判斷即可,因此最後得出的程式碼如下: ```php= for($i=1 ; $i<=9 ; $i++){ for( $j=1 ; $j<=9 ; $j++ ){ if($i==1 || $i==9){ echo "*"; }else if($j==1 || $j==9 || $j==$i || $j==(9-$i+1)){ echo "*"; }else{ echo "&nbsp;"; } } echo "<br>"; } ``` ## 課後練習 1. 根據直角三角形的做法,撰寫一個可以印出倒直角三角形的程式,如下圖: ``` ***** **** *** ** * ``` 2. 根據正三角的做法,撰寫一個倒正三角形的程式,如下圖: ``` ********* ******* ***** *** * ``` 3. 綜合菱形及矩形的做法,撰寫一個挖空的菱形程式,如下圖: ``` * * * * * * * * * * * * * * * * ``` 4. 承上題,在挖空的菱形中加入對角線 ``` * *** * * * * * * ********* * * * * * * *** * ``` 5. 將星星數改成變數,只要更改這個變數的值,就可以畫出不同大小的形狀。