# 類別 Class
回顧我們用 `dictionary` 做 RPG:
```python=
role_1 = {'hp':100, 'attack': 13, 'name':'kyle', 'magic':11}
role_2 = {'hp':123, 'attack': 34, 'name':'Steven', 'maxic':13}
print('%s has %s hp and his attack is %s.' % (role_1['name'], role_1['hp'], role_1['attack']))
```
用這個方法,我們可以存取 `role_1`、`role_2`的各類數值。但缺點一,若今天角色要新增`magic`這個參數,則全部都要新增,而且可能打錯字。缺點二,現在還看不出來xD
讓我們接著看如果用 `class` 會怎麼樣:
```python=
class role:
def __init__(self, hp, attack, name, gender):
self.hp = hp
self.attack = attack
self.name = name
self.gender = gender
kyle = role(hp=100, attack=13, name='Kyle', gender='male')
print(kyle.hp)
# 100
```
我們的起手式是用關鍵字 `class` 後面定義名稱。
這邊先定義一個 `__init__`的函數,是初始化的意思,也就是說我們要建立一個 `role` 物件,需要哪些東西,就會在這邊定義。
第8行的地方,我們建立了一個 `role`,將其用參數 `kyle`儲存,並以相關參數來初始化他。
目前為止其實還看不太出來使用 `class` 優於 `dictionary` 的地方。
你可以試試看,如果今天建立一個 `role`,但沒有寫到 `gender` 參數會怎樣?應該是會報錯!
這是正確的!因為報錯你才知道要修改~藉由我們 `class` 的規定,你在寫程式時就不會忘記把 `role`的每個參數寫進去,因為沒寫或寫錯會報錯。
但如果好處僅於此好像也還好,讓我們再往下新增定義一個 `description` 的「方法」。
```python=
class role:
coordinate = {'x':0, 'y':0}
def __init__(self, hp, attack, name, gender):
self.hp = hp
self.attack = attack
self.name = name
self.gender = gender
def description(self):
if self.gender == 'male':
print('%s has %s hp and his attack is %s.' % (self.name, self.hp, self.attack))
elif self.gender == 'female':
print('%s has %s hp and her attack is %s.' % (self.name, self.hp, self.attack))
else:
print('%s has %s hp and his/her attack is %s.' % (self.name, self.hp, self.attack))
kyle = role(hp=100, attack=13, name='Kyle', gender='male')
kyle.description()
```
如果你新增任何 `role` 都可以使用個方法。你只要事先寫好你要的模板即可。
再來我們可以增加更多的方法:
- `fight_with(oppent)` :跟某人對打,輸出「贏」或是「輸」。
- `move(x,y)`:移動x座標x個單位、y座標y個單位。你會需要有一個參數儲存座標 `coordinate`。
```python=
class role:
coordinate = {'x':0, 'y':0}
def __init__(self, hp, attack, name, gender):
self.hp = hp
self.attack = attack
self.name = name
self.gender = gender
def description(self):
if self.gender == 'male':
print('%s has %s hp and his attack is %s.' % (self.name, self.hp, self.attack))
elif self.gender == 'female':
print('%s has %s hp and her attack is %s.' % (self.name, self.hp, self.attack))
else:
print('%s has %s hp and his/her attack is %s.' % (self.name, self.hp, self.attack))
def fight_with(self, oppent):
myHp = self.hp
hisHp = oppent.hp
while(hisHp>0 and myHp>0):
hisHp -= self.attack
myHp -= oppent.attack
if hisHp>0:
print('Lose')
else:
print('Win')
# upgrade
self.hp += oppent.hp
self.attack += oppent.attack
print(f'Now your hp is {self.hp} and your attack is {self.attack}')
def move(self, x, y):
self.coordinate['x'] += x
self.coordinate['y'] += y
print('Step on (%2s, %2s)' % (self.coordinate['x'], self.coordinate['y']))
kyle = role(hp=100, attack=13, name='Kyle', gender='male')
steven = role(hp=123, attack=34, name='Steven', gender='male')
Amber = role(hp=10000, attack = 346, name = 'Amber', gender='female')
# hardcode
print('%s has %s hp and his attack is %s.' % (kyle.name, kyle.hp, kyle.attack))
print('%s has %s hp and his attack is %s.' % (steven.name, steven.hp, steven.attack))
# use function
kyle.description()
Amber.description()
# fight
kyle.fight_with(Amber)
Amber.fight_with(kyle)
# move
kyle.move(3,4)
kyle.move(31,41)
```
在 `class` 裡面定義方法時,你會發現很常把「`self`」加進去。他的意思就是「呼叫自己」。例如當你定義「`self.hp`」,那麼`kyle`使用就會變成 `kyle.hp`。
## 小練習
[用clss定義點跟線](https://replit.com/team/LinYeh/class-point-and-segment)
# RPG-class
- x座標移動a單位(a) 讓x座標增加a
- y座標移動b單位(b): 讓y座標增加b
- 與角色距離(角色): 回傳兩者距離
- 攻擊角色(角色): 敵方血量減少我方攻擊力
- 顯示資訊: 顯示角色名稱、位置、攻擊、血量