大爽Python入门公开课教案 点击查看教程总目录
不知道大家有没有玩过魔塔。
在我小时候,这是一个很经典又好玩的小游戏。
其实最早想做一个控制台版本的简易魔塔。
后来发现控制台实现的效果实在是不理想,而且耗费的精力又颇大。
总的来讲,就是费力不讨好。
所以做了更进一步的简化,用控制台只实现简化了的回合战斗。
功能大概有两处:
玩家和敌人都属于人,有以下三个基本属性(以下建成三维)
hp
attack
defence
都有一个基本方法
打击(攻击): hit
攻击的基本计算方式为: 伤害 = 自己攻击力 - 对手防御力
伤害为正时,扣除敌人对应血量。
是否存活: is_alive
即血量大于 0
玩家特有属性
敌人特有方法
drop_exp
敌人分三档
这个可以自由发挥
我这里的设置如下
玩家
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
首先需要实现一个基础的人物类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
代码如下
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()
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
最后总代码如下
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()