单部电梯调度总结性blog
单部电梯调度总结性blog
一、前言:
第二阶段的迭代性编程到现在终于结束了,回想起这三个星期的编程之旅,真的是“旱的旱死,涝的涝死”。简单的题目真的不需要动脑和什么分析过程,只要正确把各个类提取出来,写着写着一测试就通过了。而真正的“幕后黑手”害死了我不知多少脑细胞[狗头]。总的来说,这三次题目集的难度是逐渐递增的,先来两道不是那么难的题目找找手感,升升级积累经验来面对最后的boss——电梯。
知识点:
第一次电梯作业所要用到的知识点其实并不算很深,主要是“类与对象”,包括封装等等。对于电梯的属性,比如电梯所处的当前楼层currentFloor,以及运行方向direction,和一些方法,电梯运行方法run,处理请求包括增加请求方法addRequest等,都是类与对象中的知识,是面向对象编程的核心。
再就是文本处理利器——正则表达式。通俗来说,学会了正则表达式,对于写这次作业可以提供一种额外的思路,一开始我是没有想到用正则表达式通过分割逗号“,” String[] parts = req.split(",");这种方法来做的,待学了以后我发现这种方法莫名的好用,能很好地区分内部请求和外部请求。
最后就是ArrayList的使用了,用ArrayList来管理电梯请求队列,用ArrayList来存储各个请求,之后再进行遍历。
总之,对于第一次写题目集5的我来说,这些知识点掌握的并不是很好,以至于花费了很长时间来写电梯题目,在当时工程量觉得是非常大的,因为并不是很熟悉各种java工具、java语法以及知识点。
二、题量及难度:
这一次迭代性编程总共分为三次,分别是题目集5、题目集6和题目集7
- 题目集5一共有5个题目,总的来说这四题并不是很难,基本上花个一到两个小时就能完成,是对正则表达式和最基础的java语法的考察,当然有c语言的基础完成是很轻松的。最后一题则是重中之重——单部电梯调度程序,对于刚开始不熟悉的我来说,着实有点烂额头,难度挺大的。
- 题目集6更是减少了题目量,由第一次的5题减少到3题,一如既往前两题难度也不是很大,掌握了类与对象的基本知识按类划分并正确创建对象也是解决的很轻松。第3题则是单部电梯调度程序的迭代程序,在第一次电梯调度程序的基础上,目的为解决电梯类职责过多,新增要求类设计,包含但不限于乘客请求类、电梯类、请求队列类及控制类,其中控制类专门负责电梯调度过程。第一次是一个大类——电梯类完成所有的功能,而这一次迭代,则是要求划分出许多小类,所有小类合起来完成第一次大电梯类的职责。看题量3题,算不上大,但难度还是依旧。但有了题目集5的经验,这一次迭代难度也就相应的减少了一点。
- 本次迭代程序的最后一个题目集7,依旧是只有三个题目,其中第一题销售步枪,这在学c语言的时候写过,所以难度基本为0。第二题是蒙特卡洛法求圆周率,结合老师发的详解,写起来也不是很难,纯粹是数学问题代码化。第3题在题目集6的电梯程序基础上又进行了一次迭代,乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层> 以及 对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾),还是一样虽然题量不大,难度还是在这里的。
三、设计与分析:
接下来就到了设计与分析板块
1.第一次作业:
1.7-5 NCHU_单部电梯调度程序
分数 70
中等
全屏浏览
切换布局
作者 段喜龙
单位 南昌航空大学
设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。
使用键盘模拟输入乘客的请求,此时要注意处理无效请求情况,例如无效楼层请求,比如超过大楼的最高或最低楼层。还需要考虑电梯的空闲状态,当没有请求时,电梯停留在当前楼层。
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),具体运行规则详见输入输出样例。
1)分析
题目中要求设计一个电梯类,包含最大和最小楼层、当前楼层、运行方向、状态,内部和外部请求队列。外部请求要分上行和下行。电梯的运行规则是关键,需要优先处理同方向请求,处理完后再处理反向请求。每次移动一层,检查是否需要停靠,处理请求时要开门关门。输入可能有无效楼层或重复请求,需要过滤掉。
- 设计:
设计一个电梯类,其中包含电梯的属性,以及一些方法。
属性:最小楼层、最大楼层、当前楼层、方向、状态、内部请求队列、外部上行队列、外部下行队列。
方法:处理请求、移动电梯、检查停靠、更新状态等。
minFloor 和 maxFloor:最小和最大楼层。
currentFloor:当前所在楼层。
direction:运行方向(UP, DOWN, IDLE)。
status:运行状态(STOPPED, MOVING, OPENING, CLOSING)。
internalRequests:内部请求队列(存储目标楼层)。
externalUpRequests 和 externalDownRequests:外部上行和下行请求队列。
- 代码分析:

2.第二次作业:
由于第二次作业没有做出来,在此说明我在做第二次作业中存在的问题、心路历程和感悟。
1)问题:
无论如何改进,输出结果总是

可能违背了题目中的要求:优先处理同方向请求,另一个可能的问题是电梯在到达顶层或底层时的方向反转逻辑。可能没有正确更新状态,导致后续方向判断错误。
以下是SourceMonitor中的代码分析:
1.Elevator类:

- PassengerRequest类:

- RequestQueue类:

- Main

2)心路历程
在我一开始拿到这个题目的时候,我心想着这和第一次写电梯没什么区别,只要把第一次电梯题目中Elevator类中的一些无关电梯本身的属性和方法提取出来作为一个新的类,在这些新的类中实现原本已经实现的功能即可。可是当我按部就班的去做的时候,在idea中写啊写,写完Main以后都没有报错,只是提示一些无关紧要的警告的时候,我是很开心的,因为那时我觉得这道题也就这样嘛,但当我把测试用例复制过去时,却发现输出结果和应该输出的结果大相径庭,我傻眼了,在那之后我尝试去找错误,无论是请教室友甚至问ai到底哪里出现了逻辑错误,依然无法解决,输出结果总是对不上,要么是在第三层就停了,要么第三层往下走之后,在处理完所有向上的请求后,处理向下请求时,只处理到第五层,于是电梯就不走了,即使是有比第五层还低的请求时,亦是如此。
3.第三次作业:
1)心路历程:
在经历了第二次作业电梯迭代设计的挫折之后,说真的有点灰心,看到这个题目又迭代了一次,我觉得我还是无法写出来,但总不能不尝试就放弃吧,于是在我写完该题目集的前两题之后,课闲时间就一直在idea里面写、调试,只能说属于是燃尽了。
4.感悟:
经过着三次电梯题目的迭代,从最初代的所有代码全部堆积在一个类Elevator中,到后来的新增类来减少Elevator类中的职责,我知晓了类单一职责原则的重要性。把所有职责全部放在一个类中实现,这不仅会让代码显得臃肿,在开发中其他人不一定会有耐心看,而且也不方便他人阅读,也就是该程序没有可读性。
此外,对于电梯的状态管理也是一个重点,一开始我使用数组来存储电梯的状态<UP>和<DOWN>等等,后来在网上查资料学习的过程中,知晓了enum这个枚举类型,于是我便带着试一试的心态使用了枚举类型,虽然最终还是没有做出来后面两道题,但是枚举类型确实要比单纯用数组好。在csdn上,有博主解释说enum比数组更有可读性,用数组存储依赖注释,而且可能会出现隐式错误,再就是枚举类型可以把所有状态定义在一个地方,方便统一管理。
采坑心得
因为只完成了第一次电梯设计,在此分析我在第一次电梯设计中的采坑心得。
第一次写完该电梯设计时,报运行超时的错误,当时有点茫然,不知道是因为老师出差在外pta平台的问题还是真的我的代码的问题,于是我去idea里面再次测试,发现真的一直输出同样的语句。我意识到是我的代码有问题,后来发现原来在方法checkCurrentDirection中,使用了过多的if-else并嵌套for循环
如图

后来我把这一块改成

运行超时的错误就解决了。
因此,在以后编写代码时,能尽量不用过多的if-else嵌套for等循环就尽量不用,这很容易导致运行超时。
改进建议
可以优化一些过于冗余的方法,就比如上文中过多的if-else嵌套for循环,可以通过更好的方法来代替,那么就用后者来代替,过多的if-else不仅会导致有时候运行超时,更会降低代码的可读性。
还有一点就是在该方法中电梯每次进行方向决策的时候都要重新检索一遍,这也会导致出现运行超时的错误。

我觉得可以用更好的方法来代替,但可能超出了我现有的知识范围,所以暂时不知道怎么改进,庆幸不是因为这里而报的运行超时错误。
总结
通过这三个星期的电梯迭代编程,从一开始的一个类解决所有问题入手,到后来慢慢的减轻类Elevator的职责,使用新类来实现先前的功能,我深刻理解了SRP单一职责原则的重要性。单一职责原则可以增强代码的可读性,提高代码的可维护性,更重要的是可以提高代码的复用性。
第二个收获则是正则表达式。正则表达式可以从文本中提取所需要的信息,正则表达式是文本处理的利器,学起来也不是很男,掌握后能极大提升开发效率和代码质量。在数据验证、日志分析、文本转换等场景中,合适的正则表达式往往能替代数百行传统代码。
最后做一个展望,期望下次迭代性编程我能有所突破,完成所有的题目!

浙公网安备 33010602011771号