PTA题目集5~7的总结性Blog

前言

面向对象程序设计课程第一次迭代设计作业结束了,第一次迭代作业,以电梯程序位中心,不断的添加新的功能,在这个过程中有许多的知识点:
1.Java基本语法;
2.电梯运行的LOOK算法;
3.Java链表的使用;
4.面向对象的设计思路;
5.如何增加代码可拓展性;
6.如何使用自动化测试工具。
这三次题目集的题量总体不算太多,难度中上,只要将电梯的运行逻辑搞懂以及第一次的电梯题目设计好结构,之后两次的迭代有第一次的基础就比第一次的简单。

设计与分析

第一次作业

作业要求

设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求。
输入样例:
1
20
< 3,UP>
<5>
<6,DOWN>
<7>
<3>
end
输出样例:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door

实现方式

代码通过模拟电梯的运行过程,处理内外部请求,根据请求的方向和楼层决定电梯的运行方向和停靠楼层。代码的核心逻辑在于 run 方法,它根据电梯的当前状态(上行或下行)处理各种请求情况,直到所有请求都处理完毕。

源码分析

代码类图

image
设计了两个类,一个主类,一个电梯类。
Main 类:负责接收用户输入,包括最低楼层、最高楼层以及电梯的内外部请求,然后创建 Elevator 类的实例并调用其方法来模拟电梯运行。
Elevator 类:负责电梯的具体逻辑,包括请求处理、状态管理和运行模拟。

复杂度分析

image

分析与心得

代码规模:代码行数为 343 行,有 2 个类(Main和Elevator ),共有228 个方法,平均每个类约 1.50 个方法 。

复杂度:最大复杂度为 6(位于Main.main() ),平均复杂度为 6.00 ,分支语句占比 28.2%,方法调用语句达 228 个。代码逻辑有一定复杂性,包含较多条件判断和方法间调用。

注释情况:带注释的行数仅占 8.5% ,注释比例较低,代码可读性较低。

优点:功能实现上较为完整,通过多个方法细分处理电梯的初始化、运行、请求处理等逻辑,结构相对清晰。不同类之间分工明确,Main类负责输入和整体流程控制,Elevator类专注电梯自身属性和操作。

不足:注释少,逻辑部分复杂(如电梯运行方向判断、请求处理优先级 )缺少注释辅助理解。方法间调用频繁,代码耦合度较高,一处修改可能引发连锁反应。代码可维护性和可扩展性较差。
心得:
代码可读性:注释是提升代码可读性的关键要素,后续开发中应及时、充分添加注释,特别是复杂算法和业务逻辑处,方便自己和他人理解代码意图。
复杂度控制:要关注代码复杂度,尽量遵循单一职责原则和高内聚低耦合原则。对于复杂方法,可进一步拆分细化,降低方法复杂度和代码块嵌套深度,提高代码可维护性。

第二次作业

作业要求

对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类。
电梯运行规则与前阶段单类设计相同,但要处理如下情况:
乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>。
输入样例:
1
20
< 3,UP>
< 3,UP>
<5>
<5>
<5>
<6,DOWN>
<7>
<7>
<3>
<22,DOWN>
<5,DOWN>
<30>
END
输出样例:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Open Door # Floor 5
Close Door
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door

实现方式

通过多个类协同工作,实现电梯运行的模拟。从用户输入获取请求信息,利用请求队列管理请求,根据电梯状态和请求情况确定电梯初始运行方向,根据用户输入的内部请求(电梯内乘客按下的楼层按钮)和外部请求(电梯外乘客按下的上下行按钮,来获得电梯下一目标楼层,之后控制电梯的移动到达目标楼层。

源码分析

代码类图

image

设计了个五个类,分别为,主类,电梯类,外部请求类,请求类,控制类。
Elevator类:用于表示电梯,包含电梯的当前楼层、运行方向、状态以及最大和最小楼层等属性,同时提供了相应的访问和修改方法。
ExternalRequest类:表示外部请求,记录请求的楼层和方向(向上或向下)。
Controller类:作为电梯系统的控制核心,负责处理乘客请求、确定电梯运行方向、控制电梯移动等操作。
RequestQueue类:用于管理请求队列,包含内部请求队列(乘客在电梯内按下的楼层按钮)和外部请求队列(乘客在电梯外请求乘坐电梯)。
Main类:程序的入口点,负责读取用户输入的最小楼层、最大楼层和乘客请求,并调用控制器处理这些请求

复杂度分析

image

分析与心得

代码规模:代码行数为 366 行,涉及多个类(如 ExternalRequest、Elevator、Controller、RequestQueue、Main 等 )。整体围绕电梯系统的功能实现展开,涵盖电梯状态管理、请求处理等功能模块。

复杂度:最大复杂度为 16(位于 Main.main() ) ,平均复杂度为 2.33 ,分支语句占比 22.3%,方法调用语句有 233 个 。表明代码存在较多逻辑分支,方法间调用频繁,如 Controller.run() 方法中大量 if - else 嵌套处理请求逻辑,使得代码逻辑较为复杂,理解与维护难度较大。

注释情况:带注释的行数占比仅 6.3% ,注释比例很低,这极大地影响了代码的可读性,对于阅读代码和理解其中的业务逻辑及算法思路造成较大阻碍。

优点:功能模块划分较明确,通过不同类分别处理外部请求(ExternalRequest 类 )、电梯自身属性和操作(Elevator 类 )、请求队列管理(RequestQueue 类 )以及整体控制逻辑(Controller 类 ),职责相对清晰。对电梯运行的各种情况考虑较为周全,从请求的添加、方向的判断到运行过程中的各种操作,都有相应的代码实现,功能完整性较好。

不足:注释匮乏,关键逻辑如电梯运行方向的确定、复杂的请求处理流程等缺少注释说明,给后续开发人员理解和维护代码带来极大困难。部分方法(如 Controller.run() )逻辑过于复杂,if - else 多层嵌套,代码结构混乱,可读性差。代码耦合度较高,方法间调用关系复杂,一处修改可能引发多处连锁反应,不利于代码的扩展和维护。

心得:代码规模较大,通过多类实现复杂功能。但复杂度高,分支和方法调用多,理解维护难,且注释匮乏影响可读性。虽功能模块划分清晰、功能完整,可关键逻辑缺注释,部分方法结构乱,耦合度高。这提醒我编程时要合理控制复杂度,重视注释,平衡功能与质量,确保代码结构清晰、易维护。

第三次作业

作业要求

对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类。电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)。
输入样例:
1
20
<5,9>
<8>
<9,3>
<4>
<2>
end
输出样例:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Open Door # Floor 8
Close Door
Current Floor: 9 Direction: UP
Open Door # Floor 9
Close Door
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Open Door # Floor 4
Close Door
Current Floor: 3 Direction: DOWN
Current Floor: 2 Direction: DOWN
Open Door # Floor 2
Close Door
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Current Floor: 9 Direction: UP
Open Door # Floor 9
Close Door
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door

实现方式

该代码通过多类协作模拟电梯运行。先从用户输入获取最小、最大楼层,创建电梯、请求队列及控制器对象。接着读取用户输入的内、外部请求并加入队列。然后依队列情况确定电梯初始方向并设为移动状态。运行时按方向选最近请求为目标楼层,控制电梯移动,途中输出楼层和方向,到达后开关门并移除已处理请求,直至队列为空。

源码分析

代码类图

image

设计了个五个类,分别为,主类,电梯类,乘客类,请求类,控制类。
Elevator类:用于表示电梯,包含电梯的当前楼层、运行方向、状态以及最大和最小楼层等属性,同时提供了相应的访问和修改方法。
Passenger类:用于表示乘客,包含乘客的起始楼层和目标楼层,以及获取乘客移动方向的方法。
Controller类:作为电梯系统的控制核心,负责处理乘客请求、确定电梯运行方向、控制电梯移动等操作。
RQ类:用于管理请求队列,包含内部请求队列(乘客在电梯内按下的楼层按钮)和外部请求队列(乘客在电梯外请求乘坐电梯)。
Main类:程序的入口点,负责读取用户输入的最小楼层、最大楼层和乘客请求,并调用控制器处理这些请求。

复杂度分析

image

分析与心得

代码规模:代码行数为 411 行,涉及多个类(如 Elevator、Passenger、Controller、RQ、Main 等)。整体围绕电梯系统的功能实现展开,涵盖电梯状态管理、乘客请求处理等功能模块。

复杂度:最大复杂度为 15(位于 Main.main () ) ,平均复杂度为 2.25,分支语句占比 22.9%,方法调用语句有 248 个 。这表明代码存在较多逻辑分支,方法间调用频繁,如 Controller.run () 方法中大量 if - else 嵌套处理请求逻辑,使得代码逻辑较为复杂,理解与维护难度较大。

注释情况:带注释的行数占比仅 6.3% ,注释比例很低 导致代码的可读性差。

优点:功能模块划分较明确,通过不同类分别处理电梯属性和操作(Elevator 类)、乘客信息(Passenger 类)、请求队列管理(RQ 类)以及整体控制逻辑(Controller 类),职责相对清晰。对电梯运行的各种情况考虑较为周全,从请求的添加、方向的判断到运行过程中的各种操作,都有相应的代码实现,功能完整性较好。

不足:注释匮乏,关键逻辑如电梯运行方向的确定、复杂的请求处理流程等缺少注释说明,给后续开发人员理解和维护代码带来极大困难。部分方法(如 Controller.run () )逻辑过于复杂,if - else 多层嵌套,代码结构混乱,可读性差。代码耦合度较高,方法间调用关系复杂,一处修改可能引发多处连锁反应,不利于代码的扩展和维护。

心得:这段电梯系统代码规模较大,411 行涉及多类。复杂度方面,分支多、方法调用频繁,理解维护难。注释仅占 6.3%,严重影响可读性。优点是模块划分清晰,功能实现较周全。但不足也明显,注释匮乏,关键逻辑无说明,部分方法结构混乱,耦合度高。此次分析让我明白,编写代码要注重逻辑简洁、注释充分、降低耦合,以提升可维护性。

采坑心得

第一次电梯问题,由于事先没有构思好代码以及审题不仔细,写代码时出现大量错误以及代码冗杂度大,出现了许多不必要的结构,如用了大量的队列等。
第二次电梯迭代时,由于第一次代码没有设计好结构,使得第二次要将代码拆分为多类时无法拆分,最终还是选择重新构思代码,整理电梯运行逻辑。
第三次电梯迭代时,由于之前的代码的边界条件处理不当,导致最后两个测试点一直过不去,显示非零返回,后来才发现是由于代码中判断电梯运行方向时没有考虑到内部请求队列和乘客请求队列中其中一个为空另一个不为空或者是两个都为空等情况。
综上我踩过的坑,在写代码之前一定要先构思好代码的结构再动手写。

改进建议

再分析自己写的代码之后,我感觉自己的代码会议非常大的改进空间,首先是代码的逻辑混乱,使用了大量的if-else语句,代码的扩展性也不高,要对代码进行重构。之后是代码的可读性低,要增加代码的注释。

总结

电梯迭代开发的过程充满了挑战,但也让我收获颇丰。在开发过程中,一定要重视代码的设计和架构,良好的设计是应对需求变更和扩展的基础。同时,要注重代码的可读性和可维护性,及时添加注释。对于边界条件和异常情况的处理,要做到全面和严谨,不能抱有侥幸心理。在面对问题时,不要急于修改代码,而是要深入分析问题的根源,选择合适的解决方案。每一次踩坑都是一次成长的机会,通过总结经验教训,不断改进和优化代码,才能写出高质量的代码

posted @ 2025-04-19 14:56  周凌建  阅读(44)  评论(0)    收藏  举报