# 用Dictionary做文字RPG
> Auther: 蘇柏丞
## 文字RPG
*情節介紹
1.輸入1繼續攻擊,輸入9逃跑。
2.輸入2使用第一個魔法攻擊,此回合不能普通攻擊。
3.輸入drink喝一罐藥水,增加血量,但此回合不能普通攻擊。
4.每回合顯示適當的資訊。
>也可以嘗試加入更多的情節,以下參考:
自訂 魔王血量、魔王攻擊
自訂 角色血量、角色攻擊
設定總回合數,並在到達規定回數後,依血量決定結果(或魔王存活就判定失敗)
設定藥水每次補充角色20%的總血量
設定至少一個魔法攻擊的招式及傷害(傷害值為魔王當前血量的10%)
設定魔法攻擊冷卻時間
## 範例(初學者版)
```python=
bossHp = 500
attack = 13
round = 0
choice = 0
while (bossHp > 0 and choice != 9):
choice = int(input('輸入1普通攻擊,輸入2魔法攻擊。輸入9逃。'))
round += 1
# level up per 3 rounds
if ( round % 3 == 0):
attack = attack*2+1
if ( choice == 1 ):
bossHp = bossHp - attack
if ( choice == 2 ):
bossHp = bossHp - attack * 2
if ( choice == 9 ):
break
if ( bossHp < 0) : #避免出現負數
bossHp = 0
print(f'經過第{round:2d}回合的攻擊,Boss 剩下{bossHp}Hp')
if ( bossHp > 0) :
print(f'遊戲結束,因為Boss 剩下{bossHp}Hp,所以挑戰失敗')
else :
print('遊戲結束,因為Boss 剩下 0Hp ,所以挑戰成功!!!!')
```
* 試著用函數來化簡,讓整體結構更加簡潔易懂。
* 試著用字典來管理這麼多個變數。
* 或是使用類別(最佳)來實作這個文字RPG
## 函數化
範例使用:
將攻擊程式函數化
使用時,僅需修改數值
```python=
def boss_attack(bossHp , attack , ab): #attack bonus
bossHp = bossHp - attack * ab
return bossHp
```
### 實際使用
```python=
bossHp = 500
attack = 13
round = 0
choice = 0
atk = 1
def boss_attack(bossHp , attack , ab): #attack bonus
bossHp = bossHp - attack * ab
return bossHp
while (bossHp > 0 , choice != 9 ):
print('輸入1普通攻擊,輸入2魔法攻擊。輸入9逃。')
round += 1
choice = input('')
magicAttack = bossHp * 0.1
if choice == "1" :
bossHp = boss_attack(bossHp , attack , 1)
elif choice == "2" :
bossHp = boss_attack(bossHp , attack , 2)
elif choice == "9" :
break
else:
print("無效指令!!!!!! 這回合無法攻擊")
if bossHp == 0:
print("勇者戰勝了!!!")
break
else :
print(f'經過第{round:2d}回合的攻擊,Boss 剩下{bossHp}Hp')
```
* 函數就是將一段會重複使用的程式碼模組化
## Dictionary 用法 1
### 範例:
```python=
myDictionary = {
'boss' : '習大大' ,
'attack' : 13,
'hp':100,
'magic_attack':15,
}
myDictionary['hp'] -= 10
print('%s血量剩下%d' % (myDictionary['boss'],myDictionary['hp']))
```
> `attack`,`hp`,`magic_attack`為`Dictionary`中的索引
>
> 代表叫到`attack`字元時,會傳喚出其賦值`13`
### 實作:
>目標:
>
>1. 將之前的 bossHp , bossAttack 整合成用 Dictionary 來呈現;就是將“角色”的“屬性”寫在各角色的 Dictionary 內
>
>註:可使用前面所提供的範例魔改
## 中繼版
> 改動:
>
> 1. 加入了"是否重新開始"的選擇
> 2. 給予魔王攻擊力與勇士血量
> 3. 增加藥水回復技能("drink")
> 4. 新增了"m1"密技(魔王損失10%血量)
```python=
again = "Yes"
while again != "No" :
boss = {
"hp" : eval(input('魔王血量')),
"attack" : eval(input('魔王攻擊力')),
}
coolguy = {
"hp" : eval(input('勇者血量')),
"attack" : eval(input('勇者攻擊力')),
}
allHp = coolguy['hp']
drink = coolguy ['hp'] * 0.2
round = 0
chioce = '0'
while (boss['hp'] > 0 , chioce != '9' ,coolguy['hp'] > 0):
print('輸入1普通攻擊,輸入2魔法攻擊。輸入9逃。')
round += 1
choice = input('')
coolguy['hp'] = coolguy['hp'] - boss['attack']
magicAttack = boss['hp'] * 0.1
if choice == "1" :
boss['hp'] = boss['hp'] - coolguy['attack']
elif choice == "2" :
boss['hp'] = boss['hp']- coolguy['attack'] * 2
elif choice == "m1" :
boss['hp'] = boss['hp']- magicAttack
elif choice == "drink" :
coolguy['hp'] = coolguy['hp'] + drink
if coolguy['hp'] > allHp :
coolguy['hp'] = allHp
elif choice == "9" :
break
else :
if round > 10 :
if choice == "m2" :
boss['hp'] = boss['hp'] - boss['hp'] * 0.5
else:
print("無效指令!!!!!! 這回合無法攻擊")
if boss['hp'] <= 0 :
boss['hp'] = 0
if coolguy['hp'] <= 0 :
coolguy['hp'] = 0
if coolguy['hp'] == 0 :
if boss['hp'] == 0 :
print("勇者選擇與習大大同歸於盡...")
break
else :
print("勇者血量見底,撲街ㄌ")
break
elif choice == 'drink' :
print("勇者選擇喝下藥水,目前血量%dhp"% coolguy['hp'])
elif boss['hp'] == 0:
print("勇者戰勝了習大大!!!")
break
else :
print(f'經過第{round:2d}回合,Boss 剩下%dHp,勇者剩下%dhp' % (boss['hp'],coolguy['hp']))
again = input("輸入No結束 其餘繼續(請注意大小寫)")
```
## Dictionary 用法 2
> 雖然上一個版本已經可以作為 文字 RPG手遊 來玩耍了,但 Dictionary 也可以拿來優化遊戲中關於招式的部分,讓其可以更好維護,也可以簡化程式碼
>
> Dictionary 的索引也可用來代表一段數學算式,如以下範例:
## 範例:
``` python =
boss = {
"hp" : eval(input('Boss 生命值')),
"attack" : eval(input('Boss 攻擊力')),
}
coolguy = {
"hp" : eval(input('Cool Guy 生命值')),
"attack" : eval(input('Cool Guy 攻擊力')),
}
choice = input('輸入1普通攻擊,輸入2魔法攻擊。輸入9逃。')
def action():
global boss , coolguy, choice
dictionary = {
"1" : (boss['hp'] - coolguy['attack']) ,
"2" : (boss['hp'] - coolguy['attack'] * 2) ,
}
boss['hp'] = dictionary[choice]
return boss
action()
print(boss['hp'])
```
* 範例中,”索引“ 從角色的屬性,變成了招數的代號
當叫到 “1” 時,其代表```
boss['hp'] - coolguy['attack']```這段運算程式碼
所以只要再用```boss['hp'] = dictionary[choice]```
就可以取代 ```中繼版``` 中的一堆 ``` if / else ... ```了
註:函數內的 ```global``` 代表引用 "全域變數" ; 函數 內/外 的 "變數引值" 相同
## 實作:
>目標:
>
>1. 將之前的 if / else 用 Dictionary 函數來取代;就是將招數寫在同個 Dictionary 內
>
>註:可使用前面所提供的範例魔改
## Ultra 版
``` python =
again = "Yes"
def action():
global boss , coolguy, choice , allHp , bug
dictionary = {
'1' : (boss['hp'] - coolguy['attack']) ,
'2' : (boss['hp'] - coolguy['attack'] * 2) ,
'm1' : (boss['hp'] - boss['hp'] * 0.1),
'drink': (coolguy['hp'] + allHp * 0.2 ),
}
if choice == '1' or choice == '2' or choice == 'm1':
boss['hp'] = dictionary[choice]
bug = 0
elif choice == 'drink' :
coolguy['hp'] = dictionary[choice]
bug = 0
if coolguy['hp'] > allHp :
coolguy['hp'] = allHp
else:
bug = 1
# 確保血量不會小於 0
if boss['hp'] <= 0 :
boss['hp'] = 0
while again != "No" :
# set up
bug = 0
boss = {
"hp" : eval(input('魔王血量')),
"attack" : eval(input('魔王攻擊力')),
}
coolguy = {
"hp" : eval(input('勇者血量')),
"attack" : eval(input('勇者攻擊力')),
}
allHp = coolguy['hp']
round = 0
while (boss['hp'] > 0 ,coolguy['hp'] > 0):
round += 1
print('輸入1普通攻擊,輸入2魔法攻擊。輸入9逃。')
choice = input()
if choice == '9' :
break
coolguy['hp'] = coolguy['hp'] - boss['attack']
action()
if bug == 1 :
while bug == 1 :
print("錯誤指令,請重新輸入")
choice = input('輸入1普通攻擊,輸入2魔法攻擊。輸入9逃。')
if choice == '9':
break
action()
if coolguy['hp'] <= 0 :
coolguy['hp'] = 0
elif choice == 'drink' :
print(f'在第{round:2d}回合,勇者選擇喝下藥水,此時 Boss剩下%dHp,勇者回復到%dhp' % (boss['hp'],coolguy['hp']))
elif coolguy['hp'] == 0 :
if boss['hp'] == 0 :
print("勇者選擇與習大大同歸於盡...")
break
else :
print("勇者血量見底,撲街ㄌ")
break
elif boss['hp'] == 0:
print("勇者戰勝了習大大!!!")
break
else :
print(f'經過第{round:2d}回合,Boss 剩下%dHp,勇者剩下%dhp' % (boss['hp'],coolguy['hp']))
again = input("輸入No結束 其餘繼續(請注意大小寫)")
```