电梯作业总结blog

电梯作业总结blog

前言

知识点:

个人认为本次作业涉及知识量不大,主要在于正则表达式的学习以及ArrayList或ListLink的使用,在于对队列的增删改,题目的复杂更偏向于对问题的思考方法。当然第一次接触所花费的时间较多,同时学习后的实践调试也需要不断尝试。

题量:

第一次作业初看下来因为不熟悉,同时也是第一次编写系统型的程序,所以显得工程量较大,所花费时间大概是三到四天。

第二次作业开始迭代基于第一次进行修改题量就会显得小很多,本人花了一天多的时间进行修改调试,主要在于后续对测试点通过的调试。

第三次作业由于对题目的理解加深以及老师的提示,所以花的时间会更少,但由于个人的初期设计与老师出题的设计不一致所以相对于其他人修改更大,花的时间为两天多。

总的来说,只要思考清楚题目与老师的想法,这次的题目题量并不算特别大(当然花费的时间比我过去做题的时间多得多的)。

难度:

总的来说这次作业的题目是由困难到简单,困难是由于各种java工具不熟悉以及对java编程的理解不高,题目有一定复杂度造成的。所以从客观的角度来说本次作业难度中等偏上(个人来说)。

本次电梯作业三次题目如下:

第一次:

设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。
使用键盘模拟输入乘客的请求,此时要注意处理无效请求情况,例如无效楼层请求,比如超过大楼的最高或最低楼层。还需要考虑电梯的空闲状态,当没有请求时,电梯停留在当前楼层。
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),具体运行规则详见输入输出样例。

输入格式:

第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

  • 电梯内乘客请求格式:<楼层数>
  • 电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
  • 当输入“end”时代表输入结束(end不区分大小写)。

输出格式:

模拟电梯的运行过程,输出方式如下:

  • 运行到某一楼层(不需要停留开门),输出一行文本:
    Current Floor: 楼层数 Direction: 方向
  • 运行到某一楼层(需要停留开门)输出两行文本:
    Open Door # Floor 楼层数
    Close Door

第二次:

对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(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

第三次:

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

电梯运行规则与前阶段相同,但有如下变动情况:

  • 乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
  • 对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)

注意:本次作业类设计必须符合如上要求(包含但不限于设计电梯类、乘客类、队列类以及控制类),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次及第二次电梯程序提交到本次题目中测试)。

输入格式:

第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。

  • 电梯内乘客请求格式:<楼层数>
  • 电梯外乘客请求格式:<请求源楼层,请求目的楼层>,其中,请求源楼层表示乘客发起请求所在的楼层,请求目的楼层表示乘客想要到达的楼层。
  • 当输入“end”时代表输入结束(end不区分大小写)。

输出格式:

模拟电梯的运行过程,输出方式如下:

  • 运行到某一楼层(不需要停留开门),输出一行文本:
    Current Floor: 楼层数 Direction: 方向
  • 运行到某一楼层(需要停留开门)输出两行文本:
    Open Door # Floor 楼层数
    Close Door

设计与分析

第一次作业:

对源码分析结果如下:

前期构思:

先阅读题目,提到有一个电梯类,包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列其中,电梯外部请求队列需要区分上行和下行

所以从中总结出,电梯类中方法有门的开关,用户请求的输入输出,判断运行方向,运行状态,电梯运行,楼层移动等方法。同时主方法中需要对输入的格式进行拆分。

中期编写:

首先搭建框架,大概将每个方法写出对内容不进行填充,在其中提前想好用户请求的的类型,这里选择采用ArrayList,便于增删改以及不限制请求数量。对于电梯的运行采用判断方向-楼层移动-判断是否应该开门(停止)这一运行逻辑。其中对于方向的判定和是否停止程序书写比较简陋,简单将目标请求与当前楼层相比较,留到后续再精细化。对于主方法中的输入格式拆分询问了同学,选择采用正则表达式,如下所示:

String regex = "<(.*?)>"; // 匹配<>之间的内容

Pattern pattern = Pattern.compile(regex);

String[] parts = new String[0];

do

{

floor = in.nextLine();

Matcher matcher = pattern.matcher(floor);

String request;

while (matcher.find())

{

request = matcher.group(1); // 输出<>之间的内容

parts = request.split(","); // 分离,两侧内容

// parts:{"number","direction"}

}

if(!floor.equals("end")&&!floor.equals("END"))

{

if (parts.length == 1)

{ // 内部请求

}

else if (parts.length == 2)

{ // 外部请求

}

}

else

break;

} while (!floor.equals("end")&&!floor.equals("END"));

如此大致框架搭建完成。

最终实现:

对于方向的判定和是否停止进行进一步详细实现。尝试多if-else的方法,发现主要判断在于是否第一次运行,若是则为方向UP,若否则进入下一步判定,然后对于内外部请求是否都不为空,是否一个为空一个不为空,然后对每种情况进行讨论。

对于门的开关与是否停止由于前期思考不充分,所以将两者放在同一个类中(这里需要注意类的单一原则),将内外请求与当前楼层相比较,如果内部请求与当前楼层一直则停止开门,如果外部请求与楼层一致需要考虑方向与当前运行方向是否一致。

总结:

第一次主要对于题目的理解不透彻,导致中间走了许多弯路,如请求的输入是否对输入一个一个判定(当时未想到正则表达式)。运行规则的设计,有时会导致输出开关门又不输出当前楼层,与预期输出不符合。总之第一次作业是对这个系统的熟悉,为后续的迭代做基础与基本学习。

第二次作业:

对源码分析结果如下:

迭代设计:

本次作业要求将原本的电梯类中的各个方法改写为类,同时增加了对于输入重复的考虑。所以对于电梯程序的运行并没有太大改动,同时在此次作业中主要考察对类结构的使用,根据题目给出的类图进行迭代。

总结:

在本次中作业中,对于类相互的关系进行重点考察,主要改动在于主函数中新加入了一个lastin与lastout变量以检测本次输入的楼层与上一次输入的楼层是否重复,每次输入后若输入不重复last变量就等于本次输入楼层,以此进行检测。

第三次作业:

对源码分析结果如下:

迭代设计:

本次作业要求对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类(当时写的时候没有注意到加入乘客类取消乘客请求类,导致提交成功的时候已经来不及修改了,所以一定要注意审题!!!!!!!),逻辑为由乘客请求与当前楼层是否一致进行判断是否停止。同时对输入进行修改。由<楼层,方向><进入楼层,请求到达楼层>,所以主要对类修改与主方法输入修改,根据题目给出的提示就是将外部请求的目标楼层放于内部请求的末尾,所以只需在乘客请求中进行完善即可。

总结:

本次电梯由于加入了乘客类与我最初判断方向的设计有一定偏差,所以在方向判定和是否停止类相当于重写了一遍,总体来说这次题目主要考察了对题目的了解程度,对程序运行逻辑的了解。

踩坑心得

审题马虎:

写较复杂题目时没仔细查看各个环节的要求如:

编程过程中未发现仅考虑头请求进行比较,导致走了很多弯路,所以一定要审好题在进行编程设计。

非零返回问题:

end未区分大小写以及Arraylist未初始化导致了提交时总出现非零返回。重新在CSDN上重新学习了Arraylist的使用方法才逐步解决。所以在使用一个工具时一定要先看明白使用说明书。

输出开关门时不输出当前移动楼层:

例如题目要求的输出是:

Current Floor: 1 Direction: UP

Current Floor: 2 Direction: UP

Current Floor: 3 Direction: UP

Open Door # Floor 3

Close Door

在我修改之前的输出为:

Current Floor: 1 Direction: UP

Current Floor: 2 Direction: UP

Open Door # Floor 3

Close Door

这是由于电梯运行方法中,移动楼层与判断开关门以及判断方向的三种方法的逻辑关联出现问题。

电梯到达目标楼层多运动一次:

这是由于电梯方向的判定出现问题,在当前运行方向若遇到外部请求方向相反应该进行判断是否还有与当前方向一致的内部请求,不然会出现在判断外部请求方向不一致后继续往前移动的结果,最终导致在两个楼层之间多运动一次

例如题目要求:

Current Floor: 1 Direction: UP

Current Floor: 2 Direction: UP

Current Floor: 3 Direction: UP

Open Door # Floor 3

Close Door

未修改前输出:

Current Floor: 1 Direction: UP

Current Floor: 2 Direction: UP

Current Floor: 3 Direction: UP

Current Floor: 4 Direction: DOWN

Current Floor: 3 Direction: DOWN

Open Door # Floor 3

Close Door

在第三次迭代中采用到达目标楼层这一逻辑可以避免该种问题。

改进建议

第一次题目中需要改进最大的一处是对于各个方法功能的区分,开关门方法就只有对于门的状态改变,判断是否停下就只有判断这一功能,不应该将两者混合。其余的地方在于对逻辑的进一步修改,减少if-else的使用。

其次对于注释的使用较少,从而导致自己写着写着忘记了之前的代码作用,最终使得写代码过程中来回翻找和回忆,浪费了时间。督促自己一定要及时增加注释,养成良好习惯。

对于类的单一职责理解不够,例如在控制类中又加入了判断的方法,导致控制类十分臃肿。应该后续设计一个判断类,从而进一步实现类的单一职责。

总结

学习成果:

本次作业中学习到了ArrayList的使用与正则表达式的使用方法,并且在本次题目中多有实践,例如:

同时对于类之间的相互使用的更加熟练,对于这种相对以往更大的程序也拥有了一套自己的做题方法:

第一步:先搭建整体框架,将所需要实现的类的属性方法都简单给出,主要在于不出现语法错误以及程序能正常输入输出。

第二步:开始仔细审查题目中对于各个类的要求,对于方法的实现,然后开始逐步完善方法,主要还是在于初步能符合题目所给出的输入输出。

第三步:细究细节,能够真正解决题目,完成作答且符合题目要求。

对题目的改进建议:

加强测试点与测试样例的联系:

在提交过程中给出的测试样例都通过了但测试点仍旧有几个没通过,同学提交时给出的测试样例没通过但最终提交却全对了,所以希望可以加强二者之间的关系,方便学生快速找到自己的问题所在。

posted @ 2025-04-18 21:49  桦叶梧桐  阅读(60)  评论(0)    收藏  举报