大爽Python入门公开课教案 点击查看教程总目录
1 背景介绍
不知道大家有没有玩过魔塔。
在我小时候,这是一个很经典又好玩的小游戏。
其实最早想做一个控制台版本的简易魔塔。
后来发现控制台实现的效果实在是不理想,而且耗费的精力又颇大。
总的来讲,就是费力不讨好。
所以做了更进一步的简化,用控制台只实现简化了的回合战斗。
功能大概有两处:
- 输入命令,获取玩家信息或者退出游戏。
- 输入敌人,让玩家和敌人战斗,将战斗结果展示出来。
2 详细说明
人
玩家和敌人都属于人,有以下三个基本属性(以下建成三维)
- 血量:
hp
- 攻击力:
attack
- 防御力:
defence
都有一个基本方法
-
打击(攻击):
hit
攻击的基本计算方式为: 伤害 = 自己攻击力 - 对手防御力
伤害为正时,扣除敌人对应血量。 -
是否存活:
is_alive
即血量大于 0
玩家特有属性
- 等级: lv
初始等级为1。
每升一级,血量恢复。三维翻倍。 - 经验: exp
该值分两部分,一个是当前经验,一个是升级经验。
当前经验够升级时,扣除升级经验并升级。
每升一级,所需升级经验翻倍。
敌人特有方法
- 经验掉落:
drop_exp
该方法返回经验值,战胜敌人即可获得该经验值。
敌人分三档
- 普通敌人
- 高级敌人: 攻击时,无视玩家防御(即伤害=攻击力)
- BOSS: 攻击时,无视玩家防御(即伤害=攻击力),还能自己回血(回血量=伤害量)
数值设置
这个可以自由发挥
我这里的设置如下
玩家
hp, attack, defence = 100, 10, 5
exp = 0 / 20
普通敌人
hp, attack, defence = 50, 10, 5
掉落经验值:10
高级敌人
hp, attack, defence = 100, 20, 10
掉落经验值:20
BOSS
hp, attack, defence = 200, 40, 20
掉落经验值:40
游戏流程
运行游戏,先展示欢迎信息。
Welcome to my game.
再展示玩家信息
======= Player status ========
HP: 100 / 100
Attack: 10
Defence: 10
Lv: 1. EXP: 0/ 20
==============================
接着提醒用户输入
Enter your command:
玩家可以输入命令,或者敌人
可解析的命令如下
s
: 展示玩家信息q
: 退出游戏
退出游戏时,输出如下
Bye.
可解析的敌人如下
e
:Enemy
,普通敌人a
:AdvancedEnemy
, 高级敌人b
:Boss
, 老怪
输入敌人,则让玩家和敌人战斗,
战斗流程是,玩家先攻击敌人,然后敌人再攻击玩家,直至一方死亡。
战胜敌人时,输出战胜信息如下(包括敌人种类,获得经验,当前经验,剩余血量)
(比如战胜普通敌人)
Defeat enemy: Enemy. Gain exp: 10. Current exp: 10 / 20. Left hp: 55
战斗过程中,如果有升级,则输出升级信息如下
You upgraded, current level: 2, current hp: 200.
战斗失败,输出失败信息如下,且结束游戏
You lost. Boss's left hp: 100
可以一次输入多个敌人,玩家从前往后依次战斗。
运行效果
输入分别是
e
e
a
b
运行效果如下
Welcome to my game.
======= Player status ========
HP: 100 / 100
Attack: 10
Defence: 10
Lv: 1. EXP: 0/ 20
==============================
Enter your command:e
Defeat enemy: Enemy. Gain exp: 10. Current exp: 10 / 20. Left hp: 55
Enter your command:e
Defeat enemy: Enemy. Gain exp: 10. Current exp: 20 / 20. Left hp: 10
You upgraded, current level: 2, current hp: 200.
Enter your command:a
Defeat enemy: AdvancedEnemy. Gain exp: 20. Current exp: 20 / 40. Left hp: 20
Enter your command:s
======= Player status ========
HP: 20 / 200
Attack: 20
Defence: 20
Lv: 2. EXP: 20/ 40
==============================
Enter your command:b
You lost. Boss's left hp: 240
3 分析
类的构思
首先需要实现一个基础的人物类Person
然后继承Person
实现玩家类Player
之后继承Person
实现敌人类:
Enemy
,AdvancedEnemy
和Boss
。
人物类就这些。
最后将游戏的处理也放在一个类Game
里去进行。
初步架构
class Person:
pass
class Player(Person):
pass
class Enemy(Person):
pass
class AdvancedEnemy(Enemy):
pass
class Boss(Enemy):
pass
class Game:
pass
4 逐步实现
基础类Person
代码如下
class Person:
def __init__(self, hp, attack, defence):
self.hp = hp
self.attack = attack
self.defence = defence
def hit(self, other):
damage = self.attack - other.defence
if damage > 0:
other.hp -= damage
def is_alive(self):
return self.hp > 0
玩家类Player
class Player(Person):
def __init__(self):
hp, attack, defence = 100, 10, 5
super().__init__(hp, attack, defence)
self.lv = 1
self.base_hp = self.hp # base_hp: 当前等级总HP, 升级时是这个翻倍
self.exp = [0, 20] # 第一个是现有经验,第二个是升级需要的总经验。
def show_info(self):
"""
展示玩家信息。
效果示例如下:
======= Player status ========
HP: 20 / 200
Attack: 20
Defence: 20
Lv: 2. EXP: 20/ 40
==============================
"""
print("{:=^30s}".format(" Player status "))
print("HP: %s / %s" % (self.hp, self.base_hp))
print("Attack: %s" % self.attack)
print("Defence: %s" % self.attack)
print("Lv: %s. EXP: %s / %s" % (self.lv, self.exp[0], self.exp[1]))
print("=" * 30)
def win(self, enemy):
exp = enemy.drop_exp()
self.exp[0] += enemy.drop_exp()
print("Defeat enemy: %s. Gain exp: %s. Current exp: %s / %s. Left hp: %s" %
(enemy.__class__.__name__, exp, self.exp[0], self.exp[1] ,self.hp))
if self.exp[0] >= self.exp[1]:
self.exp[0] -= self.exp[1] # 升级时扣除升级需要的经验
self.lv_up()
def lv_up(self):
self.exp[1] = self.exp[1] * 2 # 每升一级,升级时需要的经验翻倍
self.lv += 1
# 每升一级,三维翻倍
self.base_hp = self.base_hp * 2
self.attack = self.attack * 2
self.defence = self.defence * 2
# 升级后,恢复满血
self.hp = self.base_hp
print("You upgraded, current level: %s, current hp: %s." % (self.lv, self.hp))
def lose(self, enemy):
print("You lost. %s's left hp: %s" % (enemy.__class__.__name__, enemy.hp))
其中,有这样一个语法
enemy.__class__.__name__
enemy.__class__
: 作用是得到enemy
这个对象object
的类__class__
class.__name__
: 作用是得到一个类class
的名字(字符串形式)
使用示例如下
class AAA:
pass
a = AAA()
print(a.__class__)
print(a.__class__ == AAA)
print(a.__class__.__name__)
print(AAA.__name__)
输出为
<class '__main__.AAA'>
True
AAA
AAA
敌人类
三种敌人代码如下
Enemy
类
class Enemy(Person):
def __init__(self, base=1):
hp, attack, defence = 50 * base, 10 * base, 5 * base
super().__init__(hp, attack, defence)
self.exp = 10 * base
def drop_exp(self):
return self.exp
AdvancedEnemy
类
class AdvancedEnemy(Enemy):
def __init__(self):
super().__init__(base=2)
def hit(self, other):
damage = self.attack
if damage > 0:
other.hp -= damage
Boss
类
class Boss(Enemy):
def __init__(self):
super().__init__(base=4)
def hit(self, other):
damage = self.attack
if damage > 0:
other.hp -= damage
self.hp += damage
游戏类Game
class Game:
def __init__(self):
self.player = Player()
def run(self):
print("Welcome to my game.")
self.player.show_info()
while True:
cmd = input("Enter your command:")
cmd = cmd.lower()
if cmd == "s":
self.player.show_info()
elif cmd == "q":
print("Bye")
return
else:
self.handle_commands(cmd)
def handle_commands(self, cmd):
for c in cmd:
if c == "e":
enemy = Enemy()
elif c == "a":
enemy = AdvancedEnemy()
elif c == "b":
enemy = Boss()
else:
print("Invalid Input.")
return
self.fight(enemy)
def fight(self, enemy):
while True:
self.player.hit(enemy)
if not enemy.is_alive():
self.player.win(enemy)
return
enemy.hit(self.player)
if not self.player.is_alive():
self.player.lose(enemy)
exit()
调用
调用起来非常简单
game = Game()
game.run()
4 优化
Game
类的handle_commands(self, cmd)
方法中,
条件判断有些罗嗦,如果敌人类增加,则又要增加。
有的语言有case
语法,能简化这里。
python虽然没有这个语法,但是有办法实现对应效果,甚至更简单。
优化方法如下
先在之前的空白处添加变量enemy_map
如下
enemy_map = {
"e": Enemy,
"a": AdvancedEnemy,
"b": Boss,
}
再修改handle_commands(self, cmd)
方法如下
def handle_commands(self, cmd):
for c in cmd:
if c in enemy_map:
enemy_class = enemy_map[c]
enemy = enemy_class()
self.fight(enemy)
else:
print("Invalid Input.")
return
5 总代码
最后总代码如下
class Person:
def __init__(self, hp, attack, defence):
self.hp = hp
self.attack = attack
self.defence = defence
def hit(self, other):
damage = self.attack - other.defence
if damage > 0:
other.hp -= damage
def is_alive(self):
return self.hp > 0
class Player(Person):
def __init__(self):
hp, attack, defence = 100, 10, 5
super().__init__(hp, attack, defence)
self.lv = 1
self.base_hp = self.hp # base_hp: 当前等级总HP, 升级时是这个翻倍
self.exp = [0, 20] # 第一个是现有经验,第二个是升级需要的总经验。
def show_info(self):
"""
展示玩家信息。
效果示例如下:
======= Player status ========
HP: 20 / 200
Attack: 20
Defence: 20
Lv: 2. EXP: 20/ 40
==============================
"""
print("{:=^30s}".format(" Player status "))
print("HP: %s / %s" % (self.hp, self.base_hp))
print("Attack: %s" % self.attack)
print("Defence: %s" % self.attack)
print("Lv: %s. EXP: %s / %s" % (self.lv, self.exp[0], self.exp[1]))
print("=" * 30)
def win(self, enemy):
exp = enemy.drop_exp()
self.exp[0] += enemy.drop_exp()
print("Defeat enemy: %s. Gain exp: %s. Current exp: %s / %s. Left hp: %s" %
(enemy.__class__.__name__, exp, self.exp[0], self.exp[1], self.hp))
if self.exp[0] >= self.exp[1]:
self.exp[0] -= self.exp[1] # 升级时扣除升级需要的经验
self.lv_up()
def lv_up(self):
self.exp[1] = self.exp[1] * 2 # 每升一级,升级时需要的经验翻倍
self.lv += 1
# 每升一级,三维翻倍
self.base_hp = self.base_hp * 2
self.attack = self.attack * 2
self.defence = self.defence * 2
# 升级后,恢复满血
self.hp = self.base_hp
print("You upgraded, current level: %s, current hp: %s." % (self.lv, self.hp))
def lose(self, enemy):
print("You lost. %s's left hp: %s" % (enemy.__class__.__name__, enemy.hp))
class Enemy(Person):
def __init__(self, base=1):
hp, attack, defence = 50 * base, 10 * base, 5 * base
super().__init__(hp, attack, defence)
self.exp = 10 * base
def drop_exp(self):
return self.exp
class AdvancedEnemy(Enemy):
def __init__(self):
super().__init__(base=2)
def hit(self, other):
damage = self.attack
if damage > 0:
other.hp -= damage
class Boss(Enemy):
def __init__(self):
super().__init__(base=4)
def hit(self, other):
damage = self.attack
if damage > 0:
other.hp -= damage
self.hp += damage
enemy_map = {
"e": Enemy,
"a": AdvancedEnemy,
"b": Boss,
}
class Game:
def __init__(self):
self.player = Player()
def run(self):
print("Welcome to my game.")
self.player.show_info()
while True:
cmd = input("Enter your command:")
cmd = cmd.lower()
if cmd == "s":
self.player.show_info()
elif cmd == "e":
print("Bye")
return
else:
self.handle_commands(cmd)
def handle_commands(self, cmd):
for c in cmd:
if c in enemy_map:
enemy_class = enemy_map[c]
enemy = enemy_class()
self.fight(enemy)
else:
print("Invalid Input.")
return
def fight(self, enemy):
while True:
self.player.hit(enemy)
if not enemy.is_alive():
self.player.win(enemy)
return
enemy.hit(self.player)
if not self.player.is_alive():
self.player.lose(enemy)
exit()
game = Game()
game.run()