# 類別 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 - 與角色距離(角色): 回傳兩者距離 - 攻擊角色(角色): 敵方血量減少我方攻擊力 - 顯示資訊: 顯示角色名稱、位置、攻擊、血量