---
# System prepended metadata

title: 重複結構
tags: [python]

---

# 重複結構
###### tags: `python`

## While Loop
當某條件成立時，就做某件事，直到不成立為止。
```python=
while (condition):
    do_something
```

舉例，有人進場就計一次，並說歡迎光臨，直到10個人進場。
```python=
count = 0
while (count < 10):
    count = count +1
    print("歡迎光臨，您是第%d個客人" % count)
```

### 100以內，3的倍數
印出100以內，3的倍數。
```flow
start=>start: i=1
is3=>condition: i%3==0
print=>operation: print i
incre=>operation: i=i+1
lt100=>condition: i less equal than 100
end=>end

start->is3
is3(yes)->print
is3(no)->incre
print->incre
incre->lt100
lt100(yes)->is3
lt100(no)->end
```
```python=
i = 1
while (i<100):
    if(i%3 == 0):
        print(i)
    i = i+1
```
**Challenge**
1. 輸出總共幾個3的倍數。
2. 若尾數是3也輸出。
3. 更改程式變成：輸入三個數，low, high, num。輸入low跟high之間，num的倍數。

### 終極密碼
電腦從1到100隨機選擇一個整數，使用者猜測該整數。若答對，回傳答對，結束程式。若答錯，告訴使用者新的區間，並繼續猜。
```flow
num=>inputoutput: num = 1到100隨機的整數
guess=>inputoutput: guess = 使用者猜測
result=>condition: num == guess
range=>operation: 提示新的範圍
end=>end


num->guess->result
result(yes)->end
result(no)->range->guess
```

```python=
import random
num = random.randint(1,100)
up = 100
down = 0
guess = int(input("輸入猜測的數："))
while (guess != num):
    if guess > num:
        up = guess
    else:
        down = guess
    print("範圍在 %d 到 %d 之間" % (down, up))
    guess = int(input("輸入猜測的數："))
print("你猜對了！答案是%d" % guess)
```
### 文字RPG
設定魔王血量、勇者攻擊，當魔王未死，就攻擊。換成程式的想法，當魔王血量大於0，就重複攻擊。
```python=
hp = 1000
attack = 13
while (hp > 0):
    hp -= attack
    print(f'魔王Hp剩下:{hp}')
```
新增更多情節包含：
- 加入回合數。
- 若魔王已死，顯示死亡，而非負的血量。
- 每3回合角色升級，攻擊變成2倍。
- 加入勇者血量，會被扣血。記得勇者未死才能繼續打怪。
- 加入互動，輸入1繼續打，輸入9逃。
```python=
hp = 1000
attack = 13
round = 0
decide = 1
角色hp = 100
魔王攻擊 = 11
while (hp > 0 and decide==1 and 角色hp > 0):
  round = round + 1
  print(f'現在是第 {round} 回合')

  # Level up per 3 rounds
  if (round % 3 == 0):
    attack = 2*attack
    
  # 勇者
  角色hp = 角色hp - 魔王攻擊
  print(f'勇者被打，剩下:{角色hp}HP')
  # 魔王
  hp = hp - attack
  if (hp > 0):
    print(f'Hp剩下:{hp}\n')
  else:
    print('Dead')
  
  decide = eval(input('輸入1繼續打，輸入9逃跑：'))
```
可以嘗試加入更多的情節，以下參考：
設定
1. 自訂 魔王血量、魔王攻擊
2. 自訂 角色血量、角色攻擊
3. 設定回合數
4. 設定藥水每次補充角色20%的總血量
5. 設定至少一個魔法攻擊的招式及傷害(傷害值為魔王當前血量的10%)


情節
1. 輸入1繼續攻擊，輸入9逃跑。
2. 輸入m1使用第一個魔法攻擊，此回合不能普通攻擊。
3. 輸入drink喝一罐藥水，此回合不能普通攻擊。
4. 從第【你的座號】回合開始，每3回合升級。升級後攻擊力變成原本的1.1倍。
5. 每回合顯示適當的資訊。

- 你可以試著用函數來化簡，讓整體結構更加簡潔易懂。
- 你可以用字典來管理這麼多個變數。
- 或是使用類別(最佳)來實作這個文字RPG 


## For loop
`for`迴圈有兩種基本的用法，一種是「指定次數」；另一種是「迭代」。
### 指定次數
```python=
for i in range(10):
    print(i)
```
`i` 會從0開始遞增到9，總共進行10次。每次執行`print(i)`。
因此第一次印出0、第二次印出1 ... 第十次印出9

你也可以指定範圍：
```python=
for i in range(2,10):
    print(i)
```
`i`會從2開始作「`10-2 = 8`」次，所以會印 2 到 9。

可以指定間隔：
```python=
for i in range(2,10,2):
    print(i, end='')
# output: 2 4 6 8
```
Hint: 有時候我們只是指定次數，但用不到`i`，此時可以把`i`改成`_`。

```python=
for _ in range(3):
    do_something
```

#### Exercise
印出50到100之間，3的倍數。並最後輸出總共有幾個3的倍數。

### 迭代
我們可以把一個串列當作迭代的對象：
```python=
shoppingList = ['醬油', '洋芋片', '麵條']
for item in shoppingList:
    print("記得要買%s！" % (item))
# output:
# "記得要買醬油！"
# "記得要買洋芋片！"
# "記得要買麵條！"
```

### 迭代+索引
當你想要迭代但又想要有編號的時候，可以用 `enumerate`
```python=
shoppingList = ['醬油', '洋芋片', '麵條']
for index, item in enumerate(shoppingList):
    print(f'第{index+1}項要買的東西是{item}。')

# 第1項要買的東西是醬油。
# 第2項要買的東西是洋芋片。
# 第3項要買的東西是麵條。
```

### Advance Exercise
對一串數字進行質因數分解。
```python=
numbers = [60, 39, 77, 1024, 2022]
for number in numbers:
    do_something...
    

# output:
# 60 = 2^2 * 3 * 5
# 39 = 3 * 13
# 1024 = 2^10
# 2022 = ...
```

### Nested Structure
接著我們看一下`for loop`的巢狀結構。
[用*畫圖](https://colab.research.google.com/drive/1AX_9kJM03DMOjcuDVe6OcDzqGwF1_dxz?usp=sharing)

## Wrapping up
- 當我們需要指定條件時，使用`while loop`
- 當我們需要指定次數時，使用`for loop`
- 當我們需要迭代串列時，使用`for loop`
- 每個結構裡面都可以在各自放別的結構。

### Exercise
試著做一個1A2B的猜數字遊戲吧！
[參考答案](https://colab.research.google.com/drive/1wM4sHnpi97KWzoE3mYPwimodRBnPgNdO?usp=sharing)