三次大作业——总结
一、前言
总结三次题目集的知识点、题量、难度等情况:
-
1.第一次大作业题目分别是求身份证号校验位、求解一元二次方程(类设计)、正则表达式训练-验证码校验、正则表达式训练-QQ号校验、单部电梯调度程序
主要涉及基础计算、类设计、正则表达式等知识点。 -
2.第二次大作业的题目分别是点与线(类设计)、汽车风挡玻璃雨刷问题(类设计)、单部电梯调度程序(类设计),其中主要涉及单一职责原则、类设计要点等知识点,重点在于电梯调度问题,此次电梯调度对上一次电梯调度进行了迭代涉及,题目中直接给出了类图,与上次相比,增加了通过类图涉及类的步骤,相对于通过文字涉及更加清晰明了。
-
3.第三次大作业的题目分别是销售步枪问题、蒙特卡罗方法求圆周率、单部电梯调度程序(类设计-迭代),涉及的知识点有单一职责原则、数据验证、蒙特卡洛仿真方法等,第三次的电梯调度对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),难度升级。
总的来说,这三次大作业的题目中前几题难度适中,根据给出的类图再经过题目理解分析可以实现测试点通过,难点都在于三道电梯调度题,因为情况复杂,所要分析的问题更多,所以最终都没有完成。
二、设计与分析
- [ 第一次大作业]
题目:
设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。
使用键盘模拟输入乘客的请求,此时要注意处理无效请求情况,例如无效楼层请求,比如超过大楼的最高或最低楼层。还需要考虑电梯的空闲状态,当没有请求时,电梯停留在当前楼层。
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),具体运行规则详见输入输出样例。
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
想法:
对于这种大段题设同时输入输出都要大片说明的题目,笔者本能就会产生畏惧,感觉自己会做不出来,事实上也确实是这样,其他题目都十分顺利地完成了,只有三道电梯调度题一直困扰我很久,最终交的几次显示答案错误,虽然输入例子后有一半能够正确输出,但还是一分都没有。

接下来笔者想说一下是如何实现无编译错误然后输入以下例子只有一半楼层输出的。

- 1.就像上面说到,面对这种复杂题,笔者一般不认为自己能完全手敲出来,所以看到题设先按照要求写出相应的类,然后去理解题目里的运行要求,脑中大概有一个电梯运行的模型,接下来具体运行规则的代码则先寻求AI的帮助,给出一个大致的轮廓,然后在次基础上进行理解,面对未见过的用法则通过查找资料进行学习记录。
诸如下类(暂截简单问答)
![image]()



- 2.当然,AI有时也并不可靠,虽说有时它比人更能理清内在逻辑,但是它也是在大数据的总结下进行书写代码,如果有时候题目有些另类,它就会出错,反复得出错误答案,甚至比人还要“死脑筋”。所以这几次在AI的帮助下也无法完成完全运行,提交时输入用例后只能得出一些楼层的停靠情况,表示代码仍有问题。
- 3.之后过了提交时间,知道AI协助无望后,笔者自行用IDE在其基础上进行修改,最后输入上面给出的用例,只是可以得到对应的效果,一旦换一些例子,就又出现问题,如:

(感觉问题出在内外队列上)
- 4.之后又试了几次,其间仍尝试用AI进行辅助修改,但对于这个题目,AI就如同失智了一般,反复带笔者进入“死胡同”,最后下一次电梯调度都快结束了还是没有正确结果,也就暂时放弃了。
- 5.这是用要求中提到的SourceMontor制出的图表,放入代码提前感受一下java大段代码中各数据属性的值。


- [第二次大作业 ]
题目:
对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类,具体设计可参考如下类图。

电梯运行规则与前阶段单类设计相同,但要处理如下情况:
乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>
注意:本次作业类设计必须符合如上要求(包含但不限于乘客请求类、电梯类、请求队列类及控制类,其中控制类专门负责电梯调度过程),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次电梯程序提交到本次题目中测试)。
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表 下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
想法感悟:
本次电梯调度题目相当于前一次题目的迭代升级,但本次代码给出了类图,严格意义上说是对类设计的要求更严格了,但是对于写类代码而言,要求算是更清晰简洁了一些。题目虽然增设了测试点,但难度依旧。

历程:
-
1.因为上次大作业的电梯调度反正也没做出来,干脆就没再延用之前的代码,而是从类设计开始,按照以前的想法,应该是尽可能地将逻辑放入电梯类里,但是本题要求要使用单一职责原则,所以不能将所有的逻辑都放在一个类里。
-
2.在利用AI辅助的过程中,我学到一个知识点就是去重逻辑。其实看到这道题会懵是因为电梯停靠会有很多情况,很多中途插入的请求,而去重逻辑就是在解决这个问题,如连续的相同电梯内请求:例如 <3><3><3>,过滤后只保留一个 <3>。连续的相同电梯外请求:例如 <5, DOWN><5, DOWN>,过滤后只保留一个 <5, DOWN>。
<3> 和 <3> 是相同的(同内请求,同楼层)。
<5, UP> 和 <5, UP> 是相同的(同外请求,同楼层,同方向)。
<5, UP> 和 <5, DOWN> 是不同的(同外请求,同楼层,但方向不同)。这两个请求代表在5楼有人想上行,也有人想下行,电梯可能需要为这两个请求分别停靠,因此不能去重。
<3> 和 <3> 是相同的(同内请求,同楼层)。
<5, UP> 和 <5, UP> 是相同的(同外请求,同楼层,同方向)。
<5, UP> 和 <5, DOWN> 是不同的(同外请求,同楼层,但方向不同)。这两个请求代表在5楼有人想上行,也有人想下行,电梯可能需要为这两个请求分别停靠,因此不能去重。
<3> 和 <5, UP> 是不同的(类型不同)。<3> 和 <5, UP> 是不同的(类型不同)。
总的来说,去重逻辑是一个数据预处理过程,理论如此,但实际操作与理论还是有所差距,笔者在未达到题目要求的情况下,进行了理论学习,后续有时间会再尝试实际操作。
- 3.写代码卡壳的时候去专门了解了单一职责原则,单一职责原则完整且简洁的定义应该是一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。通俗而言则是就一个类而言,应该仅有一个引起它变化的原因。从题目中给出的内容可以知道电梯类主要有设置状态(setState)、判断楼栋是否合规(isValidFloor)等职责,Controller类中主要有判断是否停止、就近选择楼层插入、变动请求等职责。而使用单一职责原则的好处就是使代码更加清晰,便于修改,和哪个类相关就放在哪个类里,这一点从做题的过程中确实切身感受到了,不用在混乱的逻辑里找问题。


- [ 第三次作业 ]
题目:
对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类,具体设计可参考如下类图。

电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客求格式:<楼层数>
电梯外乘客请求格式:<请求源楼层,请求目的楼层>,其中,请求源楼层表示乘客发起请求所在的楼 层,请求目的楼层表示乘客想要到达的楼层。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
想法:
第三次大作业的电梯调度相当于是对第二次的类设计方面的迭代,取消了之前的乘客请求类而改为乘客类,如之前一样,在进行代码编写之前先进行题目分析,得到一些内容,包括:外部请求被服务后,其目的楼层会作为内部请求加入电梯内部队列(队尾),这意味着外部请求的源楼层是电梯要去接人的楼层(方向由电梯当前扫描方向与请求的源楼层位置决定)。接到人后,乘客的目的楼层成为内部请求。
当然,还是那句话,理论与实践存在距离,在实践编写代码的过程中仍会出现各种问题,并且在一些不可抗力的因素之下,笔者花在第三道电梯调度问题上的时间比较少,所以想要说的问题比较少,心路历程也缺乏。
只能寄希望于下一次大作业,不再撰写未实现测试点的心路历程,而是编写完成题目后的“踩坑”心得!
三、总结
- 虽说三次作业的最后电梯调度答题都没有完全实现,但是通过其他题目还是令笔者学习到了许多java知识,如单一职责原则、正则表达式、数据验证、基础算法等,同时还接触了不少编程思想,只要在做,就会有进步。
- 不管结果如何,这三次大作业都是一次阶段性的学习,笔者没有完成证明这一阶段没有花足够多的时间去学习理解消化,以及编程能力的有待加强,相信在下一个阶段的学习中笔者能更加专注努力去完成题目!


浙公网安备 33010602011771号