---
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 " ";
}
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 " ";
}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 " ";
}
}
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 " ";
}
}
echo "<br>";
}
```
## 課後練習
1. 根據直角三角形的做法,撰寫一個可以印出倒直角三角形的程式,如下圖:
```
*****
****
***
**
*
```
2. 根據正三角的做法,撰寫一個倒正三角形的程式,如下圖:
```
*********
*******
*****
***
*
```
3. 綜合菱形及矩形的做法,撰寫一個挖空的菱形程式,如下圖:
```
*
* *
* *
* *
* *
* *
* *
* *
*
```
4. 承上題,在挖空的菱形中加入對角線
```
*
***
* * *
* * *
*********
* * *
* * *
***
*
```
5. 將星星數改成變數,只要更改這個變數的值,就可以畫出不同大小的形狀。