单部电梯调度程序三次题目集总结

前言

本次的三次题目集均围绕单部电梯调度程序进行展开:第一次有电梯内乘客请求(<楼层数>)和电梯外乘客请求(<乘客所在楼层数,乘梯方向>)作为输入,然后模拟题目中所描述的电梯运行过程进行输出;第二次在第一次的基础上对类的设计进行了要求(包含但不限于设计电梯类、乘客请求类、队列类以及控制类);第三次要求加入乘客类,取消乘客请求类,输入中外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>。第一次题目只需要看懂电梯运行的逻辑并掌握一些基础语法就可以完成,第二次作业则需要掌握类的设计、调用等知识点,第三次还要求了两个输入队列的交互,难度是逐层递增的。因为是在上一次代码的基础上进行修改的,所以三次的题量对笔者来说差不多。

设计与分析

第一次作业

因题目篇幅实在过长,笔者对其进行了总结,提炼出了电梯运行的核心逻辑:只看内部队列和外部队列首元素。
具体内容如下:
1.查看到达内部队列首元素楼层数需要的运行方向与电梯此时运行方向是否一致,查看外部队列首元素乘梯方向与电梯此时运行方向是否一致
2.如果都一致,则选择楼层距离短的那个响应,记为响应一次并记录响应队列,如果楼层距离相等,记为响应两次;如果只有一个一致,则响应一致的那一个,记为响应一次并记录响应队列;如果都不一致,则选择楼层距离短的那个响应,记为响应一次并记录响应队列,如果楼层距离相等,记为响应两次;
3.如果响应一次,就删除该响应队列的首元素,如果响应两次,就删除两个队列的首元素
4.更新电梯运行方向并朝着响应楼层方向运行,途径每一层都输出楼层数和方向直到到达响应楼层
5.到达响应楼层后打印开门,然后继续从第一步开始直到处理完所有请求(两个队列都为空)

代码规模

image
image
image
image

  1. 整体规模、结构
    (1)文件与类结构:核心逻辑集中于Main.java文件,共涉及3个类(Main、Elevator、Markedstatus),平均每个类有1.33个方法(总方法数4个:Main类2个、Elevator类2个、Markedstatus类0个),属于单文件小型工具类项目,类与方法数量偏少,职责集中。
    (2)代码行数与语句:总代码行153行,可执行语句93条,方法调用语句81次,整体属于轻量型模块级别。
  2. 复杂度与可维护性
    (1)圈复杂度:最大圈复杂度为隐性高值。Main.handleCurrentFloor()方法属于高复杂度模块,嵌套逻辑密集,维护难度大,需重点优化。
    (2)代码块深度:最大块深度5,平均块深度2.92,块深度3的语句占比65.6%,嵌套层级偏深。
    (3)注释比例:注释占比仅1.3%,缺乏对关键业务逻辑、类与方法的有效说明,可读性极差。
  3. 方法级复杂度分布
    (1)复杂度最高的方法是Main.handleCurrentFloor(),有效语句数88条、最大块深度5、方法调用次数占比超85%,逻辑高度集中,分支嵌套密集,是整个项目的复杂度核心。
    (2)其他方法复杂度极低,均在1-2之间,无嵌套逻辑,仅承担入口或属性操作功能。
  4. 代码块深度的直方图分布
    (1)块深度为1的语句12条,深度2的语句15条,深度3的语句61条,深度4的语句4条,深度5的语句1条。过度嵌套的语句占比20.4%,且全部集中在Main.handleCurrentFloor()方法中,其他方法无深层嵌套问题。
  5. 雷达图的多维度对比
    (1)% Comments的“雷达半径”显著偏小,与Avg Complexity、Max Complexity、Max Depth形成明显反差,代码存在注释严重不足、核心方法复杂度偏高的突出问题。
    (2)类数量分布、方法平均语句数、依赖规模等维度的“雷达半径”相对均衡,处于合理区间,整体无过度冗余或缺失的结构问题。

第二次作业

根据题目要求,在第一次作业代码的基础上进行类的设计和调整

代码规模

image
image
image
image
image

  1. 整体规模、结构
    (1)文件与类结构:涉及6个类(Main、ElevatorController、Elevator、RequestQueue、InRequest、OutRequest),平均每个类有4.83个方法,形成“入口类+控制类+模型类+队列类”的分层架构,符合面向对象设计原则。
    (2)代码行数与语句:总代码行316行,可执行语句189条,方法调用语句119次,属于小型模块级别。
  2. 复杂度与可维护性
    (1)圈复杂度:最大圈复杂度为19(Main.handleInput()方法),平均圈复杂度2.07。
    (2)代码块深度:最大块深度6,平均块深度2.06,块深度为2的语句80条,深度4-6的语句共23条,主要集中在核心业务方法中,过度嵌套比例较低,整体结构可控。
    (3)注释比例:注释占比2.5%,可读性较差。
  3. 方法级复杂度分布
    (1)复杂度最高的方法是Main.handleInput(),圈复杂度19、语句数30、最大块深度6、方法调用26次。
    (2)ElevatorController.processAllRequests()和RequestQueue.hasSameDirRequests()复杂度均为5,分别承担请求批量处理和同方向请求检查职责,存在一定业务复杂度。
    (3)其余方法复杂度均在1-2之间,无复杂嵌套,仅承担基础功能。
  4. 代码块深度的直方图分布
    (1)块深度为0的语句12条,深度1的语句47条,深度2的语句80条,深度3的语句27条,深度4的语句15条,深度5的语句6条,深度6的语句2条。
    (2)深度≥4的过度嵌套语句占比约13.2%,集中在Main.handleInput()和ElevatorController.processAllRequests()中,其他方法无深层嵌套问题,整体嵌套结构健康度中等。
  5. 雷达图的多维度对比
    (1)% Comments“雷达半径”显著偏小,与Avg Complexity、Max Complexity、Max Depth形成明显反差,代码存在注释严重不足、核心方法复杂度偏高的突出问题。
    (2)Methods/Class、Avg Stmts/Method的“雷达半径”处于较均衡水平,说明类与方法的规模分布合理,仅局部核心方法存在复杂度和注释的短板,整体结构无明显冗余或缺失。

第三次作业

根据题目要求,在第二次作业代码的基础上将外部请求队列格式由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>

代码规模

image
image
image
image

  1. 整体规模、结构
    (1)文件与类结构:核心逻辑集中于Main.java文件,共涉及6个类(Main、ElevatorController、Elevator、RequestQueue、InRequest、Passenger),平均每个类有5.17个方法。
    (2)代码行数与语句:总代码行361行,可执行语句211条,方法调用语句132次。
  2. 复杂度与可维护性
    (1)圈复杂度:最大圈复杂度为21(Main.handleInput()方法),平均圈复杂度2.63。Main.handleInput()因需处理多格式输入解析与请求分发,逻辑分支密集,属于高复杂度方法;ElevatorController.handleCurrentFloor()复杂度11、RequestQueue.hasSameDirRequests()复杂度12,也存在一定优化空间。
    (2)代码块深度:最大块深度7,平均块深度2.42,块深度为2的语句66条,深度4-7的语句共29条,主要集中在核心业务方法中,过度嵌套比例较低。
  3. 方法级复杂度分布
    (1)复杂度最高的方法是Main.handleInput(),圈复杂度21、语句数28、最大块深度7、方法调用24次。
    (2)ElevatorController.handleCurrentFloor()复杂度11、RequestQueue.hasSameDirRequests()复杂度12,分别承担当前楼层请求处理和同方向请求检查职责,存在较高业务复杂度。
    (3)其余方法复杂度在1-5之间,无复杂嵌套,仅承担基础功能。
  4. 代码块深度的直方图分布
    (1)块深度为0的语句9条,深度1的语句42条,深度2的语句66条,深度3的语句65条,深度4的语句16条,深度5的语句5条,深度6的语句4条,深度7的语句4条。
    (2)深度≥4的过度嵌套语句占比约15.6%,且全部集中在Main.handleInput()、ElevatorController.handleCurrentFloor()和RequestQueue.hasSameDirRequests()中,其他方法无深层嵌套问题,整体嵌套结构健康度中等。
  5. 雷达图的多维度对比
    (1)% Comments的“雷达半径”完全缺失,与Avg Complexity、Max Complexity、Max Depth形成强烈反差,反映出代码完全无注释与核心方法复杂度极高的突出问题。
    (2)Methods/Class、Avg Stmts/Method的“雷达半径”处于较均衡水平,说明类与方法的规模分布合理,仅局部核心方法存在复杂度和注释的严重短板,整体结构无明显冗余或缺失。

采坑心得

第一次作业

1.刚开始看到题目中“不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求)”这句话,以为是一行一行处理输入,后输出有误发现是分为内外两个队列,首元素并行处理,其他串行处理。
2. 非零返回:当内外队列都有请求,但所有分支都未触发电梯移动时程序卡住,添加“若电梯未移动且队列非空,强制移动”逻辑。
3.运行超时:电梯移动时采用 “循环逐层判断”,产生大量重复循环,运行时间过长,改为直接计算移动步数、批量输出楼层。

第二次作业

image
笔者改完代码之后提交,发现第一个测试点显示答案错误,但是老师给的样例测试完都没有任何问题,问了ai改了几个小时还是找不到问题所在,后面又和同学讨论自行设计了一些测试也没有发现问题,最后又重新给ai提供了我的代码和一些测试样例,它给我的反馈如下:
问题核心:调度调度逻辑错误,未正确实现 “同向优先” 原则。当前代码在选择下一个目标楼层时,没有优先处理当前方向上的所有请求,而是简单比较距离,导致电梯频繁变向,不符合样例预期。
关键修改点:实现 “同向优先” 调度:电梯应先处理完当前方向(上行 / 下行)上的所有请求,再反向处理剩余请求;优化请求筛选:在每个方向上,优先处理该方向上的内部请求(电梯内按钮)和同向外部请求(楼层外上行 / 下行按钮)。
实际上笔者的代码是有考虑这个方面的,有可能是这部分的逻辑比较复杂混乱,导致答案错误,这次修改完之后两个测试点就都通过了。

第三次作业

第三次作业比较顺利,在第二次代码的基础上改完之后提交就一次通过了所有的测试点。(老师给的测试样例有一些问题,我就没有参考这个直接提交了)

改进建议

1.拆分主函数,将其逻辑按功能模块拆解为多个低复杂度子方法,降低圈复杂度和块深度。
2.针对类、关键方法、复杂逻辑分支添加注释,将注释占比提升至10%以上,增强代码可读性。
3.梳理Max Depth≥5的代码块,简化过度嵌套的if-else或循环,使代码结构更扁平。
4.在写代码之前就提前设计好类图,梳理各个类之间的关系,不要直接上手想到哪里写哪里,这样后续的修改会更简单

总结

三次作业的迭代过程,我学会了从“面向过程逻辑实现”到“面向对象设计”。我不仅进一步熟悉了Java语法,还掌握了代码迭代与优化的核心方法,学会了通过“方法拆分”“类职责重构”降低代码复杂度。
但是,我还缺乏高级的面向对象设计能力,我所涉及的类设计仍停留在“职责拆分”层面,对工厂模式、策略模式等设计模式的应用不足。后续需深入学习设计模式,提升架构扩展性。同时,我还应该学习一些单元测试框架,为核心方法编写测试用例,提前规避逻辑漏洞。
此外,希望老师在编写测试点时可以提供一些参考文字,给出每个测试点具体在检测哪种情况,这样我们也可以比较有针对性地修改代码,不至于过于盲目找不出问题所在。

posted @ 2025-11-22 22:58  杨蕾yl  阅读(2)  评论(0)    收藏  举报