把理论变成游戏,面向对象的三大特性在这一刻全活了。
👋 你好,我是 Evan ,一名计算机专业的学长,也是《大一突围》专栏的作者。学完封装、继承、多态,你可能还是有点懵------这些东西到底怎么用?今天我们不背概念,直接动手写一个 怪物战斗小游戏 。你将看到:Monster 父类怎么设计,Dragon、Goblin 怎么继承,fight() 方法如何体现多态。我会同时给出 Python 和 Java 两个版本的代码,让你对比感受。
欢迎来到 《大一突围》 专栏。

一、游戏设计:我们要做什么?

核心玩法:
-
玩家从三种怪物中选择一只:Dragon(龙) 、Goblin(哥布林) 、Slime(史莱姆)。
-
玩家选择与电脑控制的怪物对战。
-
每回合玩家选择攻击或使用技能,电脑随机攻击。
-
一方 HP 降到 0 以下,战斗结束。
涉及 OOP 概念:
-
封装:怪物的 HP、攻击力、技能名私有,通过方法访问。
-
继承 :所有怪物继承自抽象类
Monster。 -
多态 :
fight()方法根据怪物类型执行不同逻辑,技能效果各异。
二、UML 类图设计

-
父类
Monster定义了所有怪物的通用属性和方法。 -
子类重写
useSkill(),实现各自的技能效果。
三、Python 版本实现(简洁易懂)
3.1 父类 Monster
python
class Monster:
def __init__(self, name, hp, attack_power, skill_name):
self._name = name # 封装:私有属性(约定)
self._hp = hp
self._attack_power = attack_power
self._skill_name = skill_name
def take_damage(self, damage):
self._hp -= damage
if self._hp < 0:
self._hp = 0
def is_alive(self):
return self._hp > 0
def attack(self, target):
damage = self._attack_power
target.take_damage(damage)
print(f"{self._name} 发动普通攻击,造成 {damage} 伤害!")
def use_skill(self, target):
# 由子类实现
pass
# getter 方法
def get_name(self):
return self._name
def get_hp(self):
return self._hp
def get_skill_name(self):
return self._skill_name
3.2 子类 Dragon
python
python
class Dragon(Monster):
def __init__(self):
super().__init__("炎龙", 150, 25, "烈焰吐息")
def use_skill(self, target):
damage = 40
target.take_damage(damage)
print(f"{self._name} 使用 {self._skill_name},造成 {damage} 伤害!")
3.3 子类 Goblin
python
python
class Goblin(Monster):
def __init__(self):
super().__init__("哥布林", 80, 20, "偷袭")
def use_skill(self, target):
damage = 35
target.take_damage(damage)
print(f"{self._name} 使用 {self._skill_name},造成 {damage} 伤害!")
3.4 子类 Slime
python
python
class Slime(Monster):
def __init__(self):
super().__init__("史莱姆", 120, 15, "腐蚀酸液")
def use_skill(self, target):
damage = 30
target.take_damage(damage)
print(f"{self._name} 使用 {self._skill_name},造成 {damage} 伤害!")
3.5 战斗逻辑(多态的体现)
python
python
def battle(player_monster, computer_monster):
print(f"\n战斗开始!")
print(f"你的 {player_monster.get_name()} VS 电脑的 {computer_monster.get_name()}")
turn = 0
while player_monster.is_alive() and computer_monster.is_alive():
turn += 1
print(f"\n=== 第{turn}回合 ===")
# 玩家回合
action = input("选择 1-普通攻击 2-技能: ")
if action == '1':
player_monster.attack(computer_monster)
else:
player_monster.use_skill(computer_monster)
if not computer_monster.is_alive():
print(f"{computer_monster.get_name()} 倒下了!你赢了!")
break
# 电脑回合(随机选择攻击或技能)
import random
if random.choice([True, False]):
computer_monster.attack(player_monster)
else:
computer_monster.use_skill(player_monster)
if not player_monster.is_alive():
print(f"{player_monster.get_name()} 倒下了!你输了...")
break
print(f"你的 {player_monster.get_name()} HP: {player_monster.get_hp()}")
print(f"电脑 {computer_monster.get_name()} HP: {computer_monster.get_hp()}")
3.6 主函数
python
python
def main():
print("选择你的怪物:")
print("1. 炎龙 (高攻击、高血量)")
print("2. 哥布林 (平衡)")
print("3. 史莱姆 (高血量、低攻击)")
choice = input("输入数字: ")
if choice == '1':
player = Dragon()
elif choice == '2':
player = Goblin()
else:
player = Slime()
import random
computer = random.choice([Dragon(), Goblin(), Slime()])
battle(player, computer)
if __name__ == "__main__":
main()
四、Java 版本实现(展示类型安全与强 OOP)
4.1 抽象父类 Monster.java
python
java
public abstract class Monster {
private String name;
private int hp;
private int attackPower;
private String skillName;
public Monster(String name, int hp, int attackPower, String skillName) {
this.name = name;
this.hp = hp;
this.attackPower = attackPower;
this.skillName = skillName;
}
public void takeDamage(int damage) {
hp -= damage;
if (hp < 0) hp = 0;
}
public boolean isAlive() {
return hp > 0;
}
public void attack(Monster target) {
target.takeDamage(attackPower);
System.out.println(name + " 发动普通攻击,造成 " + attackPower + " 伤害!");
}
public abstract void useSkill(Monster target); // 子类实现多态
// getters
public String getName() { return name; }
public int getHp() { return hp; }
public String getSkillName() { return skillName; }
}
4.2 子类 Dragon.java
python
java
public class Dragon extends Monster {
public Dragon() {
super("炎龙", 150, 25, "烈焰吐息");
}
@Override
public void useSkill(Monster target) {
int damage = 40;
target.takeDamage(damage);
System.out.println(getName() + " 使用 " + getSkillName() + ",造成 " + damage + " 伤害!");
}
}
4.3 Goblin.java 与 Slime.java(结构相同,数值不同)
python
java
// Goblin.java
public class Goblin extends Monster {
public Goblin() {
super("哥布林", 80, 20, "偷袭");
}
@Override
public void useSkill(Monster target) {
int damage = 35;
target.takeDamage(damage);
System.out.println(getName() + " 使用 " + getSkillName() + ",造成 " + damage + " 伤害!");
}
}
// Slime.java
public class Slime extends Monster {
public Slime() {
super("史莱姆", 120, 15, "腐蚀酸液");
}
@Override
public void useSkill(Monster target) {
int damage = 30;
target.takeDamage(damage);
System.out.println(getName() + " 使用 " + getSkillName() + ",造成 " + damage + " 伤害!");
}
}
4.4 战斗逻辑 Main.java
python
java
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("选择你的怪物:");
System.out.println("1. 炎龙 (高攻击、高血量)");
System.out.println("2. 哥布林 (平衡)");
System.out.println("3. 史莱姆 (高血量、低攻击)");
int choice = scanner.nextInt();
Monster player;
switch (choice) {
case 1: player = new Dragon(); break;
case 2: player = new Goblin(); break;
default: player = new Slime(); break;
}
Random rand = new Random();
Monster computer = rand.nextBoolean() ? new Dragon() : (rand.nextBoolean() ? new Goblin() : new Slime());
battle(player, computer);
scanner.close();
}
public static void battle(Monster player, Monster computer) {
System.out.println("\n战斗开始!");
System.out.println("你的 " + player.getName() + " VS 电脑的 " + computer.getName());
Scanner sc = new Scanner(System.in);
int turn = 0;
while (player.isAlive() && computer.isAlive()) {
turn++;
System.out.println("\n=== 第" + turn + "回合 ===");
System.out.print("选择 1-普通攻击 2-技能: ");
int action = sc.nextInt();
if (action == 1) {
player.attack(computer);
} else {
player.useSkill(computer);
}
if (!computer.isAlive()) {
System.out.println(computer.getName() + " 倒下了!你赢了!");
break;
}
Random rand = new Random();
if (rand.nextBoolean()) {
computer.attack(player);
} else {
computer.useSkill(player);
}
if (!player.isAlive()) {
System.out.println(player.getName() + " 倒下了!你输了...");
break;
}
System.out.println("你的 " + player.getName() + " HP: " + player.getHp());
System.out.println("电脑 " + computer.getName() + " HP: " + computer.getHp());
}
sc.close();
}
}
五、OOP 特性在本项目中的体现总结

六、如何扩展这个游戏?

-
增加新怪物 :只需新建子类,重写
useSkill,战斗逻辑完全不用动(多态的威力)。 -
增加属性相克 :在
useSkill或attack中加入类型判断。 -
保存战绩:用文件或数据库记录胜率。
七、Evan 的实战总结
这个小游戏我当年用 Java 写出来后,真正理解了"面向对象就是模拟现实世界"。怪物是对象,攻击是方法,不同怪物行为不同就是多态。如果你能把一个游戏从头到尾用 OOP 实现一遍,你就再也不会问"封装继承多态有什么用"了。
❓ 问题:你在这个怪物战斗游戏基础上增加了什么新功能?或者你遇到过什么 OOP 设计上的困惑?欢迎在评论区分享你的代码或问题,我会选出 3 位同学,送出《OOP 设计模式入门小册》和《怪物战斗游戏完整源码包》。
📌 如果本文让你爱上了面向对象编程,请点 👍 赞 + 关注 ,本专栏 《大一突围》 持续输出有趣的编程实战。
收藏本文,随时回来添加新怪物,打造属于你的怪物图鉴!