條件式&迴圈整理
===
**作者 - 彭彥菱
編輯 - BESTCI跨域人才程式能力培育計畫 / NTU BESA**
**項目**
==for loop (basic & nested & advanced )==
==while loop (basic & advanced & sentinel)==
==Conditions (if / else & Cascading if )==
**共筆內容**
**課程重點**
* for loops (basic)
* while loops (basic)
* coditionals
* advanced loop (while True)
* for loop - range
* nested for loop
**課程範例**
* 終極密碼
* 找到最大值
---
## 課程重點
在程式語言的世界裡重複咒語有兩種,for 跟 while loop,那這兩者到底有甚麼不同呢?
### 1. for loop (definite loop)
需要執行的次數:**已知**
依據問的問題,得知需要執行迴圈的次數。
**Basic For Loop**
```python=
for i in range(99): # 括號內的數字表示迴圈執行的次數
| |
重複區間
| |
```
**Nested Loops 巢狀迴圈**
(Lecture5)
### 2. while(Indefine loop)
需要執行的次數:**未知**
依據問的問題,來判斷要執行的動作,但不知道實際要執行的次數。
**Basic while loop**
```python=
while condition():
| |
Yes 區間
| |
|No 區間|
```
**Bugs for while loop (Fencepost Bug)**
* Infinite loop 需注意無限循環迴圈的情況
* 執行大於檢查
* OBOB (Off-By-One Bug)
:::info
在做while for loop時,最常出現缺頭或缺尾的bug
解決方案: 在執行loop前或後,多執行一次。
:::
舉例說明: 一個fence posts 的組成,會需要一個panel,兩個fenceposts,而fenceposts的數量會比panel多一個。

這就像是Karel要從(1,1)移動到盡頭(1,7),並放置一整排的beeper,會遇到的狀況是,當Karel走到最後一格時,是面對牆壁(`front_is_not_clear`),並不會放一顆beeper,所以我們要在while loop的No區間,多一行`put_beeper()`,才會放滿第一行的beeper,達成任務。

### 3. Conditions (Yes / No)
條件式的基本架構會從問題出發。
**Basic Conditionals**
```python=
if condition():
| |
Yes區間
| |
else:
| |
No區間
| |
```
**if statement 擇一執行**
因為if跟else會共用一個condition,所以else就不用在加condition,而if的Yes區間一定要有code,No區間就不一定要有code,若進入no區間則會直接結束這個條件式,若不執行任何動作,直接輸入`pass`。
**如何判斷 if / while 使用時機?**
if-else跟while loop不同的是,while會執行很多次,不斷地詢問,直到跳出loop,移到No區間為止,而if-else只會執行一次。
* nested if: 若是if內縮排再使用if,則是「滿足兩個條件的交集」才會執行。
* 2 if in arow: 若在if相同縮排處變成會「一定檢查」
**Advanced if statement**
這裡舉個例子來說明Advanced if statement的觀念,假設我們希望Keral可以移動到beeper上,並且撿取beeper,應該要用哪個if statement做會比較適合呢?

* **nested if**: 取兩個if條件的交集
> Karel撿取beeper需要同時滿足兩個條件,1. 前方是空的 2. 人需站在beeper上面,才會執行`pick_beeper` ,`move()`這些動作。
```python=
if front_is_clear():
if on_beeper():
pick_beeper()
move()
```
* **2 if in arow** 兩個if的條件都會被檢查到,會執行符合的條件
> Karel的前方只要是空的,就會往前移動一格,只要是站在beeper上面,就會撿取beeper。
```python=
if front_is_clear():
move()
if on_beeper():
pick_beeper()
```
### 4. advanced loop (while True)
while True不會擋任何迴圈,不管如何一定會進入這個迴圈。
若在執行迴圈時,遇到某些狀況需要停止,會使用`break`來跳出迴圈。
> 可以參考後面的課程範例: 終極密碼 (while True)
```python=
while True:
break
```
若在執行迴圈時,遇到某些狀況想要略過特定狀況,會使用`continue`。
```python=
while True:
continue
```
### 5. for loop - range
- 要如何判斷迴圈會跑幾次?
- *i* 是variable(迴圈編號),存了甚麼?
- zero-index: 程式通常從[0]開始編號
**range(start,stop,step)**
> start是起始值,stop是終止值,step是間隔值
先來看幾個例子:
* one argument
```python=
end = 5 #上限不包含
for i in range(end):
# 0,1,2,3,4
```
* two arguments
```python=
start = 1 #下限包含
end = 5
for i in range(start,end): # default step = 1
# 1,2,3,4
```
* three arguments
```python=
start = 1
end = 11
step = 2
for i in range(start,end,step):
# 0,1,3,5,7,9
```

(ref from https://www.pythonclassroom.com/loops/for-loop-range-one-argument)
### 6. Nested for loop
double variable要注意變數不重複
使用Nested loop印出以下圖形:
```
####
####
####
```
```python=
ROWS = 3
COLS = 4
for i in range(ROWS): # 總共列數
for j in range(COLS): # 總共欄數
print('#', end ="") #印出4個連續的#
print("") # 印出空字元=換行
```
那來試試看階梯變形版的圖形
```
#
##
###
```
這裡需要思考的是,當每次進入loop時,印出的`#`需要遞增1個,所以會使用`for j in range(i+1)`。
當跑第一圈時,`i = 0`代入,會得到`for j in range(1)`,第一列會印出`#`,跑第二圈時,第二列會印出`##`,以此類推。
```python=
for i in range(3): #總共三列
for j in range(i+1): #每印下一列增加1
print('#', end ="")
print("") #換行
```
如果`for j in range(i+1)`改成`for j in range(3)` 或 `for j in range(1,4)`會印出滿版的九宮格的#圖樣。
```
###
###
###
```
來試試看用Nested loop印出checkboard吧!
```
# #
# #
# #
# #
```
建議可以先觀察`#`所在位置,剛好都是在ROW與COL相加除以2的位置,取餘數為0的位置。
```python=
ROWS = 4
COLS = 4
for i in range(ROWS):
for j in range(COLS):
if (i+j)/2 == 0:
print("#", end = "")
else
print("", end = "")
print("")
```
## 課程範例
### 1. 終極密碼
Basic while loop
```python=
# This number controls when to stop the game
SECRET = 45
# Basic while loop
def main():
print("Guess a number from 0-99: ")
guess = int(input("guess: "))
while guess != SECRET:
if guess > SECRET:
print("Too high")
else:
print("Too small")
guess = int(input("guess: "))
print("Congrat!!!")
```
用進階loop迴圈`while True`的寫法,並使用`break`。
```python=
# advanced while True loop
def main():
print("Guess a number from 0-99: ")
guess = int(input("guess: "))
while True:
if guess > SECRET:
print("Too high")
elif guess == SECRET:
break
else:
print("Too small")
guess = int(input("guess: "))
print("Congrat!!!")
```
### 2. 找到最大值
```python=
# This constant controls when to stop
EXIT = -1
def main():
"""
This program find the maximum among
user inputs
"""
print('This program finds the maximum!')
data = int(input('Your Data: '))
if data == EXIT:
print("No number!")
else:
maximum = data
while True:
data = int(input('Your Data: '))
if data > maximum:
maximum = data
elif data == EXIT:
print(maximum)
break
```