OOPre课程总结(第八次作业)

崔成林-24371260 2025-11-06 21:58:56

OOPre课程总结(第八次作业)

一、项目架构

1. 最终架构

img

IntelliJ Community中没有Diagram选项,故使用外部插件生成UML类图并导出。

(我有的是力气和手段.JPG)

2. 各个模块的功能

冒险者核心模块(Adventurer):
代表游戏中的冒险者角色。基本属性:生命值、攻击力、防御力、魔法值、金钱。
能够处理物品的获取、装备、使用和移除,能够实现战斗、使用技能、雇佣或被雇佣、死后处理等功能。

物品系统模块
①药瓶系统(Bottles)
分为四类:HpBottle恢复生命值,AtkBottle提升攻击力,DefBottle提升防御力,ManaBottle恢复魔法值。
一次性使用物品,对目标产生对应的增益效果。
②装备系统(Equipment)
分为三类:Sword提供攻击力加成,Magicbook提供魔法攻击加成,Armour提供防御力加成。
可提供持续属性加成。
③法术系统(Spells)
分为两类:HealSpell治疗法术恢复目标生命值,AttackSpell攻击法术对目标造成伤害。
需要消耗魔法值,但可重复使用。

工厂模式模块(Factory)
集中创建所有游戏物品的工厂类,根据类型字符串动态创建对应的物品实例。
支持创建药瓶、装备、法术等所有物品类型,统一创建接口,便于扩展新的物品类型

词法分析模块(Lexer)
解析关系加载命令的输入字符串。
去除空白字符,提取标识符和符号。
支持ID字符(字母、数字、下划线)和括号、逗号识别。

主控制模块(MainClass)
程序入口和主控制循环,处理所有用户输入命令,协调各个模块的交互。
支持aa添加冒险者、ab添加药瓶、ae添加装备、ls学习法术、ri移除物品、ti装备物品、use使用物品、fight战斗、bi购买物品、ar/rr/lr关系管理的命令。

关系网络模块
管理冒险者之间的明确的上下级层级结构关系,通过观察者模式实现下属关注上级状态,生命值过低时触发下属援助。
下属自动使用最佳治疗法术援助上级,下属不能对上级使用有害效果,各人只能对盟友使用有益效果

战斗系统模块
处理冒险者之间的战斗,支持单人对多人的战斗场景,并计算最终攻击力和防御力。
物理攻击力>目标最高防御力时造成伤害使用魔法书时消耗魔法值进行群体攻击。
不能攻击自己的上级。

经济系统模块
管理冒险者的金钱和交易,处理物品购买和死亡奖励,实现简单的商店系统
购买物品花费最多100金钱,死亡时掉落所有金钱和物品价值,击杀者获得死亡奖励

游戏状态管理
管理冒险者的生命状态,处理死亡事件和后续清理,触发状态相关的事件。
自动检测死亡并保证不会“鞭尸”,低生命值时请求援助,死亡时清除关系网络

各个模块职责单一,通过接口和抽象类实现松耦合。

3. 迭代与重构过程

第二次作业:实现了冒险者类Adventurer、药水瓶类Bottle、装备类Equipment,利用容器管理所有冒险者,并管理每一个冒险者所拥有的药水瓶和装备。

本次作业任务较为简单,初步确定了“冒险者 - 物品”的基本架构,具备初步处理输入命令的能力。

第三次作业:引入了背包与携带(handle)的概念,提出了“可用物品”(Usable)的概念。药水瓶进一步分为四种类型,并引入了法术的概念。

由于引入了继承关系和接口,本次作业需要进行重构。

具体而言:

  • 引入了Usable抽象类,所有的可用物品都是Usable的子类,实现获取ID(getId)和使用(Use)抽象方法。
  • 物品作为一个接口存在(使用继承会造成巨量的冗余,因此换用接口),实现获取ID(getId)和物品类型(getType)的功能,并在子类中进一步实现。
  • 药水瓶Bottle改为一个抽象类,具体的功能由成为子类的四种具体药水实现。

第五次作业:装备进一步细分为武器和防具,并引入战斗系统、金钱系统和工厂模式的生成新物品。冒险者可以击败其他的冒险者,也可以购买装备。

本次作业主要重构内容是将生成新物品的方法改为一个统一的工厂(Factory)。此外,部分数组和图被替换成更快捷的HashSet和HashMap。

第六次作业:引入了雇佣关系以及对应的约束条件,通过观察者模式实现随从对上级的援助。

本次作业是代码量最大、最复杂最难的一期(个人感觉)。
在构建代码时,既要阻止下属的”反叛“(即攻击上司,往往是因为涉及攻击的方法没有及时修改),又要维护雇佣关系的图(死亡后及时移除对应关系,我强测栽在这个上面了(悲))

第七次作业:引入递归下降处理输入的方法。

整体业务上没有大的变动。

二、使用JUnit的体会

JUnit的核心思想就是”测试驱动开发“。测试不仅是验证代码正确性的工具,更是设计代码结构的重要手段,编写测试的过程=>在实现功能前就思考接口设计和边界情况。
或者说,测试用例就是最鲜活的需求文档和使用说明书。

  1. 测试层次
    良好的测试结构具有清晰的层次,测试代码本身也易于维护和理解。

  2. 测试覆盖率
    语句覆盖:确保每行代码都被执行。
    分支覆盖:测试所有条件分支。
    路径覆盖:覆盖所有可能的执行路径。

3.边界条件
边界值往往是最容易出问题的地方,极值测试能发现潜在的整数溢出等问题,空值、零值、负值都需要特别关注。
测试数据应该具有代表性且覆盖各种场景,系统性的数据组合测试能发现隐藏的交互问题。

4.测试专用类
测试专用类,又叫测试替身,用来隔离依赖,通常是为测试而设计的可配置类。
测试替身让测试更加专注和可控,可以模拟各种难以重现的场景,并且提高了测试的执行速度。

5.测试生命周期
@Before在每个测试方法前执行,通常是初始化测试环境、创建测试类等。
@After在每个测试方法后执行,一般是清理资源。
测试环境的隔离性保证了测试的独立性,适当的清理可以避免测试间的相互影响。

6.断言

assertEquals()    // 值相等断言
assertTrue()      // 条件断言  
assertFalse()     // 否定条件断言
assertNotNull()   // 非空断言
assertNull()      // 空值断言
assertSame()      // 同一对象断言

7.测试命名
一般是在对应的类前后加test,这样一眼就能看见是测的哪个类。

Extra.【您的代码中疑似包含非法操作,将提交人工审核】

这个……通常是因为代码中(尤其是测试代码)包含了反射或者系统操作。
指导书里面有写着不得使用反射等操作。
所以,我们的测试应当是在本地执行的静态测试操作,使用aasert断言(而不是滥用的System.out)来进行测试。

三、学习OOPre的心得体会

1.从过程到对象

整个游戏项目做下来,确实体会到面向对象编程(OOP)与传统的面向过程编程(比如C)在思维方式上有根本差异。比如最初我仍然倾向于用一堆的函数和复杂的数据结构来实现游戏逻辑(思维惯性要不得),但最终还是学会了用对象的视角来思考问题。
面向对象编程不再关注先做什么后做什么的执行流程,而是思考:这个游戏世界中有哪些实体?它们各自有什么属性和行为?
这样每个对象都是一个独立的小世界,封装了自己的状态和功能。
最大的一点体现就是方法的顺序变得自由了一些,不用像在C语言里面那样死扣函数顺序(当然还是建议按一定分类来写方法,不然写太乱有碍观瞻)

2.“四大支柱”的理解

封装:将数据(属性)和操作数据的方法捆绑在类中,实现了良好的封装。
这样冒险者的内部状态被保护起来(private),只能通过公开的方法(public)来访问和修改,在数据变化时能够触发相应的业务逻辑,保证对象始终处于合法状态。

继承:通过构建清晰的类层次结构、合理的继承关系能够极大减少代码重复。有点像C语言的函数,但是比函数更强大。
抽象类定义通用接口,具体类实现特定行为。但过度继承会导致体系僵化。

多态:同一接口不同实现,非常灵活。比如,无论是什么类型的Bottle,都使用相同的use方法,但是具体效果由实际类型决定。
这样的代码更加通用和可扩展,新增物品类型时也就不再需要大费周章修改使用者的代码。

抽象:接口和抽象类从具体实现中抽离出核心概念,关注的是做什么而不是怎么做,这样的设计更加清晰和灵活。

3.设计模式

工厂模式:Factory类,将对象创建逻辑集中管理,容易新增类型,而不用“挨家挨户”检查修改。
观察者模式:对象之间通过接口进行通信(比如,某冒险者受伤了,就可以通过接口摇人救援),而不是直接引用具体类,让系统更加灵活。

4.Bugs and Debug(and more bugs)

E = m * c ^ 2

Error = more codes ^ 2

总体上讲我的代码写得还算顺利,只有第六次的时候出了Bug,在实现冒险者上下级关系时,冒险者死亡以后没有及时移除关系,然后喜提强测WA……

一开始以为是”老板的老板不是老板“,但是读了题以后发现”我的老板的老板,就是我的老板“。后来把一个33行的测试点下载下来以后发现了关系图维护不正确的问题,才终于找出了Bug。

启示:
①尽可能地在本地进行充分的测试再上传,样例本身只是一种提示,多测测特殊情况。(当然本地测试的范围毕竟还是有限)
②报错以后尽量找那种行数正确、某一行出错的WA点,通过给出的错误信息,从头开始一步一步推导,查找究竟是哪里出了问题(比如该移除的没有移除)。因此较短的WA输入分外有价值。
③如果行数不对,需要关注那些可能引起输出行数变化的指令,然后从这些指令开始进行排查。
④如果确定代码已经烂透了,不要再浪费时间,立刻回退到最后一次(上一次)正确提交,重新开始构建!

“向已经延误的项目增派人手,只会进一步延误项目的进度。”——《人月神话》


总的说来,这门课的收获远超预期,面向对象编程的真正价值不在于语法特性,而在于它提供了一种组织复杂系统的思维方式,构建更加健壮(Robust)的软件系统。

四、对OOPre课程的简单建议

现有的课程设置已经非常合理、内容足够丰富,非要提建议的话……可以提供一些Java的基础操作指南,第一节课的时候面对一门陌生的语言感觉有点无从下手……


最后,感谢尊敬的老师,感谢各位认真负责的助教,也感谢各位OOPre课程的同学们!

...全文
32 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

270

社区成员

发帖
与我相关
我的任务
社区描述
2026年北航面向对象设计与构造
java 高校
社区管理员
  • 孙琦航
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧