关于单部电梯调度程序作业的想法和总结
一、前言:
在本轮题集中,第5次题集主要考察了java中单个类的创建和设计,第6次和第7次题集则迭代了多类的设计和单一职责。总体而言,本轮题集的题量并不多,重点在于理清类与类之间的关系。除了三次迭代的电梯运行程序难度较大外,其余题目难度适中。
二、设计与分析:
题集5第一次电梯程序迭代:
点击查看题目
设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。
电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。
使用键盘模拟输入乘客的请求,此时要注意处理无效请求情况,例如无效楼层请求,比如超过大楼的最高或最低楼层。还需要考虑电梯的空闲状态,当没有请求时,电梯停留在当前楼层。
请编写一个Java程序,设计一个电梯类,包含状态管理、请求队列管理以及调度算法,并使用一些测试用例,模拟不同的请求顺序,观察电梯的行为是否符合预期,比如是否优先处理同方向的请求,是否在移动过程中处理顺路的请求等。为了降低编程难度,不考虑同时有多个乘客请求同时发生的情况,即采用串行处理乘客的请求方式(电梯只按照规则响应请求队列中当前的乘客请求,响应结束后再响应下一个请求),具体运行规则详见输入输出样例。
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
输入样例:
在这里给出一组输入。例如:
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
点击查看代码
import java.util.LinkedList;
import java.util.Scanner;
enum Direction {
UP,
DOWN,
NONE
}
enum Status {
MOVE,
STOP
}
class Elevator {
private int maxFloor;
private int minFloor;
private int currentFloor;
private Direction direction;
private Status status;
int targetfloor;
private LinkedList<InternalRequest> internalRequests = new LinkedList<>(); // 改为LinkedList
private LinkedList<ExternalRequest> externalRequests = new LinkedList<>(); // 改为LinkedList
public Elevator(int maxFloor, int minFloor) {
this.maxFloor = maxFloor;
this.minFloor = minFloor;
this.currentFloor = 1;
this.targetfloor = currentFloor;
this.direction = Direction.UP;
this.status = Status.STOP;
}
public static class InternalRequest {
private int floor;
public InternalRequest(int floor) {
this.floor = floor;
}
public int getFloor() {
return floor;
}
}
public static class ExternalRequest {
private int floor;
private Direction direction;
public ExternalRequest(int floor, Direction direction) {
this.floor = floor;
this.direction = direction;
}
public int getFloor() {
return floor;
}
public Direction getDirection() {
return direction;
}
}
public void addInternalRequest(int floor) {
if (floor >= minFloor && floor <= maxFloor) {
internalRequests.add(new InternalRequest(floor));
}
}
public void addExternalRequest(int floor, Direction direction) {
if (floor >= minFloor && floor <= maxFloor) {
externalRequests.add(new ExternalRequest(floor, direction));
}
}
public LinkedList<InternalRequest> getInternalRequests() { // 返回类型改为LinkedList
return internalRequests;
}
public LinkedList<ExternalRequest> getExternalRequests() { // 返回类型改为LinkedList
return externalRequests;
}
private int findtargetfloor() {
if (externalRequests.isEmpty() && internalRequests.isEmpty()) {
return currentFloor;
} else if (externalRequests.isEmpty()) {
return internalRequests.getFirst().getFloor(); // get(0) -> getFirst()
} else if (internalRequests.isEmpty()) {
return externalRequests.getFirst().getFloor(); // get(0) -> getFirst()
} else {
int externalHeadfloor = externalRequests.getFirst().getFloor(); // get(0) -> getFirst()
Direction externalHeaddirection = externalRequests.getFirst().getDirection();
int internalHeadfloor = internalRequests.getFirst().getFloor(); // get(0) -> getFirst()
if (!internalRequests.isEmpty() && !externalRequests.isEmpty()) {
if (externalHeadfloor >= currentFloor && internalHeadfloor >= currentFloor) {
if (internalHeadfloor <= externalHeadfloor) {
targetfloor = internalHeadfloor;
} else if (externalHeadfloor <= internalHeadfloor) {
if (direction == externalHeaddirection) {
targetfloor = externalHeadfloor;
} else {
targetfloor = internalHeadfloor;
}
}
} else if ((externalHeadfloor >= currentFloor && currentFloor >= internalHeadfloor)
|| (internalHeadfloor >= currentFloor && currentFloor >= externalHeadfloor)) {
if (direction == Direction.UP) {
targetfloor = externalHeadfloor >= internalHeadfloor ? externalHeadfloor : internalHeadfloor;
} else if (direction == Direction.DOWN) {
targetfloor = externalHeadfloor >= internalHeadfloor ? internalHeadfloor : externalHeadfloor;
}
} else if (externalHeadfloor <= currentFloor && internalHeadfloor <= currentFloor) {
if (internalHeadfloor >= externalHeadfloor) {
targetfloor = internalHeadfloor;
} else if (externalHeadfloor >= internalHeadfloor) {
if (direction == externalHeaddirection) {
targetfloor = externalHeadfloor;
} else {
targetfloor = internalHeadfloor;
}
}
}
} else if (!internalRequests.isEmpty() && externalRequests.isEmpty()) {
targetfloor = internalHeadfloor;
} else if (internalRequests.isEmpty() && !externalRequests.isEmpty()) {
targetfloor = externalHeadfloor;
}
return targetfloor;
}
}
private void moveToTarget() {
if (currentFloor == targetfloor) return;
Direction newDirection = (targetfloor > currentFloor) ? Direction.UP : Direction.DOWN;
int steps = Math.abs(targetfloor - currentFloor);
for (int i = 1; i <= steps; i++) {
currentFloor = (newDirection == Direction.UP) ? currentFloor + 1 : currentFloor - 1;
System.out.println("Current Floor: " + currentFloor + " Direction: " + newDirection);
}
direction = newDirection;
}
private Direction decideDirection() {
if (targetfloor > currentFloor) {
direction = Direction.UP;
} else if (targetfloor < currentFloor) {
direction = Direction.DOWN;
} else {
if (!internalRequests.isEmpty() && (targetfloor == internalRequests.getFirst().getFloor())) { // get(0) -> getFirst()
if (internalRequests.size() > 1 && !externalRequests.isEmpty()) {
if ((internalRequests.get(1).getFloor() <= targetfloor)
&& (externalRequests.getFirst().getFloor() <= targetfloor)) { // get(0) -> getFirst()
direction = Direction.DOWN;
} else if ((internalRequests.get(1).getFloor() >= targetfloor)
&& (externalRequests.getFirst().getFloor() >= targetfloor)) { // get(0) -> getFirst()
direction = Direction.UP;
}
}
}
if (!externalRequests.isEmpty() && (targetfloor == externalRequests.getFirst().getFloor())) { // get(0) -> getFirst()
if (externalRequests.size() > 1 && !internalRequests.isEmpty()) {
if ((externalRequests.get(1).getFloor() <= targetfloor)
&& (internalRequests.getFirst().getFloor() <= targetfloor)) { // get(0) -> getFirst()
direction = Direction.DOWN;
} else if ((externalRequests.get(1).getFloor() >= targetfloor)
&& (internalRequests.getFirst().getFloor() >= targetfloor)) { // get(0) -> getFirst()
direction = Direction.UP;
} else {
direction = externalRequests.getFirst().getDirection(); // get(0) -> getFirst()
}
}
}
}
return direction;
}
private void Door() {
moveToTarget();
direction = decideDirection();
if ((currentFloor == targetfloor) && (!internalRequests.isEmpty() || !externalRequests.isEmpty())) {
System.out.println("Open Door # Floor " + currentFloor);
System.out.println("Close Door");
if (!internalRequests.isEmpty() && internalRequests.getFirst().getFloor() == currentFloor) {
internalRequests.removeFirst();
}
if (!externalRequests.isEmpty() && externalRequests.getFirst().getFloor() == currentFloor) {
externalRequests.removeFirst();
}
targetfloor = findtargetfloor();
}
}
public void processRequests() {
System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
targetfloor = findtargetfloor();
while (!internalRequests.isEmpty() || !externalRequests.isEmpty()) {
Door();
}
}
}
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String data;
Direction direction = null;
int floor = 0;
String request = "";
LinkedList<String> list = new LinkedList<>(); // 改用LinkedList
data = input.next();
while (!data.equalsIgnoreCase("End")) {
list.add(data);
data = input.next();
}
int minFloor = Integer.parseInt(list.get(0));
int maxFloor = Integer.parseInt(list.get(1));
Elevator elevator = new Elevator(maxFloor, minFloor);
for (int i = 2; i < list.size(); i++) {
request = list.get(i);
if (request.contains(",")) {
if (!request.matches("<\\d+,\\s*(UP|DOWN)>")) {
System.out.println("Wrong Format");
}
String[] parts = request.replaceAll("[<>]", "").split(",");
floor = Integer.parseInt(parts[0].trim());
direction = Direction.valueOf(parts[1].trim().toUpperCase());
elevator.addExternalRequest(floor, direction);
} else {
if (!request.matches("<\\d+>")) {
System.out.println("Wrong Format");
}
floor = Integer.parseInt(request.replaceAll("[<>]", ""));
elevator.addInternalRequest(floor);
}
}
elevator.processRequests();
input.close();
}
}
设计思路:
| 根据输入请求后生成的两个队列的头元素来确定目标楼层,向目标楼层移动并判断方向,到达目标楼层后处理该层的请求。但运行后超时,后对源码分析发现在我的代码中逐层移动循环太多,故改为直接移动到目标楼层,打印移动过程中的楼层信息和电梯运行方向。 |
源码分析:
使用SourceMonitor对源码分析,结果如下:

个人分析:
从上述结果可知源码存在较多的条件逻辑语句,特别是在目标楼层的判断和电梯运行方向的判断上,使得代码比较复杂,在后续迭代中尝试简化逻辑判断。
心得体会:
其实在本次题集结束前我并没有做出来这次的电梯运行程序,一直没能弄明白其方向的判断逻辑,是题集结束后第二天才想出来,但也存在遗漏一些情况的时候,都是通过idea断点调试一步步试出来的,花费了大量的时间。
题集6第二次电梯程序迭代:
点击查看题目
对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类,具体设计可参考如下类图。
电梯迭代1类图.png
电梯运行规则与前阶段单类设计相同,但要处理如下情况:
乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<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:
在这里给出一组输入。例如:
1
20
< 3,UP>
<5>
<6,DOWN>
<7>
<3>
end
输出样例1:
在这里给出相应的输出。例如:
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
输入样例2:
在这里给出一组输入。例如:
1
20
< 3,UP>
< 3,UP>
<5>
<5>
<5>
<6,DOWN>
<7>
<7>
<3>
<22,DOWN>
<5,DOWN>
<30>
END
输出样例2:
在这里给出相应的输出。例如:
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
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
点击查看代码
import java.util.LinkedList;
import java.util.Scanner;
enum Direction {
UP,
DOWN,
NONE
}
class InternalRequest {
private final int floor;
public InternalRequest(int floor) {
this.floor = floor;
}
public int getFloor() {
return floor;
}
}
class ExternalRequest {
private final int floor;
private final Direction direction;
public ExternalRequest(int floor, Direction direction) {
this.floor = floor;
this.direction = direction;
}
public int getFloor() {
return floor;
}
public Direction getDirection() {
return direction;
}
}
class RequestQueue {
private final LinkedList<InternalRequest> internalRequests = new LinkedList<>();
private final LinkedList<ExternalRequest> externalRequests = new LinkedList<>();
private final int minFloor;
private final int maxFloor;
public RequestQueue(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
}
public void addExternalRequest(int floor, Direction direction) {
if (floor < minFloor || floor > maxFloor) {
return;
}
if (!externalRequests.isEmpty()) {
ExternalRequest lastRequest = externalRequests.getLast();
if (lastRequest.getFloor() == floor && lastRequest.getDirection() == direction) {
return;
}
}
externalRequests.add(new ExternalRequest(floor, direction));
}
public void addInternalRequest(int floor) {
if (floor < minFloor || floor > maxFloor) {
return;
}
if (!internalRequests.isEmpty()) {
InternalRequest lastRequest = internalRequests.getLast();
if (lastRequest.getFloor() == floor) {
return;
}
}
internalRequests.add(new InternalRequest(floor));
}
public LinkedList<InternalRequest> getInternals() {
return internalRequests;
}
public LinkedList<ExternalRequest> getExternals() {
return externalRequests;
}
}
class Elevator {
private int maxFloor;
private int minFloor;
private int currentFloor;
private Direction direction;
int targetfloor;
public Elevator(int maxFloor, int minFloor) {
this.maxFloor = maxFloor;
this.minFloor = minFloor;
this.currentFloor = 1;
this.targetfloor = currentFloor;
this.direction = Direction.UP;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
public int getCurrentFloor() {
return currentFloor;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public void setTargetfloor(int targetfloor){
this.targetfloor = targetfloor;
}
public int getTargetfloor(){
return targetfloor;
}
public void moveToTarget() {
if (currentFloor == targetfloor) return;
Direction newDirection = (targetfloor > currentFloor) ? Direction.UP : Direction.DOWN;
int steps = Math.abs(targetfloor - currentFloor);
for (int i = 1; i <= steps; i++) {
currentFloor = (newDirection == Direction.UP) ? currentFloor + 1 : currentFloor - 1;
System.out.println("Current Floor: " + currentFloor + " Direction: " + newDirection);
}
direction = newDirection;
}
public void doorOperation() {
System.out.println("Open Door # Floor " + currentFloor);
System.out.println("Close Door");
}
}
class Controller {
private final Elevator elevator;
private final RequestQueue queue;
public Controller(int minFloor, int maxFloor) {
this.elevator = new Elevator(minFloor, maxFloor);
this.queue = new RequestQueue(minFloor, maxFloor);
}
public RequestQueue getQueue(){
return queue;
}
private int findtargetfloor() {
LinkedList<ExternalRequest> externalRequests = queue.getExternals();
LinkedList<InternalRequest> internalRequests = queue.getInternals();
int currentFloor = elevator.getCurrentFloor();
int targetfloor = elevator.getTargetfloor();
Direction direction = elevator.getDirection();
if (externalRequests.isEmpty() && internalRequests.isEmpty()) {
return currentFloor;
} else if (externalRequests.isEmpty()) {
return internalRequests.getFirst().getFloor();
} else if (internalRequests.isEmpty()) {
return externalRequests.getFirst().getFloor();
} else {
int externalHeadfloor = externalRequests.getFirst().getFloor();
Direction externalHeaddirection = externalRequests.getFirst().getDirection();
int internalHeadfloor = internalRequests.getFirst().getFloor();
if (!internalRequests.isEmpty() && !externalRequests.isEmpty()) {
if (externalHeadfloor >= currentFloor && internalHeadfloor >= currentFloor) {
if (internalHeadfloor <= externalHeadfloor) {
targetfloor = internalHeadfloor;
} else if (externalHeadfloor <= internalHeadfloor) {
if (direction == externalHeaddirection) {
targetfloor = externalHeadfloor;
} else {
targetfloor = internalHeadfloor;
}
}
} else if ((externalHeadfloor >= currentFloor && currentFloor >= internalHeadfloor)
|| (internalHeadfloor >= currentFloor && currentFloor >= externalHeadfloor)) {
if (direction == Direction.UP) {
targetfloor = externalHeadfloor >= internalHeadfloor ? externalHeadfloor : internalHeadfloor;
} else if (direction == Direction.DOWN) {
targetfloor = externalHeadfloor >= internalHeadfloor ? internalHeadfloor : externalHeadfloor;
}
} else if (externalHeadfloor <= currentFloor && internalHeadfloor <= currentFloor) {
if (internalHeadfloor >= externalHeadfloor) {
targetfloor = internalHeadfloor;
} else if (externalHeadfloor >= internalHeadfloor) {
if (direction == externalHeaddirection) {
targetfloor = externalHeadfloor;
} else {
targetfloor = internalHeadfloor;
}
}
}
} else if (!internalRequests.isEmpty() && externalRequests.isEmpty()) {
targetfloor = internalHeadfloor;
} else if (internalRequests.isEmpty() && !externalRequests.isEmpty()) {
targetfloor = externalHeadfloor;
}
return targetfloor;
}
}
private Direction decideDirection() {
LinkedList<ExternalRequest> externalRequests = queue.getExternals();
LinkedList<InternalRequest> internalRequests = queue.getInternals();
int currentFloor = elevator.getCurrentFloor();
int targetfloor = elevator.getTargetfloor();
Direction direction = elevator.getDirection();
if (targetfloor > currentFloor) {
direction = Direction.UP;
} else if (targetfloor < currentFloor) {
direction = Direction.DOWN;
} else {
if (!internalRequests.isEmpty() && (targetfloor == internalRequests.getFirst().getFloor())) {
if (internalRequests.size() > 1 && !externalRequests.isEmpty()) {
if ((internalRequests.get(1).getFloor() <= targetfloor)
&& (externalRequests.getFirst().getFloor() <= targetfloor)) {
direction = Direction.DOWN;
} else if ((internalRequests.get(1).getFloor() >= targetfloor)
&& (externalRequests.getFirst().getFloor() >= targetfloor)) {
direction = Direction.UP;
}
}
}
if (!externalRequests.isEmpty() && (targetfloor == externalRequests.getFirst().getFloor())) {
if (externalRequests.size() > 1 && !internalRequests.isEmpty()) {
if ((externalRequests.get(1).getFloor() <= targetfloor)
&& (internalRequests.getFirst().getFloor() <= targetfloor)) {
direction = Direction.DOWN;
} else if ((externalRequests.get(1).getFloor() >= targetfloor)
&& (internalRequests.getFirst().getFloor() >= targetfloor)) {
direction = Direction.UP;
} else {
direction = externalRequests.getFirst().getDirection();
}
}
}
}
return direction;
}
private void Arrival() {
Direction newDirection = decideDirection();
elevator.setDirection(newDirection);
elevator.doorOperation();
removeProcessedRequests();
int targetfloor = findtargetfloor();
elevator.setTargetfloor(targetfloor);
}
private void removeProcessedRequests() {
LinkedList<ExternalRequest> externalRequests = queue.getExternals();
LinkedList<InternalRequest> internalRequests = queue.getInternals();
int currentFloor = elevator.getCurrentFloor();
if (!internalRequests.isEmpty() && internalRequests.getFirst().getFloor() == currentFloor) {
internalRequests.removeFirst();
}
if (!externalRequests.isEmpty() && externalRequests.getFirst().getFloor() == currentFloor) {
externalRequests.removeFirst();
}
}
public void processRequests() {
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
elevator.setTargetfloor(findtargetfloor());
while (!queue.getInternals().isEmpty() || !queue.getExternals().isEmpty()) {
elevator.moveToTarget();
Arrival();
}
}
}
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String data;
Direction direction = null;
int floor = 0;
String request = "";
LinkedList<String> list = new LinkedList<>();
data = input.next();
while (!data.equalsIgnoreCase("End")) {
list.add(data);
data = input.next();
}
int minFloor = Integer.parseInt(list.get(0));
int maxFloor = Integer.parseInt(list.get(1));
Controller controller = new Controller(minFloor, maxFloor);
for (int i = 2; i < list.size(); i++) {
request = list.get(i);
if (request.contains(",")) {
if (!request.matches("<\\d+,\\s*(UP|DOWN)>")) {
continue;
}
String[] parts = request.replaceAll("[<>]", "").split(",");
floor = Integer.parseInt(parts[0].trim());
direction = Direction.valueOf(parts[1].trim().toUpperCase());
controller.getQueue().addExternalRequest(floor,direction);
} else {
if (!request.matches("<\\d+>")) {
continue;
}
floor = Integer.parseInt(request.replaceAll("[<>]", ""));
controller.getQueue().addInternalRequest(floor);
}
}
controller.processRequests();
input.close();
}
}
设计思路:
| 按照题目要求将上次电梯程序拆分为电梯类、乘客请求类、队列类以及控制类,简化目标楼层和电梯运行方向的判断逻辑,严格遵循单一职责原则(SRP)。 |
源码分析:
使用SourceMonitor对源码分析,结果如下:

个人分析:
在本次迭代中简化了代码的一些条件判断逻辑,同时在类的划分中尽量遵循了单一职责原则,如Dooroperations就只负责打印门的开关,但还是存在很多不必要的循环。
心得体会:
在本次迭代中,由于不同类的划分,在类与类的关系和调用不同类的方法时,会出现错误,如在电梯运行判断方向时,一开始并未将判断后的方向更新返回到电梯类中,导致电梯的运行出现问题,并且,发现在电梯运行时目标楼层的查询和运行方向的判断时机需要严格掌握,仅仅将判断句调换个位置,就可能出现不同结果,导致程序无限循环。
题集7第三次电梯程序迭代:
点击查看题目
对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类,具体设计可参考如下类图。
类图.png
电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)
注意:本次作业类设计必须符合如上要求(包含但不限于设计电梯类、乘客类、队列类以及控制类),凡是不符合类设计要求此题不得分,另外,PTA得分代码界定为第一次提交的最高分代码(因此千万不要把第一次及第二次电梯程序提交到本次题目中测试)。
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<请求源楼层,请求目的楼层>,其中,请求源楼层表示乘客发起请求所在的楼层,请求目的楼层表示乘客想要到达的楼层。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
输入样例1:
在这里给出一组输入。例如:
1
20
<5,4>
<5>
<7>
end
输出样例1:
在这里给出相应的输出。例如:
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
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Open Door # Floor 5
Close Door
Current Floor: 4 Direction: DOWN
Open Door # Floor 4
Close Door
输入样例2:
在这里给出一组输入。例如:
1
20
<5,9>
<8>
<9,3>
<4>
<2>
end
输出样例2:
在这里给出相应的输出。例如:
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
点击查看代码
import java.util.LinkedList;
import java.util.Scanner;
enum Direction {
UP,
DOWN,
NONE
}
class Passenger {
private final int sourceFloor;
private final int destinationFloor;
public Passenger(int sourceFloor, int destinationFloor) {
this.sourceFloor = sourceFloor;
this.destinationFloor = destinationFloor;
}
public int getSourceFloor() {
return sourceFloor;
}
public int getDestinationFloor() {
return destinationFloor;
}
public Direction getDirection() {
if(destinationFloor > sourceFloor){
return Direction.UP;
}else{
return Direction.DOWN;
}
}
}
class RequestQueue {
private final LinkedList<Integer> internalRequests = new LinkedList<>();
private final LinkedList<Passenger> externalRequests = new LinkedList<>();
private final int minFloor;
private final int maxFloor;
public RequestQueue(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
}
public void addExternalRequest(int sourceFloor,int destinationFloor) {
if (sourceFloor < minFloor || sourceFloor > maxFloor) {
return;
}
if(destinationFloor < minFloor || destinationFloor > maxFloor){
return;
}
if (!externalRequests.isEmpty()) {
Passenger lastRequest = externalRequests.getLast();
if (lastRequest.getSourceFloor() == sourceFloor && lastRequest.getDestinationFloor() == destinationFloor) {
return;
}
}
externalRequests.add(new Passenger(sourceFloor,destinationFloor));
}
public void addInternalRequest(int floor) {
if (floor < minFloor || floor > maxFloor) {
return;
}
if (!internalRequests.isEmpty() && internalRequests.getLast() == floor) {
return;
}
internalRequests.add(floor);
}
public LinkedList<Passenger> getExternals() {
return externalRequests;
}
public LinkedList<Integer> getInternals() {
return internalRequests;
}
}
class Elevator {
private int maxFloor;
private int minFloor;
private int currentFloor;
private Direction direction;
int targetfloor;
public Elevator(int maxFloor, int minFloor) {
this.maxFloor = maxFloor;
this.minFloor = minFloor;
this.currentFloor = 1;
this.targetfloor = currentFloor;
this.direction = Direction.UP;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
public int getCurrentFloor() {
return currentFloor;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public void setTargetfloor(int targetfloor){
this.targetfloor = targetfloor;
}
public int getTargetfloor(){
return targetfloor;
}
public void moveToTarget() {
if (currentFloor == targetfloor) return;
Direction newDirection = (targetfloor > currentFloor) ? Direction.UP : Direction.DOWN;
int steps = Math.abs(targetfloor - currentFloor);
for (int i = 1; i <= steps; i++) {
currentFloor = (newDirection == Direction.UP) ? currentFloor + 1 : currentFloor - 1;
System.out.println("Current Floor: " + currentFloor + " Direction: " + newDirection);
}
direction = newDirection;
}
public void doorOperation() {
System.out.println("Open Door # Floor " + currentFloor);
System.out.println("Close Door");
}
}
class Controller {
private final Elevator elevator;
private final RequestQueue queue;
public Controller(int minFloor, int maxFloor) {
this.elevator = new Elevator(minFloor, maxFloor);
this.queue = new RequestQueue(minFloor, maxFloor);
}
public RequestQueue getQueue(){
return queue;
}
private int findtargetfloor() {
LinkedList<Passenger> externalRequests = queue.getExternals();
LinkedList<Integer> internalRequests = queue.getInternals();
int currentFloor = elevator.getCurrentFloor();
int targetfloor = elevator.getTargetfloor();
Direction direction = elevator.getDirection();
if (externalRequests.isEmpty() && internalRequests.isEmpty()) {
return currentFloor;
} else if (externalRequests.isEmpty()) {
return internalRequests.getFirst();
} else if (internalRequests.isEmpty()) {
return externalRequests.getFirst().getSourceFloor();
} else {
int externalHeadfloor = externalRequests.getFirst().getSourceFloor();
Direction externalHeaddirection = externalRequests.getFirst().getDirection();
int internalHeadfloor = internalRequests.getFirst();
if (!internalRequests.isEmpty() && !externalRequests.isEmpty()) {
if (externalHeadfloor >= currentFloor && internalHeadfloor >= currentFloor) {
if (internalHeadfloor <= externalHeadfloor) {
targetfloor = internalHeadfloor;
} else if (externalHeadfloor <= internalHeadfloor) {
if (direction == externalHeaddirection) {
targetfloor = externalHeadfloor;
} else {
targetfloor = internalHeadfloor;
}
}
} else if ((externalHeadfloor > currentFloor && currentFloor > internalHeadfloor)
|| (internalHeadfloor > currentFloor && currentFloor > externalHeadfloor)) {
if (direction == Direction.UP) {
targetfloor = externalHeadfloor >= internalHeadfloor ? externalHeadfloor : internalHeadfloor;
} else if (direction == Direction.DOWN) {
targetfloor = externalHeadfloor >= internalHeadfloor ? internalHeadfloor : externalHeadfloor;
}
} else if (externalHeadfloor <= currentFloor && internalHeadfloor <= currentFloor) {
if (internalHeadfloor >= externalHeadfloor) {
targetfloor = internalHeadfloor;
} else if (externalHeadfloor >= internalHeadfloor) {
if (direction == externalHeaddirection) {
targetfloor = externalHeadfloor;
} else {
targetfloor = internalHeadfloor;
}
}
}
} else if (!internalRequests.isEmpty() && externalRequests.isEmpty()) {
targetfloor = internalHeadfloor;
} else if (internalRequests.isEmpty() && !externalRequests.isEmpty()) {
targetfloor = externalHeadfloor;
}
return targetfloor;
}
}
private Direction decideDirection() {
LinkedList<Passenger> externalRequests = queue.getExternals();
LinkedList<Integer> internalRequests = queue.getInternals();
int currentFloor = elevator.getCurrentFloor();
int targetfloor = elevator.getTargetfloor();
Direction direction = elevator.getDirection();
if (targetfloor > currentFloor) {
direction = Direction.UP;
} else if (targetfloor < currentFloor) {
direction = Direction.DOWN;
} else {
if (!internalRequests.isEmpty() && (targetfloor == internalRequests.getFirst())) {
if (internalRequests.size() > 1 && !externalRequests.isEmpty()) {
if ((internalRequests.get(1) <= targetfloor)
&& (externalRequests.getFirst().getSourceFloor() <= targetfloor)) {
direction = Direction.DOWN;
} else if ((internalRequests.get(1) >= targetfloor)
&& (externalRequests.getFirst().getSourceFloor() >= targetfloor)) {
direction = Direction.UP;
}
}
}
if (!externalRequests.isEmpty() && (targetfloor == externalRequests.getFirst().getSourceFloor())) {
if (externalRequests.size() > 1 && !internalRequests.isEmpty()) {
if ((externalRequests.get(1).getSourceFloor() <= targetfloor)
&& (internalRequests.getFirst() <= targetfloor)) {
direction = Direction.DOWN;
} else if ((externalRequests.get(1).getSourceFloor() >= targetfloor)
&& (internalRequests.getFirst() >= targetfloor)) {
direction = Direction.UP;
} else {
direction = externalRequests.getFirst().getDirection();
}
}else if(internalRequests.isEmpty()){
direction = externalRequests.getFirst().getDirection();
}
}
}
return direction;
}
private void Arrival() {
Direction newDirection = decideDirection();
elevator.setDirection(newDirection);
elevator.doorOperation();
removeProcessedRequests();
int targetfloor = findtargetfloor();
elevator.setTargetfloor(targetfloor);
newDirection = decideDirection();
elevator.setDirection(newDirection);
removeProcessedRequests();
}
private void removeProcessedRequests() {
LinkedList<Passenger> externals = queue.getExternals();
LinkedList<Integer> internals = queue.getInternals();
int currentFloor = elevator.getCurrentFloor();
if (!externals.isEmpty() && externals.getFirst().getSourceFloor() == currentFloor && externals.getFirst().getDirection() == elevator.getDirection()) {
Passenger passenger = externals.removeFirst();
queue.addInternalRequest(passenger.getDestinationFloor());
}
if (!internals.isEmpty() && internals.getFirst() == currentFloor) {
internals.removeFirst();
}
}
public void processRequests() {
System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
elevator.setTargetfloor(findtargetfloor());
while (!queue.getInternals().isEmpty() || !queue.getExternals().isEmpty()) {
elevator.moveToTarget();
Arrival();
}
}
}
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String data;
Direction direction = null;
int floor = 0;
String request = "";
LinkedList<String> list = new LinkedList<>();
data = input.next();
while (!data.equalsIgnoreCase("End")) {
list.add(data);
data = input.next();
}
int minFloor = Integer.parseInt(list.get(0));
int maxFloor = Integer.parseInt(list.get(1));
Controller controller = new Controller(minFloor, maxFloor);
for (int i = 2; i < list.size(); i++) {
request = list.get(i);
if (request.contains(",")) {
if (!request.matches("<\\d+,\\s*\\d+>")) {
continue;
}
String[] parts = request.replaceAll("[<>]", "").split(",");
int sourceFloor = Integer.parseInt(parts[0].trim());
int destinationFloor = Integer.parseInt(parts[1].trim());
controller.getQueue().addExternalRequest(sourceFloor, destinationFloor);
} else {
if (!request.matches("<\\d+>")) {
continue;
}
floor = Integer.parseInt(request.replaceAll("[<>]", ""));
controller.getQueue().addInternalRequest(floor);
}
}
controller.processRequests();
input.close();
}
}
设计思路:
| 按照本次迭代要求加入乘客类,并取消乘客请求类,分析题目可知主要将之前的外部请求进行修改,并由外部请求的原楼层和目标楼层进行其方向判断,如若目标大于原,相当于原外部请求中方向为UP,同时增加一个到达目标楼层并处理请求后,将外部队列目标楼层添加到内部队列队尾的方法,其它不需要做出太多修改。 |
源码分析:
使用SourceMonitor对源码分析,结果如下:

个人分析:
从上述结果可知源码还是存在较多的条件逻辑语句,在本轮三次迭代中一直没能做到简化条件判断,使得代码比较复杂,在在后续的学习中要加强逻辑思维的训练,同时方法的调用中存在许多不必要的重复。
心得体会:
在本次迭代中并没有花费多少时间,主要是两个地方的调整和改变,同时,在运行代码时,开始四个测试点只通过了两个,再次由断点调试发现问题出在方向判断上漏了情况,导致程序无线循环,在后续学习中要加强思维的严谨性。
三、总结:
1、问题:
在本轮题集中,发现自己没有养成添加注释的习惯,在发现问题并要进行修改时,常常还要重新思考这段代码的用处,使得代码的维护性降低。同时,在条件逻辑判断中还是没能做到最简化,出现许多不必要的代码,降低了代码的运行效率。
2、收获:
在本轮题集中,我能够逐渐理解单一职责原则,理清了类与类之间的关系,并能通过断点调试判断问题所在并解决,虽然要花费很多时间,但也产生了一定的乐趣,体会到了不断修改自己代码所带来的成就感和完成题目后所带来的满足感。
3、反思:
经过本轮题集,在今后的学习中,要形成添加注释的习惯,同时要加强思维逻辑的训练,尽量做到代码的简化,降低代码的复杂度,最后,一定要先理清思路再开始写代码,不要一味埋头苦干,在最开始就是因为没有理清思路导致未完成第一次题集。

浙公网安备 33010602011771号