[Toc]
# 第9章 IO流
又是一個周末。小墨使用最新學的函數知識豐富了《小墨歷險記》:
* 在游戲開始加入了墨家村英雄榜供玩家選擇角色;
* 加入了關卡,整個游戲設置了5個boss,難度逐漸升級;
* 你需要一直戰斗,但是每過一個關卡會獎勵和關卡難度相對應的生命值。
最后在加入保存游戲進度功能的過程中出現了問題。看墨哥哥也在家,小墨就來找哥哥了。
最新的一款小墨歷險記究竟什么樣?小墨遇到的問題,墨哥哥又是如何解決的呢?一起來看看吧。
時間:又一個周末
地點:小墨家
小墨:墨哥哥,我又做了一款新的小墨歷險記,加入了你之前講的一些情節。但是現在遇到了點問題,你有時間了幫我看看吧?
墨哥哥:好啊小墨,現在就有時間。
小墨:那我先說說我做了哪些功能。
## 9.1 又一版小墨歷險記
小墨:首先,我定義了一個方法叫background,交代故事背景
```
# 背景介紹
def background():
print("游戲開始……")
print("歡迎來到墨家村,如今是妖獸的地盤")
```
這一款和前面小墨歷險記不同的是,游戲的主角不再是小墨,而是由玩家來選擇。這里我定義好了一堆角色的數據,用于玩家選擇角色:
```
hero_list = [
{'index': 1, 'name': '墨小小', 'hp': 1000, 'mp': 800, 'ap': 45, 'dp': 20,
'skills': ['一墨橫空', '墨渡迷津', '墨之縱橫', '墨下乾坤'], 'skills_hp': [20, 45, 75, 100],
'is_warrior': True, 'is_mage': False, 'is_hunter': False, },
{'index': 2, 'name': '墨小妹', 'hp': 1200, 'mp': 700, 'ap': 35, 'dp': 21,
'skills': ['貂蟬拜月', '西施捧心', '昭君出塞', '貴妃醉酒'], 'skills_hp': [18, 23, 47, 82],
'is_warrior': True, 'is_mage': True, 'is_hunter': False, },
{'index': 3, 'name': '墨大元', 'hp': 1100, 'mp': 600, 'ap': 38, 'dp': 17,
'skills': ['千里橫行', '寒刀斷水', '狂龍破日', '天地無情'], 'skills_hp': [26, 51, 80, 102],
'is_warrior': True, 'is_mage': False, 'is_hunter': True, },
{'index': 4, 'name': '墨當歸', 'hp': 900, 'mp': 1100, 'ap': 44, 'dp': 17,
'skills': ['流水行云', '披云戴月', '翻云覆雨', '排山倒海'], 'skills_hp': [23, 45, 80, 97],
'is_warrior': False, 'is_mage': True, 'is_hunter': False, },
{'index': 5, 'name': '墨魚兒', 'hp': 1000, 'mp': 1000, 'ap': 42, 'dp': 23,
'skills': ['小楫輕舟', '扁舟一葉', '大江似練', '滄波萬頃'], 'skills_hp': [19, 39, 68, 92],
'is_warrior': False, 'is_mage': False, 'is_hunter': True, }
]
```
# [插畫:一共5個角色供玩家選擇,角色名稱如下:]
其實就是把墨家村英雄榜的數據拿過來豐富了一下,添加了index和skills_hp字段。這里index表示角色的編號,skills_hp表示技能列表skills對應的傷害列表。
玩家有多種方式選擇角色,可以直接輸入角色編號直接選擇;也可以輸入角色職業比如“戰士”,程序就列出所有的戰士角色供玩家選擇;當然也輸入姓名的一部分進行模糊查詢來選擇:
```
# 選擇角色
def select_role(hero_list):
print('請輸入角色職業或角色姓名查找角色列表、輸入角色編號選擇角色。')
for hero in hero_list:
print('編號:%s,姓名:%s' % (hero.get('index'), hero.get('name')))
while True:
ni = input()
if ni == '1' or ni == '2' or ni == '3' or ni == '4' or ni == '5':
hero = hero_list[int(ni) - 1]
print('你選擇了%s' % hero.get('name'))
return hero
elif ni == '戰士':
select_roles_by_career(hero_list, 'is_warrior')
continue
elif ni == '法師':
select_roles_by_career(hero_list, 'is_mage')
continue
elif ni == '獵人':
select_roles_by_career(hero_list, 'is_hunter')
continue
else:
select_role_by_name(hero_list, ni)
continue
```
有可能玩家挑挑選選了多次才最終下了決心選哪個角色,所以這里我使用了死循環,能夠讓玩家一直挑。而如果玩家輸入了1-5中的一個,就將某個角色信息打印并使用return返回。這樣就挑選好了一個角色了。
墨哥哥:這里的select_roles_by_career和select_role_by_name就是根據職業和根據名字查找角色了對吧?
小墨:是的,這是我獨立出來的兩個方法。select_roles_by_career是按照職業選擇角色,會列出對應職業的角色。它有兩個參數,第一個是角色的列表也即所有角色,第二個是職業的標志:
```
# 列出所有該職業的角色
def select_roles_by_career(hero_list, career):
for x in hero_list:
if x.get(career):
print('編號:%s,姓名:%s' % (x.get('index'), x.get('name')))
```
select_role_by_name是模糊查詢,根據輸入的內容ni進行模糊匹配:
```
# 模糊查詢所有和輸入匹配的角色信息
def select_role_by_name(hero_list, name_like):
flag = False
for x in hero_list:
if name_like in x.get('name'):
print('編號:%s,姓名:%s' % (x.get('index'), x.get('name')))
flag = True
if not flag:
print('沒有找到對應的角色')
print('請輸入角色職業或角色姓名查找角色列表、輸入角色編號選擇角色。')
```
這里我定義了一個flag標志位,用于如果沒有任何一個角色的名字和輸入的內容相匹配的情況。比如玩家輸入了“天”,5個角色中沒有名字中含“天”的,此時就提醒用戶沒有找到對應的角色,讓他重新挑選。
墨哥哥:運行看看結果。
```
游戲開始……
歡迎來到墨家村,如今是妖獸的地盤
請輸入角色職業或角色姓名查找角色列表、輸入角色編號選擇角色。
編號:1,姓名:墨小小
編號:2,姓名:墨小妹
編號:3,姓名:墨大元
編號:4,姓名:墨當歸
編號:5,姓名:墨魚兒
戰士
編號:1,姓名:墨小小
編號:2,姓名:墨小妹
編號:3,姓名:墨大元
法師
編號:2,姓名:墨小妹
編號:4,姓名:墨當歸
大
編號:3,姓名:墨大元
天
沒有找到對應的角色
請輸入角色職業或角色姓名查找角色列表、輸入角色編號選擇角色。
墨
編號:1,姓名:墨小小
編號:2,姓名:墨小妹
編號:3,姓名:墨大元
編號:4,姓名:墨當歸
編號:5,姓名:墨魚兒
1
你選擇了墨小小
```
嗯,看起來不錯嘛。
小墨:哈哈,再接著來看我的戰斗過程。之前是和狂風戰斗,這一版我也改了,改成了一共5個關卡,每個關卡都有一個boss守著,玩家需要連續戰勝5個boss才能奪回墨家村。5個boss相關的數據是這樣的:
```
boss_list = [
{'mission_index': 1, 'mission_name': '呼嘯山谷', 'name': '狂風', 'hp': 100, 'max_attack': 200, 'min_attack': 100},
{'mission_index': 2, 'mission_name': '暴雨中的十里鋪', 'name': '狂雨', 'hp': 200, 'max_attack': 200, 'min_attack': 20},
{'mission_index': 3, 'mission_name': '雷暴下的墨河下游', 'name': '狂雷', 'hp': 500, 'max_attack': 100, 'min_attack': 90},
{'mission_index': 4, 'mission_name': '雷暴下的墨河上游', 'name': '狂電', 'hp': 1000, 'max_attack': 220, 'min_attack': 50},
{'mission_index': 5, 'mission_name': '燃燒的墨家村', 'name': '狂火', 'hp': 10000, 'max_attack': 20, 'min_attack': 10}
]
```
其中mission_index表示關卡編號,mission_name表示關卡名字,name表示這一關的boss的名字,max_attack表示這一關boss的最大攻擊力,min_attack是最小攻擊力,也就是說每一關大的boss都會隨機攻擊,范圍就是這兩個值之間。
墨哥哥:嗯,劇情不錯,原來你也很能編故事。
小墨:這不都是跟你學的嘛。
接著我定義了一個方法,用于和boss戰斗:
```
# 戰斗:某一關卡
def fight(hero, boss):
print('你來到了第%s關:%s。本關boss:%s' % (boss.get('mission_index'), boss.get('mission_name'), boss.get('name')))
# 根據傳入的角色,獲取角色的技能列表、技能傷害列表和角色的血量
skills = hero.get('skills')
skills_hp = hero.get('skills_hp')
hp_player = hero.get('hp')
# 根據傳入的boss,獲取boss的名稱和boss的血量
name_boss = boss.get('name')
hp_boss = boss.get('hp')
while True:
print('快輸入數字攻擊他!')
# 介紹角色技能
for i in range(len(skills)):
print('輸入數字%s釋放第%s個技能:%s' % (i + 1, i + 1, skills[i]))
# 接收用戶輸入的數字
input_ni = int(input())
# 如果是1-5
if input_ni == 1 or input_ni == 2 or input_ni == 3 or input_ni == 4 or input_ni == 5:
# 玩家的隨機攻擊傷害值:技能對應的傷害加上1-50的隨機值
attack_player = random.randint(1, 50) + skills_hp[input_ni - 1]
# boss扣血
hp_boss -= attack_player
# 如果boss血量在被攻擊之后小于0了則將血量置為0,防止輸出boss血量為負的情況
if hp_boss < 0:
hp_boss = 0
print(
"你使用%s擊中了%s,打出了%s點的傷害,%s剩余血量%s" % (skills[input_ni - 1], name_boss, attack_player, name_boss, hp_boss))
if hp_boss > 0: # 判斷boss是否已死,血量大于0說明還活著,活著就會反擊
# boss的隨機反擊傷害值
attack_boss = random.randint(boss.get('min_attack'), boss.get('max_attack'))
# 玩家扣血
hp_player -= attack_boss
# 如果玩家血量在被攻擊之后小于0了則將血量置為0,防止輸出血量為負的情況
if hp_player < 0:
hp_player = 0
print("憤怒的%s發起了反擊,對你造成了%s點傷害,你當前剩余血量%s" % (name_boss, attack_boss, hp_player))
if hp_player == 0: # 判斷玩家是否已死
return False
else:
# 更新角色血量
hero['hp'] = hp_player
else:
print("%s,恭喜你,擊敗了%s!完成了本關卡的挑戰" % (hero.get('name'), name_boss))
# 如果過關,獎勵本關編號*200的血量
hero['hp'] = hp_player + int(boss.get('mission_index')) * 200
print('*' * 50)
return True
# 如果用戶輸入的不是1-5,則提醒用戶
else:
print('快輸入數字鍵1-5攻擊%s!' % name_boss)
```
這個方法接收兩個參數,一個hero表示用戶選擇的角色,這個實際調用時候傳入挑選好的角色就行了。第二個參數是boss,也即boss列表中的某一個。這個方法只是和1個boss進行戰斗,想跟所有boss都戰斗一遍,還是用循環,我定義了fight_all_boss的方法:
```
# 戰斗:所有關卡
def fight_all_boss(hero, boss_list):
for boss in boss_list:
if not fight(hero, boss):
print("很遺憾,你未能完成冒險,請休息片刻重新開始。。。")
break # 結束游戲
```
在和某一個boss戰斗過程中,肯定會有失敗的情況,這個時候游戲就應該結束了。所以我在fight方法中,如果用戶血量小于0,就返回False,結束fight方法。在fight_all_boss中,如果not fight,也即fight返回False的情況,就結束游戲。而如果fight沒有返回False,則說明過關了,fight_all_boss就繼續循環,從而玩家繼續戰斗。
打斗結果如下:
```
你來到了第1關:呼嘯山谷。本關boss:狂風
快輸入數字攻擊他!
輸入數字1釋放第1個技能:一墨橫空
輸入數字2釋放第2個技能:墨渡迷津
輸入數字3釋放第3個技能:墨之縱橫
輸入數字4釋放第4個技能:墨下乾坤
4
你使用墨下乾坤擊中了狂風,打出了143點的傷害,狂風剩余血量0
墨小小,恭喜你,擊敗了狂風!完成了本關卡的挑戰
**************************************************
你來到了第2關:暴雨中的十里鋪。本關boss:狂雨
快輸入數字攻擊他!
輸入數字1釋放第1個技能:一墨橫空
輸入數字2釋放第2個技能:墨渡迷津
輸入數字3釋放第3個技能:墨之縱橫
輸入數字4釋放第4個技能:墨下乾坤
4
你使用墨下乾坤擊中了狂雨,打出了145點的傷害,狂雨剩余血量55
憤怒的狂雨發起了反擊,對你造成了129點傷害,你當前剩余血量1071
快輸入數字攻擊他!
輸入數字1釋放第1個技能:一墨橫空
輸入數字2釋放第2個技能:墨渡迷津
輸入數字3釋放第3個技能:墨之縱橫
輸入數字4釋放第4個技能:墨下乾坤
4
你使用墨下乾坤擊中了狂雨,打出了141點的傷害,狂雨剩余血量0
墨小小,恭喜你,擊敗了狂雨!完成了本關卡的挑戰
**************************************************
你來到了第3關:雷暴下的墨河下游。本關boss:狂雷
快輸入數字攻擊他!
輸入數字1釋放第1個技能:一墨橫空
輸入數字2釋放第2個技能:墨渡迷津
輸入數字3釋放第3個技能:墨之縱橫
輸入數字4釋放第4個技能:墨下乾坤
…… (篇幅原因,這里不再全部列出)
```
為了游戲的趣味性和平衡性,我還在每一關卡過關的時候獎勵玩家關卡編號乘以200的血量。
墨哥哥:整體來說還是很不錯的。不過你這個應該還沒有做完吧,按照目前的代碼,玩家一直輸入4攻擊boss就行了,因為技能4是傷害最大的。
小墨:嗯我還沒有做完呢。你看角色有個mp,表示角色的魔法量,釋放技能是需要消耗魔法的,后面會從這一塊做限制。另外現在玩家是隨機攻擊,后面攻擊力也會去使用ap的值,那是定義的攻擊力。還有dp表示防御力,這個我得想想怎么個計算法,讓防御力能抵消boss的部分傷害。
墨哥哥:嗯那樣的話就完整多了。對了,你要問我什么問題來著?
小墨:是這樣的,除了上面需要做的完善之外,我還想加入個保存游戲的功能,比如游戲開始玩家選擇了墨小小,此時玩家應該能保存游戲進度,這樣下次進來就能繼續使用墨小小了;再比如玩家已經探險到第3關了,這時他有事要出去,就需要保存下游戲進度,要不然下次進來又要從第一關開始了。想問的就是,這個保存游戲怎么做?
墨哥哥:程序運行之后,所有的數據都在內存中,程序運行結束之后數據也就從內存中清除了。只有硬盤上的東西是一直存在的,你看你每天開機關機,硬盤上的文件一直存在吧。
小墨:也就是說想要保存的話就是保存到硬盤上的文件里,這樣才能一直存在對嗎?
墨哥哥:是的。
小墨:那如何將程序中的內容保存到文件中呢?
墨哥哥:這就要用到Python中IO流方面的知識了。
## 9.2 IO流
墨哥哥:所謂IO流,就是輸入(In)輸出(Out)流的簡寫。流是個什么東西呢?以你現在想做的保存玩家數據的功能來說。本來玩家數據在程序里,現在你想把它保存在文件中,如果你把程序看做一個湖,把文件也看做是一個湖,那么問題就變成了如何將程序湖中的水“放”到文件湖中。如何放呢?很簡單,我們在兩個湖之間挖條小河,讓程序湖中的水經過這條小河流到文件湖中就可以了。這條小河就是“流”。
# [插畫:兩個湖,被一條河連接了起來]
小墨:那什么是輸入輸出流呢?
墨哥哥:所謂輸入輸出,其實就是這條河中水流的方向。如果我們以程序湖為參照物,那么從程序湖流向文件湖就稱為輸出,對應這條小河就是輸出流;從文件湖流向程序湖,就稱為輸入,對應小河就是輸入流。而如果我們以文件湖為參照物,那么程序湖流向文件湖就是輸入,文件湖流向程序湖就是輸出。
小墨:參照物不同,叫法也不同。
墨哥哥:嗯為了避免參照物混亂導致名稱混亂,只要固定一方為參照物就行了。由于我們是程序的編寫者,就固定程序為參照物。
小墨:那也就是說從程序到文件的稱為輸出流、從文件到程序的叫輸入流。
墨哥哥:是的。另外從程序中拿文件中的內容的過程,稱為“讀”,對應的將程序中的內容放入文件中的過程,稱為“寫”。
小墨:明白了。
墨哥哥:在Python中,想使用輸出流,也即想把程序中的內容保存到文件中,使用with open語法就可以了:
```
with open('D:/file/role.txt', 'w') as f:
f.write('1')
```
這里的open是Python自帶的一個函數,它既可以用來建立輸入流也可以用來建立輸出流。它的第一個參數是要讀或寫的文件的路徑,第二個參數w是write的簡寫,表示建立輸出流。as用來給open('D://file//role.txt', 'w')起個別名,f就是我起的名字,可以任意。這樣一句之后,f就表示建立好的輸出流了。接著調用f的write方法就可以將內容寫到文件中了。
小墨:我來運行一下。啊,悲劇了……
```
Traceback (most recent call last):
File "D:/my_python/write_demo.py", line 1, in <module>
with open('D:/file/role.txt', 'w') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'D:/file/role.txt'
```
墨哥哥:這是因為你D盤下沒有file這個文件夾。輸出流會自動幫你建立好要輸出的文件,但是并不會新建文件夾。另外需要注意的是,在windows系統中,路徑可以寫作“D:/file/role.txt”或“D:\\\file\\\role.txt”,而不能寫成“D:\file\role.txt”。
小墨:這個是轉義字符,我曾經聽博士說過。現在我在電腦D盤新建一個文件夾,名字叫file,然后再運行,這次可以了!file中多了個role.txt,里面有個數字1。
墨哥哥:和寫數據類似,讀程序也非常簡單:
```
with open('D://file//role.txt', 'r') as f:
print(f.read())
```
這里open的第二個參數r就是read的意思,表示從文件中讀取數據。需要注意的是,讀取的文件需要存在,要不然也會出錯的。
小墨:好的我已經明白了。我這就去把我的游戲添加存儲數據的功能。
先來定義一個方法,用于存儲用戶數據,只存儲用戶的編號就行了,拿到編號就可以從角色列表中拿到角色對應的所有數據了:
```
def save_role(save_path, role_index):
with open(save_path, 'w') as f:
f.write(role_index)
```
然后定義一個方法,用于將存儲的用戶編號取出來:
```
def get_role_index(save_path):
with open(save_path, 'r') as f:
return f.read()
```
然后在游戲開始的時候加個判斷,判斷玩家是想重新開始游戲重新挑選角色,還是想從存儲的文件中獲取角色編號,然后從角色列表中獲取該角色。同時需要注意下可能文件是空的里面什么都沒有,這時候玩家只能重新挑選角色了:
```
print('重新開始請輸入Y,取出存儲的角色請輸入Q')
input_str = input();
if input_str == 'Y':
hero = select_role(hero_list)
elif input_str == 'Q':
# 獲取存儲角色編號
index = get_role_index("D://file/role.txt")
if len(index) == 0: # 文件中內容為空,也即沒有存儲角色數據
print('沒有存儲的角色')
hero = select_role(hero_list)
else:
print('進度讀取成功')
hero = hero_list[int(index) - 1]
print('編號:%s,姓名:%s' % (hero.get('index'), hero.get('name')))
```
好了,這樣我的游戲就加入了保存角色的功能了。
# [插畫:進度條:游戲正在存檔中……]
完整代碼如下:
```
import random
# 背景介紹
def background():
print("游戲開始……")
print("歡迎來到墨家村,如今是妖獸的地盤")
# 選擇角色
def select_role(hero_list):
print('請輸入角色職業或角色姓名查找角色列表、輸入角色編號選擇角色。')
for hero in hero_list:
print('編號:%s,姓名:%s' % (hero.get('index'), hero.get('name')))
while True:
ni = input()
if ni == '1' or ni == '2' or ni == '3' or ni == '4' or ni == '5':
hero = hero_list[int(ni) - 1]
print('你選擇了%s' % hero.get('name'))
# 存儲角色數據
save_role('D://file/role.txt', str(hero.get('index')))
return hero
elif ni == '戰士':
select_roles_by_career(hero_list, 'is_warrior')
continue
elif ni == '法師':
select_roles_by_career(hero_list, 'is_mage')
continue
elif ni == '獵人':
select_roles_by_career(hero_list, 'is_hunter')
continue
else:
select_role_by_name(hero_list, ni)
continue
def select_roles_by_career(hero_list, career):
for x in hero_list:
if x.get(career):
print('編號:%s,姓名:%s' % (x.get('index'), x.get('name')))
def select_role_by_name(hero_list, name_like):
flag = False
for x in hero_list:
if name_like in x.get('name'):
print('編號:%s,姓名:%s' % (x.get('index'), x.get('name')))
flag = True
if not flag:
print('沒有找到對應的角色')
print('請輸入角色職業或角色姓名查找角色列表、輸入角色編號選擇角色。')
# 打斗
def fight(hero, boss):
print('你來到了第%s關:%s。本關boss:%s' % (boss.get('mission_index'), boss.get('mission_name'), boss.get('name')))
skills = hero.get('skills')
skills_hp = hero.get('skills_hp')
hp_player = hero.get('hp')
name_boss = boss.get('name')
hp_boss = boss.get('hp')
while True:
print('快輸入數字攻擊他!')
# 介紹角色技能
for i in range(len(skills)):
print('輸入數字%s釋放第%s個技能:%s' % (i + 1, i + 1, skills[i]))
# 接收用戶輸入的數字
input_ni = int(input())
# 如果是1-5
if input_ni == 1 or input_ni == 2 or input_ni == 3 or input_ni == 4 or input_ni == 5:
# 玩家的隨機攻擊傷害值:技能對應的傷害加上1-5的隨機值
attack_player = random.randint(1, 50) + skills_hp[input_ni - 1]
# boss扣血
hp_boss -= attack_player
# 如果boss血量在被攻擊之后小于0了則將血量置為0,防止輸出boss血量為負的情況
if hp_boss < 0:
hp_boss = 0
print(
"你使用%s擊中了%s,打出了%s點的傷害,%s剩余血量%s" % (skills[input_ni - 1], name_boss, attack_player, name_boss, hp_boss))
if hp_boss > 0: # 判斷boss是否已死,血量大于0說明還活著,活著就會反擊
# boss的隨機反擊傷害值
attack_boss = random.randint(boss.get('min_attack'), boss.get('max_attack'))
# 玩家扣血
hp_player -= attack_boss
# 如果玩家血量在被攻擊之后小于0了則將血量置為0,防止輸出血量為負的情況
if hp_player < 0:
hp_player = 0
print("憤怒的%s發起了反擊,對你造成了%s點傷害,你當前剩余血量%s" % (name_boss, attack_boss, hp_player))
if hp_player == 0: # 判斷玩家是否已死
return False
else:
# 更新角色血量
hero['hp'] = hp_player
else:
print("%s,恭喜你,擊敗了%s!完成了本關卡的挑戰" % (hero.get('name'), name_boss))
# 如果過關,獎勵本關*200的血量
hero['hp'] = hp_player + int(boss.get('mission_index')) * 200
# 保存本關
print('*' * 50)
return True
# 如果用戶輸入的不是1-5,則提醒用戶
else:
print('快輸入數字鍵1-5攻擊%s!' % name_boss)
def fight_all_boss(hero, boss_list):
for boss in boss_list:
if not fight(hero, boss):
print("很遺憾,你未能完成冒險,請休息片刻重新開始。。。")
break # 結束游戲
def get_role_index(save_path):
with open(save_path, 'r') as f:
return f.read()
def save_role(save_path, role_index):
with open(save_path, 'w') as f:
f.write(role_index)
def main():
background()
hero_list = [
{'index': 1, 'name': '墨小小', 'hp': 1000, 'mp': 800, 'ap': 45, 'dp': 20,
'skills': ['一墨橫空', '墨渡迷津', '墨之縱橫', '墨下乾坤'], 'skills_hp': [20, 45, 75, 100],
'is_warrior': True, 'is_mage': False, 'is_hunter': False, },
{'index': 2, 'name': '墨小妹', 'hp': 1200, 'mp': 700, 'ap': 35, 'dp': 21,
'skills': ['貂蟬拜月', '西施捧心', '昭君出塞', '貴妃醉酒'], 'skills_hp': [18, 23, 47, 82],
'is_warrior': True, 'is_mage': True, 'is_hunter': False, },
{'index': 3, 'name': '墨大元', 'hp': 1100, 'mp': 600, 'ap': 38, 'dp': 17,
'skills': ['千里橫行', '寒刀斷水', '狂龍破日', '天地無情'], 'skills_hp': [26, 51, 80, 102],
'is_warrior': True, 'is_mage': False, 'is_hunter': True, },
{'index': 4, 'name': '墨當歸', 'hp': 900, 'mp': 1100, 'ap': 44, 'dp': 17,
'skills': ['流水行云', '披云戴月', '翻云覆雨', '排山倒海'], 'skills_hp': [23, 45, 80, 97],
'is_warrior': False, 'is_mage': True, 'is_hunter': False, },
{'index': 5, 'name': '墨魚兒', 'hp': 1000, 'mp': 1000, 'ap': 42, 'dp': 23,
'skills': ['小楫輕舟', '扁舟一葉', '大江似練', '滄波萬頃'], 'skills_hp': [19, 39, 68, 92],
'is_warrior': False, 'is_mage': False, 'is_hunter': True, }
]
print('重新開始請輸入Y,取出存儲的角色請輸入Q')
input_str = input();
if input_str == 'Y':
hero = select_role(hero_list)
elif input_str == 'Q':
# 獲取存儲角色編號
index = get_role_index("D://file/role.txt")
if len(index) == 0:
print('沒有存儲的角色')
hero = select_role(hero_list)
else:
print('進度讀取成功')
hero = hero_list[int(index) - 1]
print('編號:%s,姓名:%s' % (hero.get('index'), hero.get('name')))
boss_list = [
{'mission_index': 1, 'mission_name': '呼嘯山谷', 'name': '狂風', 'hp': 100, 'max_attack': 200, 'min_attack': 100},
{'mission_index': 2, 'mission_name': '暴雨中的十里鋪', 'name': '狂雨', 'hp': 200, 'max_attack': 200, 'min_attack': 20},
{'mission_index': 3, 'mission_name': '雷暴下的墨河下游', 'name': '狂雷', 'hp': 500, 'max_attack': 100, 'min_attack': 90},
{'mission_index': 4, 'mission_name': '雷暴下的墨河上游', 'name': '狂電', 'hp': 1000, 'max_attack': 220, 'min_attack': 50},
{'mission_index': 5, 'mission_name': '燃燒的墨家村', 'name': '狂火', 'hp': 10000, 'max_attack': 20, 'min_attack': 10}
]
fight_all_boss(hero, boss_list)
# 調用main方法
main()
```
墨哥哥:寫的挺快的嘛!今天天色還早,你繼續完善你的游戲吧。
## 9.3 本章小結
墨哥哥總結:本章主要學習了兩方面的內容:
* 一是函數的使用。在上一章中墨博士說過,學習函數之后解決問題的思路就變了:把大問題分成小問題,小問題解決了大問題就解決了。但是思路的形成并不是一朝一夕就可以的,這個還需要你多多練習才是。
* 二是IO流的使用,這個最重要的是搞清水流的方向。
最后,在本章中小墨的《小墨歷險記》還有一些功能沒有完成,小讀者們,你能和小墨一起來完成嗎?