【魔法森林冒险】3/14 Allen类(一):主角核心属性与初始化

🏠个人主页:黎雁

🎬作者简介:C/C++/JAVA后端开发学习者

❄️个人专栏:C语言数据结构(C语言)EasyXJAVA游戏规划程序人生

✨ 从来绝巘须孤往,万里同尘即玉京

文章目录

  • [【魔法森林冒险】3/14 Allen类(一):主角核心属性与初始化🎭](#【魔法森林冒险】3/14 Allen类(一):主角核心属性与初始化🎭)
    • [📝 文章摘要](#📝 文章摘要)
    • [🎯 一、Allen类的定位:整个游戏的「核心交互载体」](#🎯 一、Allen类的定位:整个游戏的「核心交互载体」)
    • [🔍 二、核心代码拆解:Allen类的专属属性与封装](#🔍 二、核心代码拆解:Allen类的专属属性与封装)
    • [🚀 三、初始化逻辑:构造方法的执行顺序](#🚀 三、初始化逻辑:构造方法的执行顺序)
    • [🧪 四、调试示例:验证Allen的初始化效果](#🧪 四、调试示例:验证Allen的初始化效果)
    • [📌 知识回顾](#📌 知识回顾)
    • [✍️ 写在最后](#✍️ 写在最后)

【魔法森林冒险】3/14 Allen类(一):主角核心属性与初始化🎭

📝 文章摘要

内容维度 详情说明
核心摘要 本文是「魔法森林冒险」Java项目系列第三篇,聚焦玩家主角Allen类的核心设计------从专属属性定义(钥匙、任务进度、技能),到构造方法的初始化逻辑,再到属性封装的细节(HP/MP校验、数据安全),结合调试示例帮你吃透「主角角色」的开发思路。
阅读时长 12分钟
适合人群 1. Java新手:想掌握「属性封装+构造方法」的实战用法;2. 游戏开发入门者:想理解玩家角色的属性设计逻辑;3. 项目复刻者:想复刻Allen的核心状态管理。
阅读重点 1. Allen专属属性的设计思路(为什么要定义这些属性);2. 构造方法的初始化顺序与默认值设置;3. 属性封装的校验逻辑(HP/MP不能为负);4. 调试示例验证初始化效果。

🎯 一、Allen类的定位:整个游戏的「核心交互载体」

在「魔法森林冒险」中,Allen(艾伦)是玩家唯一操控的角色,所有游戏流程(战斗、拾取道具、完成任务、与Lia交互)都围绕他展开。

相比于父类Person(可交互角色抽象类),Allen需要:

✅ 新增「冒险专属属性」:钥匙数量、任务进度、技能等级、Lia信任度关联;

✅ 强化「属性校验逻辑」:比如HP为0时直接判定游戏失败;

✅ 初始化「默认状态」:初始HP/MP/金币、空背包、未完成的任务进度。

接下来我们拆解你提供的Allen.java核心代码,吃透主角的设计逻辑!

🔍 二、核心代码拆解:Allen类的专属属性与封装

2.1 完整核心代码(未修改,拆分讲解)

java 复制代码
/**
 * 玩家主角Allen类
 * 继承Person抽象类,实现玩家专属的属性与行为
 */
public class Allen extends Person {
    // ========== Allen专属属性 ==========
    // 钥匙数量(主线任务:需要收集3把钥匙解锁永恒之泉)
    private int keyCount;
    // 主线任务进度(数组:5个场景对应5个进度,0=未完成,1=完成)
    // 索引0:入口林地 1:迷雾沼泽 2:古老废墟 3:黑暗洞穴 4:永恒之泉
    private int[] mainTaskProgress;
    // 支线任务:治疗动物进度(需要治疗3只,数组记录已治疗数量)
    private int healAnimalCount;
    // 技能等级(初始1级,完成任务可升级,提升攻击力)
    private int skillLevel;
    // 与Lia的信任度(0-100,影响Lia是否辅助战斗)
    private int liaTrustLevel;

    // ========== 常量定义(固定值,方便维护) ==========
    // 初始HP
    private static final int INIT_HP = 100;
    // 初始MP
    private static final int INIT_MP = 50;
    // 初始金币
    private static final int INIT_GOLD = 20;
    // 初始技能等级
    private static final int INIT_SKILL_LEVEL = 1;
    // 主线任务数量(5个场景)
    private static final int MAIN_TASK_COUNT = 5;

    // ========== 构造方法:初始化所有属性 ==========
    public Allen() {
        // 1. 调用父类Person的构造方法(名称、描述、初始HP/MP/金币)
        super("艾伦", "年轻的魔法学徒", INIT_HP, INIT_MP, INIT_GOLD);
        // 2. 初始化专属属性默认值
        this.keyCount = 0; // 初始无钥匙
        this.mainTaskProgress = new int[MAIN_TASK_COUNT]; // 初始全0(未完成)
        this.healAnimalCount = 0; // 初始未治疗任何动物
        this.skillLevel = INIT_SKILL_LEVEL; // 初始1级技能
        this.liaTrustLevel = 0; // 初始与Lia信任度为0
        // 3. 初始化父类的背包(Person已初始化,这里可补充提示)
        System.out.println("✨ 艾伦已准备好冒险!初始状态:HP=" + INIT_HP + " MP=" + INIT_MP + " 金币=" + INIT_GOLD);
    }

    // ========== 属性封装:Getter/Setter(带校验) ==========
    // 钥匙数量:Getter
    public int getKeyCount() {
        return keyCount;
    }

    // 钥匙数量:Setter(只能增加,不能减少)
    public void addKey() {
        this.keyCount++;
        System.out.println("🔑 艾伦获得了1把钥匙!当前钥匙数量:" + this.keyCount);
    }

    // HP:重写父类setHp,强化校验(HP为0时提示游戏失败)
    @Override
    public void setHp(int hp) {
        if (hp < 0) {
            this.hp = 0;
            this.setAlive(false);
            System.out.println("❌ 艾伦的HP已耗尽!游戏失败!");
        } else if (hp > INIT_HP) {
            this.hp = INIT_HP; // HP上限为初始值(可拓展为随等级提升)
            System.out.println("💛 艾伦的HP已恢复至最大值!");
        } else {
            this.hp = hp;
        }
    }

    // MP:重写父类setMp,强化校验(MP上限限制)
    @Override
    public void setMp(int mp) {
        if (mp < 0) {
            this.mp = 0;
        } else if (mp > INIT_MP) {
            this.mp = INIT_MP;
            System.out.println("💙 艾伦的MP已恢复至最大值!");
        } else {
            this.mp = mp;
        }
    }

    // 主线任务进度:更新指定场景的进度
    public void updateMainTaskProgress(int sceneIndex, int progress) {
        if (sceneIndex < 0 || sceneIndex >= MAIN_TASK_COUNT) {
            System.out.println("⚠️ 场景索引错误!请输入0-4的数字");
            return;
        }
        if (progress != 0 && progress != 1) {
            System.out.println("⚠️ 进度值错误!只能输入0(未完成)或1(完成)");
            return;
        }
        this.mainTaskProgress[sceneIndex] = progress;
        System.out.println("📌 主线任务更新:场景" + sceneIndex + "进度变为" + (progress == 1 ? "已完成" : "未完成"));
    }

    // Lia信任度:Setter(0-100限制)
    public void setLiaTrustLevel(int liaTrustLevel) {
        if (liaTrustLevel < 0) {
            this.liaTrustLevel = 0;
        } else if (liaTrustLevel > 100) {
            this.liaTrustLevel = 100;
        } else {
            this.liaTrustLevel = liaTrustLevel;
            // 信任度≥60时,提示Lia会辅助战斗
            if (this.liaTrustLevel >= 60 && this.liaTrustLevel < 100) {
                System.out.println("🤝 Lia的信任度达到" + liaTrustLevel + "!战斗时会辅助你~");
            } else if (this.liaTrustLevel == 100) {
                System.out.println("❤️ Lia完全信任你!会为你抵挡伤害!");
            }
        }
    }

    // ========== 抽象方法实现(继承Person必须实现) ==========
    @Override
    public void act() {
        // 玩家行动逻辑(后续篇章讲解)
        System.out.println("艾伦正在思考下一步行动...");
    }

    @Override
    public boolean useItem(Item item) {
        // 道具使用逻辑(后续篇章讲解)
        return false;
    }

    @Override
    public boolean trade(Person target, Item item, int gold) {
        // 交易逻辑(后续篇章讲解)
        return false;
    }

    // ========== 辅助方法:打印当前状态 ==========
    public void printStatus() {
        System.out.println("\n===== 艾伦的当前状态 =====");
        System.out.println("HP:" + this.getHp() + " / " + INIT_HP);
        System.out.println("MP:" + this.getMp() + " / " + INIT_MP);
        System.out.println("金币:" + this.getGold());
        System.out.println("钥匙数量:" + this.keyCount);
        System.out.println("技能等级:" + this.skillLevel);
        System.out.println("Lia信任度:" + this.liaTrustLevel);
        System.out.println("已治疗动物数量:" + this.healAnimalCount);
        System.out.println("主线任务进度:");
        String[] scenes = {"入口林地", "迷雾沼泽", "古老废墟", "黑暗洞穴", "永恒之泉"};
        for (int i = 0; i < mainTaskProgress.length; i++) {
            System.out.println("  " + scenes[i] + ":" + (mainTaskProgress[i] == 1 ? "✅ 完成" : "❌ 未完成"));
        }
        System.out.println("==========================\n");
    }
}

2.2 关键知识点讲解💡

(1)专属属性设计:贴合游戏玩法
属性名 设计目的 关联玩法
keyCount 记录收集的钥匙数量 主线任务:3把钥匙解锁永恒之泉
mainTaskProgress 数组记录5个场景的任务进度 串联所有主线场景,判断是否能进入下一场景
healAnimalCount 支线任务:治疗动物数量 完成后Lia奖励永久HP+20
skillLevel 技能等级 提升攻击力,影响战斗难度
liaTrustLevel 与Lia的信任度 信任度≥60,Lia会在战斗中辅助Allen

👉 核心思路:属性设计完全围绕游戏任务展开,每个属性都对应具体的玩法,而非无意义的定义。

(2)常量定义:方便维护

static final定义固定值(INIT_HP/INIT_MP),好处是:

  • 后续想调整初始HP(比如改成150),只需改常量值,不用改所有初始化代码;
  • 代码可读性更高:INIT_HP比直接写100更易理解。
(3)属性封装:带校验的Getter/Setter
  • addKey():不直接提供setKeyCount(),而是用addKey()保证钥匙只能增加(符合游戏逻辑:钥匙捡了就不会丢);
  • 重写setHp():HP为0时直接提示「游戏失败」,强化玩家角色的死亡逻辑;
  • setLiaTrustLevel():限制信任度0-100,且达到阈值时给出提示(联动Lia的辅助战斗逻辑)。

👉 新手重点:封装不是简单写get/set,而是根据业务逻辑增加校验,保证数据安全

🚀 三、初始化逻辑:构造方法的执行顺序

Allen的构造方法是「玩家初始状态的入口」,执行顺序至关重要:
调用Allen构造方法
调用父类Person构造:初始化name/HP/MP/金币/背包
初始化Allen专属属性:keyCount=0、任务进度数组全0等
打印初始化提示:艾伦已准备好冒险

关键细节:

  1. 父类构造优先super()必须是构造方法的第一行,先初始化Person的通用属性(HP/MP/背包),再初始化Allen的专属属性;
  2. 数组初始化mainTaskProgress = new int[MAIN_TASK_COUNT],数组默认值为0(所有任务未完成);
  3. 默认值合理 :初始信任度liaTrustLevel=0(还没遇到Lia),初始技能等级1(新手难度)。

🧪 四、调试示例:验证Allen的初始化效果

写一个测试类,验证Allen的初始化是否符合预期:

java 复制代码
/**
 * Allen初始化调试示例
 */
public class AllenTest {
    public static void main(String[] args) {
        // 1. 创建Allen对象(触发构造方法)
        Allen allen = new Allen();
        
        // 2. 打印初始状态
        allen.printStatus();
        
        // 3. 测试HP校验逻辑
        System.out.println("\n--- 测试HP设置 ---");
        allen.setHp(-10); // 测试HP为负
        allen.setHp(150); // 测试HP超过上限
        allen.setHp(80);  // 测试正常HP
        
        // 4. 测试添加钥匙
        System.out.println("\n--- 测试收集钥匙 ---");
        allen.addKey();
        allen.addKey();
        
        // 5. 测试Lia信任度
        System.out.println("\n--- 测试Lia信任度 ---");
        allen.setLiaTrustLevel(60);
        allen.setLiaTrustLevel(100);
    }
}

调试输出结果:

复制代码
✨ 艾伦已准备好冒险!初始状态:HP=100 MP=50 金币=20

===== 艾伦的当前状态 =====
HP:100 / 100
MP:50 / 50
金币:20
钥匙数量:0
技能等级:1
Lia信任度:0
已治疗动物数量:0
主线任务进度:
  入口林地:❌ 未完成
  迷雾沼泽:❌ 未完成
  古老废墟:❌ 未完成
  黑暗洞穴:❌ 未完成
  永恒之泉:❌ 未完成
==========================

--- 测试HP设置 ---
❌ 艾伦的HP已耗尽!游戏失败!
💛 艾伦的HP已恢复至最大值!
--- 测试收集钥匙 ---
🔑 艾伦获得了1把钥匙!当前钥匙数量:1
🔑 艾伦获得了1把钥匙!当前钥匙数量:2
--- 测试Lia信任度 ---
🤝 Lia的信任度达到60!战斗时会辅助你~
❤️ Lia完全信任你!会为你抵挡伤害!

👉 结论:初始化逻辑完全符合预期,属性校验生效,数据安全有保障!

📌 知识回顾

  1. Allen类继承Person抽象类,新增的专属属性全部贴合游戏任务(钥匙、任务进度、Lia信任度);
  2. 构造方法遵循「父类优先」原则,先初始化通用属性,再初始化专属属性,默认值设置合理;
  3. 属性封装不是简单的get/set,而是结合业务逻辑增加校验(钥匙只能加、HP/MP有上下限);
  4. static final定义常量,提升代码可维护性;用辅助方法printStatus()快速验证状态。

✍️ 写在最后

Allen类的初始化是「玩家体验的第一步」,合理的属性设计和校验逻辑,能避免游戏运行中出现数据混乱(比如HP为负、钥匙数量为-1)。

下一篇我们会聚焦「Allen类(二):道具交互核心逻辑」,带你拆解Allen如何拾取、使用、丢弃道具,以及如何通过MagicFlower提升Lia的信任度💐。

新手建议:

  1. 把Allen的代码和测试类复制到IDE中运行,修改初始值(比如INIT_HP=150),观察输出变化;
  2. 思考:如果新增「背包重量限制」属性,该如何设计Getter/Setter?

🔥 系列文章导航:

  1. 项目总览:设计与架构
  2. 抽象层设计:Figure/Person类
  3. Allen类(一):核心属性与初始化(本文)
  4. Allen类(二):道具交互核心逻辑
    ...(后续篇章持续更新)
    💬 评论区互动:你觉得Allen还应该增加哪些专属属性?比如「攻击力」「防御力」,或者「背包重量限制」?
相关推荐
黎雁·泠崖4 小时前
【魔法森林冒险】1/14 项目总览:用Java打造你的第一个回合制冒险游戏
java·开发语言
独好紫罗兰4 小时前
对python的再认识-基于数据结构进行-a006-元组-拓展
开发语言·数据结构·python
NuageL4 小时前
原始Json字符串转化为Java对象列表/把中文键名变成英文键名
java·spring boot·json
C++ 老炮儿的技术栈4 小时前
Qt 编写 TcpClient 程序 详细步骤
c语言·开发语言·数据库·c++·qt·算法
yuuki2332335 小时前
【C++】继承
开发语言·c++·windows
222you5 小时前
Redis的主从复制和哨兵机制
java·开发语言
江湖有缘5 小时前
零基础入门:使用 Docker 快速部署 Organizr 个人主页
java·服务器·docker
牛奔5 小时前
如何理解 Go 的调度模型,以及 G / M / P 各自的职责
开发语言·后端·golang
梵刹古音5 小时前
【C++】 析构函数
开发语言·c++