电梯迭代blog
前言
这三次题目级涉及到了以下知识点:
- 面向对象编程(OOP)概念:类和对象,封装,枚举类型
- Java核心语法:控制结构,数据类型,字符串处理,输入输出
- 集合框架:ArrayList和LinkedList以及相关方法操作,
- 方法设计:方法重载,返回值处理,方法参数
- 状态管理:电梯状态以及方向管理
- 算法逻辑:电梯调度算法,最近楼层计算
我觉得这三次题目无论是从题量还是难度来说都是很大的,从面向对象的设计方面和算法复杂度来说都是前所未有的挑战。
设计与分析
第一次迭代
点击查看题目
设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为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
我的源代码
点击查看代码
java
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String data;
int floor = 0;
String direction = null;
int minFloor,maxFloor;
String request = "";
ArrayList<String> list = new ArrayList<>();
data = input.next();
while(!data.equalsIgnoreCase("End")){
list.add(data);
data = input.next();
}
minFloor = Integer.parseInt(list.get(0));
maxFloor = Integer.parseInt(list.get(1));
Elevator elevator = new Elevator(minFloor, maxFloor);
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 =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.findRequest();
input.close();
}
}
class Elevator{
private int minFloor;
private int maxFloor;
private int currentFloor;
private String direction;
private String status;
private List<Integer> internalRequests;
private List<List<String>> externalRequests;
public Elevator() {
this.minFloor = 1;
this.maxFloor = 1;
this.currentFloor = 1;
this.direction = "IDLE";
this.status = "STOPPED";
this.internalRequests = new ArrayList<>();
this.externalRequests = new ArrayList<>();
}
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = minFloor;
this.direction = "UP";
this.status = "STOPPED";
this.internalRequests = new ArrayList<>();
this.externalRequests = new ArrayList<>();
}
public List<Integer> getInternalRequests() {
return internalRequests;
}
public List<List<String>> getExternalRequests() {
return externalRequests;
}
public boolean checkFloor(int floor){
if(floor<this.minFloor||floor>this.maxFloor)
return false;
return true;
}
public void addExternalRequest(int floor,String direction){
if (checkFloor(floor)) {
List<String> request = new ArrayList<>();
request.add(String.valueOf(floor));
request.add(direction);
if (!externalRequests.contains(request)) {
externalRequests.add(request);
}
}
}
public void addInternalRequest(int floor){
if (checkFloor(floor)) {
if (!internalRequests.contains(floor)) {
internalRequests.add(floor);
}
}
}
public void findRequest() {
String nextdirection1=null;
String nextdirection=null;
int nextFloor1 = Integer.parseInt(externalRequests.get(0).get(0));
int nextFloor = internalRequests.get(0);
if (!internalRequests.isEmpty()&&!externalRequests.isEmpty()) {
if (nextFloor > currentFloor) {
nextdirection1 = "UP";
} else if (nextFloor < currentFloor) {
nextdirection1 = "DOWN";
}
nextdirection = externalRequests.get(0).get(1);
if(this.direction.equals(nextdirection)&&this.direction.equals(nextdirection1)){
if(Math.abs(currentFloor-nextFloor)>Math.abs(currentFloor-nextFloor1))
move(nextFloor1);
else
move(nextFloor);
}
else if(this.direction.equals(nextdirection)&&!this.direction.equals(nextdirection1))
{
move(nextFloor1);
}
else if(!this.direction.equals(nextdirection)&&this.direction.equals(nextdirection1)){
move(nextFloor);
}
else{
this.direction=nextdirection1;
if(Math.abs(currentFloor-nextFloor)>Math.abs(currentFloor-nextFloor1))
move(nextFloor1);
else
move(nextFloor);
}
}
else if (!externalRequests.isEmpty() && internalRequests.isEmpty()) {
this.direction=externalRequests.get(0).get(1);
move(nextFloor1);
}
else if (externalRequests.isEmpty() && !internalRequests.isEmpty()) {
if (nextFloor > currentFloor) {
this.direction = "UP";
} else if (nextFloor < currentFloor) {
this.direction = "DOWN";
}
move(nextFloor);
}
}
public void move(int floor){
if(currentFloor==1)
System.out.printf("Current Floor: %d Direction: %s\n",currentFloor,direction);
this.status = "MOVING";
if("DOWN".equals(this.direction)){
while(currentFloor>floor)
{
this.currentFloor--;
System.out.printf("Current Floor: %d Direction: %s\n",currentFloor,direction);
if(currentFloor==floor){
openDoor();
closeDoor();
}
}
}
else if("UP".equals(this.direction)){
while(currentFloor<floor)
{
this.currentFloor++;
System.out.printf("Current Floor: %d Direction: %s\n",currentFloor,direction);
if(currentFloor==floor){
openDoor();
closeDoor();
}
}
}
if (!internalRequests.isEmpty() || !externalRequests.isEmpty()) {
findRequest();
}
}
public void openDoor(){
this.status="OPENING";
System.out.printf("Open Door # Floor %d\n",currentFloor);
processRequsts();
}
public void closeDoor(){
this.status="CLOSING";
System.out.printf("Close Door\n");
}
public void processRequsts(){
if (!internalRequests.isEmpty() && internalRequests.get(0) == this.currentFloor) {
internalRequests.remove(0);
}
if (!externalRequests.isEmpty()) {
List<String> request = externalRequests.get(0);
int requestFloor = Integer.parseInt(request.get(0));
if (requestFloor == currentFloor) {
externalRequests.remove(0);
}
}
}
}
解释:
我主要是想通过检查内外部头需求的同时判断电梯方向和需求方向,遵循优先同方向的前提条件,执行后删除相应的需求,只不过这次的代码还有很多不足,没有考虑特殊情况,只是很粗略的简单情况的执行。
代码分析:
点击查看代码详细分析(中文)
文件 “elevator1.java” 的度量详情
参数 值
========= =====
项目目录 C:\Users\13458\Desktop\elevator1
项目名称 elevator1
检查点名称 基线
文件名 elevator1.java
行数 197
语句数 148
分支语句百分比 25.0
方法调用语句数 85
带注释的行的百分比 0.0
类和接口数 2
每个类的方法数 6.50
每个方法的平均语句数 9.46
最复杂方法的行号 99
最复杂方法的名称 Elevator.findRequest ()
最大复杂度 22
最深代码块的行号 26
最大代码块深度 5
平均代码块深度 2.55
平均复杂度 4.46
2 个类中最复杂的方法: 复杂度、语句数、最大深度、调用次数
Elevator.addExternalRequest() 3,6,4,7
Elevator.addInternalRequest() 3,3,4,3
Elevator.checkFloor() 2,3,2,0
Elevator.closeDoor() 1,2,2,1
Elevator.Elevator() 1,7,2,0
Elevator.Elevator() 1,7,2,0
Elevator.findRequest() 22,34,4,28
Elevator.getExternalRequests() 1,1,2,0
Elevator.getInternalRequests() 1,1,2,0
Elevator.move() 10,19,5,12
Elevator.openDoor() 1,3,2,2
Elevator.processRequsts() 5,7,4,8
Main.main() 7,30,5,24
代码块深度 语句数
0 5
1 20
2 56
3 29
4 32
5 6
6 0
7 0
8 0
9 及以上 0
心得:
这次电梯调度题我并没有做出来,最后一次提交结果也是非零返回,没能得出最后的正确结果。在最开始的这次题目集里面,我没能很透彻地理解电梯调度的原理,在电梯调度算法这个难点思路混乱,根本想不清楚,很多特殊情况都没有考虑进去,嵌套多个if-else越写越乱,再加上时间紧迫,最后失败了。
第二次迭代
点击查看题目
对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(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:
在这里给出一组输入。例如:
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
可参考以下类图
我的源代码
点击查看代码
import java.util.Scanner;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String data;
int floor = 0;
Direction direction = null;
int minFloor,maxFloor;
String request = "";
LinkedList<String> list = new LinkedList<>();
data = input.next();
String lastRequest = null;
while(!data.equalsIgnoreCase("End")){
list.add(data);
data = input.next();
}
minFloor = Integer.parseInt(list.get(0));
maxFloor = Integer.parseInt(list.get(1));
Elevator elevator = new Elevator(minFloor, maxFloor);
RequestQueue queue = new RequestQueue();
for (int i = 2; i < list.size(); i++) {
request = list.get(i);
if (request.equals(lastRequest)) {
continue;
}
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());
if (!elevator.isValidFloor(floor)) {
continue;
}
queue.addExternalRequest(new ExternalRequest(floor, direction));
} else {
if (!request.matches("<\\d+>")) {
continue;
}
floor = Integer.parseInt(request.replaceAll("[<>]", ""));
if (!elevator.isValidFloor(floor)) {
continue;
}
queue.addInternalRequest(floor);
}
lastRequest = request;
}
Controller controller = new Controller(elevator, queue);
while(!queue.getInternalRequests().isEmpty()
|| !queue.getExternalRequests().isEmpty()){
controller.processRequests();
}
input.close();
}
}
enum Direction {
UP,DOWN,IDLE
}
enum State {
MOVING,STOPPED
}
class Elevator{
private int currentFloor;
private Direction direction;
private State state;
private int maxFloor;
private int minFloor;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = 0;
this.direction = Direction.IDLE;
this.state = State.STOPPED;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getMaxFloor() {
return maxFloor;
}
public int getMinFloor() {
return minFloor;
}
public boolean isValidFloor(int floor) {
if(floor <minFloor || floor > maxFloor){
return false;
}
return true;
}
}
class ExternalRequest{
private Integer floor;
private Direction direction;
public ExternalRequest(Integer floor, Direction direction) {
this.floor = floor;
this.direction = direction;
}
public Integer getFloor() {
return floor;
}
public Direction getDirection() {
return direction;
}
}
class Controller{
private Elevator elevator;
private RequestQueue queue;
public Controller(Elevator elevator, RequestQueue queue) {
this.elevator = elevator;
this.queue = queue;
}
public Elevator getElevator() {
return elevator;
}
public void setElevator(Elevator elevator) {
this.elevator = elevator;
}
public RequestQueue getQueue() {
return queue;
}
public void setQueue(RequestQueue queue) {
this.queue = queue;
}
public void processRequests(){
determineDirection();
Integer nextFloor = getNextFloor();
if(!queue.getExternalRequests().isEmpty()){
ExternalRequest firstRequest = queue.getExternalRequests().get(0);
int externalFloor = firstRequest.getFloor();
Direction externalDirection = firstRequest.getDirection();
if (nextFloor != null) {
if(elevator.getCurrentFloor()==nextFloor){
repeatRequest(nextFloor);
nextFloor=0;
}
else
move(nextFloor);
if(!queue.getInternalRequests().isEmpty()){
int internalFloor=queue.getInternalRequests().peek();
if(nextFloor==externalFloor&&nextFloor==internalFloor){
}
else if(nextFloor==externalFloor)
elevator.setDirection(externalDirection);
}
else{
if(nextFloor==externalFloor)
elevator.setDirection(externalDirection);
}
removeRequests(nextFloor);
}
}
else{
if (nextFloor != null) {
move(nextFloor);
removeRequests(nextFloor);
}
}
}
public void determineDirection(){
if(elevator.getDirection()==Direction.IDLE)
elevator.setDirection(Direction.UP);
if (!queue.getInternalRequests().isEmpty()&&!queue.getExternalRequests().isEmpty()) {
ExternalRequest firstRequest = queue.getExternalRequests().get(0);
Direction externalDirection = firstRequest.getDirection();
int internalFloor=queue.getInternalRequests().peek();
Direction internalDirection;
int externalFloor= firstRequest.getFloor();
if (internalFloor > elevator.getCurrentFloor()) {
internalDirection = Direction.UP;
} else if (internalFloor < elevator.getCurrentFloor()) {
internalDirection = Direction.DOWN;
}
else
internalDirection = elevator.getDirection();
if (elevator.getDirection() == Direction.UP) {
if(externalDirection!=elevator.getDirection()&&internalDirection!=elevator.getDirection()){
if(externalFloor<elevator.getCurrentFloor())
elevator.setDirection(Direction.DOWN);
}
if(externalDirection==elevator.getDirection()&&internalDirection!=elevator.getDirection()){
if(externalFloor<elevator.getCurrentFloor())
elevator.setDirection(Direction.DOWN);
}
}
else{
if(externalDirection!=elevator.getDirection()&&internalDirection!=elevator.getDirection()){
if(externalFloor>elevator.getCurrentFloor())
elevator.setDirection(Direction.UP);
}
}
}
else if(!queue.getInternalRequests().isEmpty()&&queue.getExternalRequests().isEmpty()){
int internalFloor=queue.getInternalRequests().peek();
if (internalFloor > elevator.getCurrentFloor()) {
elevator.setDirection(Direction.UP);
} else if (internalFloor < elevator.getCurrentFloor()) {
elevator.setDirection(Direction.DOWN);
}
}
else if(queue.getInternalRequests().isEmpty()&&!queue.getExternalRequests().isEmpty()){
ExternalRequest firstRequest = queue.getExternalRequests().get(0);
int externalFloor = firstRequest.getFloor();
Direction externalDiretion1;
if (externalFloor > elevator.getCurrentFloor()) {
externalDiretion1=Direction.UP;
} else if (externalFloor < elevator.getCurrentFloor()) {
externalDiretion1=Direction.DOWN;
}
else
externalDiretion1=null;
if(firstRequest.getDirection()==elevator.getDirection()&&externalDiretion1==elevator.getDirection()){
elevator.setDirection(firstRequest.getDirection());
}
else
elevator.setDirection(externalDiretion1);
}
}
public void repeatRequest(int nextFloor){
openDoors();
removeRequests(nextFloor);
if(elevator.getDirection() == Direction.DOWN){
elevator.setDirection(Direction.UP);
}
else if(elevator.getDirection() == Direction.UP){
elevator.setDirection(Direction.DOWN);
}
}
public void move(int floor){
while(elevator.getCurrentFloor()>floor)
{
elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
System.out.printf("Current Floor: %d Direction: %s\n",elevator.getCurrentFloor(),elevator.getDirection());
if(shouldStop(floor)){
openDoors();
}
}
while(elevator.getCurrentFloor()<floor)
{
elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
System.out.printf("Current Floor: %d Direction: %s\n",elevator.getCurrentFloor(),elevator.getDirection());
if(shouldStop(floor)){
openDoors();
}
}
}
public boolean shouldStop(int floor){
if(elevator.getCurrentFloor()==floor){
return true;
}
else
return false;
}
public Integer getNextFloor(){
if (!queue.getInternalRequests().isEmpty()&&!queue.getExternalRequests().isEmpty()) {
ExternalRequest firstRequest = queue.getExternalRequests().get(0);
int externalFloor = firstRequest.getFloor();
int internalFloor=queue.getInternalRequests().peek();
Direction externalDirection = firstRequest.getDirection();
Direction internalDirection;
if (internalFloor > elevator.getCurrentFloor()) {
internalDirection = Direction.UP;
}
else if (internalFloor < elevator.getCurrentFloor()) {
internalDirection = Direction.DOWN;
}
else
internalDirection = elevator.getDirection();
Direction externalDiretion1;
if (externalFloor > elevator.getCurrentFloor()) {
externalDiretion1=Direction.UP;
} else if (externalFloor < elevator.getCurrentFloor()) {
externalDiretion1=Direction.DOWN;
}
else
externalDiretion1=null;
if (elevator.getDirection() == internalDirection&&elevator.getDirection() != externalDirection)
return internalFloor;
else if(elevator.getDirection() != internalDirection&&elevator.getDirection() == externalDirection){
if(externalDiretion1==elevator.getDirection())
return externalFloor;
else
return internalFloor;
}
else if(elevator.getDirection() != internalDirection&&elevator.getDirection() != externalDirection){
if((elevator.getCurrentFloor()-externalFloor)*(elevator.getCurrentFloor()-internalFloor)<0)
return externalFloor;
return getClosest(externalFloor,internalFloor);
}
else
return getClosest(externalFloor,internalFloor);
}
else if(!queue.getInternalRequests().isEmpty()&&queue.getExternalRequests().isEmpty()){
return queue.getInternalRequests().peek();
}
else if(queue.getInternalRequests().isEmpty()&&!queue.getExternalRequests().isEmpty()){
ExternalRequest firstRequest = queue.getExternalRequests().get(0);
return firstRequest.getFloor();
}
else
return null;
}
public Integer getClosest(Integer a,Integer b){
int currentFloor = elevator.getCurrentFloor();
return Math.abs(a - currentFloor) < Math.abs(b - currentFloor) ? a : b;
}
public void openDoors(){
System.out.printf("Open Door # Floor %d\n",elevator.getCurrentFloor());
System.out.printf("Close Door\n");
}
public void removeRequests(int currentFloor){
if (!queue.getInternalRequests().isEmpty() && !queue.getExternalRequests().isEmpty()) {
ExternalRequest firstRequest = queue.getExternalRequests().get(0);
int externalFloor = firstRequest.getFloor();
Direction externalDirection = firstRequest.getDirection();
int internalFloor = queue.getInternalRequests().peek();
Direction internalDirection;
if (internalFloor > elevator.getCurrentFloor()) {
internalDirection = Direction.UP;
} else if (internalFloor < elevator.getCurrentFloor()) {
internalDirection = Direction.DOWN;
} else {
internalDirection = elevator.getDirection();
}
if (elevator.getDirection() == internalDirection && currentFloor == internalFloor) {
queue.getInternalRequests().removeFirst();
}
if (elevator.getDirection() == externalDirection && currentFloor == externalFloor) {
queue.getExternalRequests().removeFirst();
}
} else if (!queue.getInternalRequests().isEmpty() && queue.getExternalRequests().isEmpty()) {
if (currentFloor == queue.getInternalRequests().peek()) {
queue.getInternalRequests().removeFirst();
}
} else if (queue.getInternalRequests().isEmpty() && !queue.getExternalRequests().isEmpty()) {
ExternalRequest firstRequest = queue.getExternalRequests().get(0);
if (currentFloor == firstRequest.getFloor()&&firstRequest.getDirection()==elevator.getDirection()) {
queue.getExternalRequests().removeFirst();
}
}
}
}
class RequestQueue {
private LinkedList<Integer> internalRequests = new LinkedList<>();
private LinkedList<ExternalRequest> externalRequests = new LinkedList<>();
public RequestQueue() {
}
public LinkedList<Integer> getInternalRequests() {
return internalRequests;
}
public void setInternalRequests(LinkedList<Integer> internalRequests) {
this.internalRequests = internalRequests;
}
public LinkedList<ExternalRequest> getExternalRequests() {
return externalRequests;
}
public void setExternalRequests(LinkedList<ExternalRequest> externalRequests) {
this.externalRequests = externalRequests;
}
public void addInternalRequest(int floor) {
internalRequests.add(floor);
}
public void addExternalRequest(ExternalRequest request) {
externalRequests.add(request);
}
}
解释:
在第一次迭代的基础上,我完善了类的写法,还考虑了很多特殊情况,完善和改进了我的代码,特别是增加了电梯执行外部需求的运行方向和电梯外部需求的方向讨论,类的写法跟所给的参照类图基本一致。
代码分析:
点击查看代码详细分析(中文)
文件 “elevator2.java” 的度量详情
参数 | 值
========= | =====
项目目录 | C:\Users\13458\Desktop\elevator2
项目名称 | elevator2
检查点名称 | 基线
文件名 | elevator2.java
行数 | 383
语句数 | 278
分支语句百分比 | 28.1%
方法调用语句数 | 181
带注释的行的百分比 | 0.0%
类和接口数 | 7
每个类的方法数 | 5.00
每个方法的平均语句数 | 6.37
最复杂方法的行号 | 177
最复杂方法的名称 | Controller.determineDirection ()
最大复杂度 | 30
最深代码块的行号 | 151
最大代码块深度 | 5
平均代码块深度 | 2.56
平均复杂度 | 3.86
5 个类中最复杂的方法: | 复杂度、语句数、最大深度、调用次数
Controller.Controller() | 1,2,2,0
Controller.determineDirection() | 30,45,5,45
Controller.getClosest() | 1,2,2,3
Controller.getElevator() | 1,1,2,0
Controller.getNextFloor() | 23,38,4,33
Controller.getQueue() | 1,1,2,0
Controller.move() | 5,10,4,10
Controller.openDoors() | 1,2,2,2
Controller.processRequests() | 13,25,5,16
Controller.removeRequests() | 17,23,4,31
Controller.repeatRequest() | 3,6,3,6
Controller.setElevator() | 1,1,2,0
Controller.setQueue() | 1,1,2,0
Controller.shouldStop() | 3,4,3,1
Elevator.Elevator() | 1,5,2,0
Elevator.getCurrentFloor() | 1,1,2,0
Elevator.getDirection() | 1,1,2,0
Elevator.getMaxFloor() | 1,1,2,0
Elevator.getMinFloor() | 1,1,2,0
Elevator.getState() | 1,1,2,0
Elevator.isValidFloor() | 3,3,3,0
Elevator.setCurrentFloor() | 1,1,2,0
Elevator.setDirection() | 1,1,2,0
Elevator.setState() | 1,1,2,0
ExternalRequest.ExternalRequest() | 1,2,2,0
ExternalRequest.getDirection() | 1,1,2,0
ExternalRequest.getFloor() | 1,1,2,0
Main.main() | 12,36,4,30
RequestQueue.addExternalRequest() | 1,1,2,1
RequestQueue.addInternalRequest() | 1,1,2,1
RequestQueue.getExternalRequests() | 1,1,2,0
RequestQueue.getInternalRequests() | 1,1,2,0
RequestQueue.RequestQueue() | 1,0,0,0
RequestQueue.setExternalRequests() | 1,1,2,0
RequestQueue.setInternalRequests() | 1,1,2,0
代码块深度 | 语句数
0 | 9
1 | 46
2 | 79
3 | 83
4 | 47
5 | 14
6 | 0
7 | 0
8 | 0
9 及以上 | 0
心得:
这次电梯调度题我对了一半,部分正确,可以说是相较第一次迭代有所进步,虽然最终还是没能完全正确,但我也对电梯调度算法有了更加深刻且正确的理解,但是在一些特殊情况上还没有完全考虑完全,再加上后面答案越改越错,思路又开始越来越乱,然后也没有时间再重新整理思路题目集就截止了。
第三次迭代
点击查看题目
对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类,具体设计可参考如下类图。
电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)
注意:本次作业类设计必须符合如上要求(包含但不限于设计电梯类、乘客类、队列类以及控制类),凡是不符合类设计要求此题不得分,另外,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.Scanner;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int minFloor = Integer.parseInt(scanner.nextLine());
int maxFloor = Integer.parseInt(scanner.nextLine());
Elevator elevator = new Elevator(minFloor, maxFloor);
RequestQueue queue = new RequestQueue();
Controller controller = new Controller(elevator, queue);
while (true) {
String input = scanner.nextLine();
if (input.equalsIgnoreCase("end")) {
break;
}
if (input.startsWith("<") && input.endsWith(">")) {
input = input.substring(1, input.length() - 1);
if (input.contains(",")) {
String[] parts = input.split(",");
int sourceFloor = Integer.parseInt(parts[0]);
int destinationFloor = Integer.parseInt(parts[1]);
queue.addExternalRequest(new Passenger(sourceFloor, destinationFloor,elevator));
} else {
int floor = Integer.parseInt(input);
queue.addInternalRequest(new Passenger(null, floor,elevator));
}
}
}
controller.processRequests();
}
}
enum Direction {
UP,DOWN,IDLE
}
enum State {
MOVING,STOPPED
}
class Elevator{
private int currentFloor;
private Direction direction;
private State state;
private int maxFloor;
private int minFloor;
public Elevator(int minFloor, int maxFloor) {
this.minFloor = minFloor;
this.maxFloor = maxFloor;
this.currentFloor = 0;
this.direction = Direction.IDLE;
this.state = State.STOPPED;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public int getMaxFloor() {
return maxFloor;
}
public int getMinFloor() {
return minFloor;
}
public boolean isValidFloor(int floor) {
if(floor <minFloor || floor > maxFloor){
return false;
}
return true;
}
}
class Passenger{
Integer sourceFloor;
Integer destinationFloor;
private Elevator elevator;
public Passenger() {
this.destinationFloor = null;
this.sourceFloor = null;
this.elevator = null;
}
public Passenger(Integer sourceFloor,Integer destinationFloor,Elevator elevator) {
this.destinationFloor = destinationFloor;
this.sourceFloor = sourceFloor;
this.elevator = elevator;
}
public Passenger(Integer sourceFloor,Integer destinationFloor ) {
this.destinationFloor = destinationFloor;
this.sourceFloor = sourceFloor;
}
public Integer getDestinationFloor() {
return destinationFloor;
}
public void setDestinationFloor(Integer destinationFloor) {
this.destinationFloor = destinationFloor;
}
public Integer getSourceFloor() {
return sourceFloor;
}
public void setSourceFloor(Integer sourceFloor) {
this.sourceFloor = sourceFloor;
}
public Direction getDirection(){
if(sourceFloor!=null){
if(sourceFloor>destinationFloor)
return Direction.DOWN;
return Direction.UP;
}
else{
if(elevator.getCurrentFloor()>destinationFloor)
return Direction.DOWN;
return Direction.UP;
}
}
}
class RequestQueue {
private LinkedList<Passenger> internalRequests = new LinkedList<>();
private LinkedList<Passenger> externalRequests = new LinkedList<>();
public RequestQueue(LinkedList<Passenger> internalRequests, LinkedList<Passenger> externalRequests) {
this.internalRequests = internalRequests;
this.externalRequests = externalRequests;
}
public RequestQueue() {
this.internalRequests = internalRequests;
this.externalRequests = externalRequests;
}
public LinkedList<Passenger> getInternalRequests() {
return internalRequests;
}
public void setInternalRequests(LinkedList<Passenger> internalRequests) {
this.internalRequests = internalRequests;
}
public LinkedList<Passenger> getExternalRequests() {
return externalRequests;
}
public void setExternalRequests(LinkedList<Passenger> externalRequests) {
this.externalRequests = externalRequests;
}
public void addInternalRequest(Passenger passenger){
internalRequests.add(passenger);
}
public void addExternalRequest(Passenger passenger){
externalRequests.add(passenger);
}
public int getExternalRequestsLength() {
return externalRequests.size();
}
}
class Controller{
private Elevator elevator;
private RequestQueue queue;
public Controller(Elevator elevator, RequestQueue queue) {
this.elevator = elevator;
this.queue = queue;
}
public Controller() {
this.elevator = elevator;
this.queue = queue;
}
public Elevator getElevator() {
return elevator;
}
public void setElevator(Elevator elevator) {
this.elevator = elevator;
}
public RequestQueue getQueue() {
return queue;
}
public void setQueue(RequestQueue queue) {
this.queue = queue;
}
public void processRequests(){
while (!queue.getExternalRequests().isEmpty() || !queue.getInternalRequests().isEmpty()) {
determineDirection();
int nextFloor = getNextFloor();
if (!queue.getExternalRequests().isEmpty() && !queue.getInternalRequests().isEmpty()) {
Passenger firstExternal = queue.getExternalRequests().getFirst();
Passenger firstInternal = queue.getInternalRequests().getFirst();
int length = queue.getExternalRequestsLength();
Direction externalDirection = firstExternal.getDirection();
if (elevator.getCurrentFloor() == nextFloor) {
openDoors();
} else {
while (!shouldStop(nextFloor)){
move(nextFloor);
}
openDoors();
}
if (queue.getExternalRequestsLength() != length)
elevator.setDirection(externalDirection);
} else if (!queue.getExternalRequests().isEmpty() && queue.getInternalRequests().isEmpty()) {
Passenger firstExternal = queue.getExternalRequests().getFirst();
Direction externalDirection = firstExternal.getDirection();
if (elevator.getCurrentFloor() == nextFloor) {
openDoors();
} else {
while (!shouldStop(nextFloor)){
move(nextFloor);
}
openDoors();
elevator.setDirection(externalDirection);
}
} else {
if (elevator.getCurrentFloor() == nextFloor) {
openDoors();
} else {
while (!shouldStop(nextFloor)){
move(nextFloor);
}
openDoors();
}
}
}
}
public void determineDirection(){
if(!queue.getExternalRequests().isEmpty()||!queue.getInternalRequests().isEmpty()){
int nextFloor=getNextFloor();
if(elevator.getCurrentFloor()>nextFloor)
elevator.setDirection(Direction.DOWN);
else if(elevator.getCurrentFloor()<nextFloor)
elevator.setDirection(Direction.UP);
else{
Passenger firstExternal = queue.getExternalRequests().getFirst();
elevator.setDirection(firstExternal.getDirection());
}
}
}
public void move(int floor){
while(elevator.getCurrentFloor()>floor)
{
elevator.setCurrentFloor(elevator.getCurrentFloor()-1);
System.out.printf("Current Floor: %d Direction: %s\n",elevator.getCurrentFloor(),elevator.getDirection());
}
while(elevator.getCurrentFloor()<floor)
{
elevator.setCurrentFloor(elevator.getCurrentFloor()+1);
System.out.printf("Current Floor: %d Direction: %s\n",elevator.getCurrentFloor(),elevator.getDirection());
}
}
public boolean shouldStop(int floor){
if(elevator.getCurrentFloor()==floor)
return true;
return false;
}
public Integer getNextFloor(){
if (!queue.getInternalRequests().isEmpty()&&!queue.getExternalRequests().isEmpty()) {
Passenger firstExternal = queue.getExternalRequests().getFirst();
Passenger firstInternal = queue.getInternalRequests().getFirst();
if(elevator.getDirection()==firstInternal.getDirection()&&elevator.getDirection()==firstExternal.getDirection()){
return getClosest(firstExternal.getSourceFloor(),firstInternal.getDestinationFloor());
}
else if(elevator.getDirection()==firstInternal.getDirection()&&elevator.getDirection()!=firstExternal.getDirection()){
return firstInternal.getDestinationFloor();
}
else if(elevator.getDirection()!=firstInternal.getDirection()&&elevator.getDirection()==firstExternal.getDirection()){
return firstExternal.getSourceFloor();
}
else{
if(elevator.getDirection() == Direction.UP){
if(elevator.getCurrentFloor()<firstInternal.getDestinationFloor()){
return firstInternal.getDestinationFloor();
}
return getClosest(firstExternal.getSourceFloor(),firstInternal.getSourceFloor());
}
else{
if(elevator.getCurrentFloor()>firstInternal.getDestinationFloor()){
return firstInternal.getDestinationFloor();
}
return getClosest(firstExternal.getSourceFloor(),firstInternal.getDestinationFloor());
}
}
}
else if(!queue.getInternalRequests().isEmpty()&&queue.getExternalRequests().isEmpty()){
Passenger firstInternal = queue.getInternalRequests().getFirst();
return firstInternal.getDestinationFloor();
}
else if(queue.getInternalRequests().isEmpty()&&!queue.getExternalRequests().isEmpty()){
Passenger firstExternal = queue.getExternalRequests().getFirst();
return firstExternal.getSourceFloor();
}
else
return null;
}
public Integer getClosest(Integer a,Integer b){
if (a == null)
return b;
if (b == null)
return a;
int currentFloor = elevator.getCurrentFloor();
return Math.abs(a - currentFloor) < Math.abs(b - currentFloor) ? a : b;
}
public void openDoors(){
System.out.printf("Open Door # Floor %d\n",elevator.getCurrentFloor());
removeRequests(elevator.getCurrentFloor());
System.out.printf("Close Door\n");
}
public void removeRequests(int floor){
if (!queue.getExternalRequests().isEmpty()) {
Passenger firstExternal = queue.getExternalRequests().getFirst();
if (firstExternal.getSourceFloor() == floor ) {
queue.addInternalRequest(new Passenger(firstExternal.getSourceFloor(), firstExternal.getDestinationFloor(), elevator));
queue.getExternalRequests().removeFirst();
}
}
if (!queue.getInternalRequests().isEmpty()) {
Passenger firstInternal = queue.getInternalRequests().getFirst();
if (firstInternal.getDestinationFloor() == floor) {
queue.getInternalRequests().removeFirst();
}
}
}
}
解释:
由于第二次迭代的逻辑写到后面很混乱,所以我重新理顺了第二次迭代的思路,简化了一些逻辑判断,同时也整理了特殊情况,完善了我的代码以及类的写法,类的写法跟所给的参照类图基本一致。
代码分析:
点击查看代码详细分析(中文)
文件 “elevator3.java” 的度量详情
参数 | 值
========= | =====
项目目录 | C:\Users\13458\Desktop\elevator3
项目名称 | elevator3
检查点名称 | 基线
文件名 | elevator3.java
行数 | 322
语句数 | 232
分支语句百分比 | 20.7%
方法调用语句数 | 139
带注释的行的百分比 | 0.0%
类和接口数 | 7
每个类的方法数 | 6.00
每个方法的平均语句数 | 4.02
最复杂方法的行号 | 255
最复杂方法的名称 | Controller.getNextFloor ()
最大复杂度 | 19
最深代码块的行号 | 195
最大代码块深度 | 6
平均代码块深度 | 2.43
平均复杂度 | 2.43
5 个类中最复杂的方法: | 复杂度、语句数、最大深度、调用次数
Controller.Controller() | 1,2,2,0
Controller.Controller() | 1,2,2,0
Controller.determineDirection() | 5,8,4,10
Controller.getClosest() | 3,6,2,3
Controller.getElevator() | 1,1,2,0
Controller.getNextFloor() | 19,26,6,45
Controller.getQueue() | 1,1,2,0
Controller.move() | 3,6,3,6
Controller.openDoors() | 1,3,2,3
Controller.processRequests() | 18,33,6,38
Controller.removeRequests() | 5,9,4,12
Controller.setElevator() | 1,1,2,0
Controller.setQueue() | 1,1,2,0
Controller.shouldStop() | 2,3,2,1
Elevator.Elevator() | 1,5,2,0
Elevator.getCurrentFloor() | 1,1,2,0
Elevator.getDirection() | 1,1,2,0
Elevator.getMaxFloor() | 1,1,2,0
Elevator.getMinFloor() | 1,1,2,0
Elevator.getState() | 1,1,2,0
Elevator.isValidFloor() | 3,3,3,0
Elevator.setCurrentFloor() | 1,1,2,0
Elevator.setDirection() | 1,1,2,0
Elevator.setState() | 1,1,2,0
Main.main() | 7,20,5,15
Passenger.getDestinationFloor() | 1,1,2,0
Passenger.getDirection() | 5,8,3,1
Passenger.getSourceFloor() | 1,1,2,0
Passenger.Passenger() | 1,2,2,0
Passenger.Passenger() | 1,3,2,0
Passenger.Passenger() | 1,3,2,0
Passenger.setDestinationFloor() | 1,1,2,0
Passenger.setSourceFloor() | 1,1,2,0
RequestQueue.addExternalRequest() | 1,1,2,1
RequestQueue.addInternalRequest() | 1,1,2,1
RequestQueue.getExternalRequests() | 1,1,2,0
RequestQueue.getExternalRequestsLength() | 1,1,2,1
RequestQueue.getInternalRequests() | 1,1,2,0
RequestQueue.RequestQueue() | 1,2,2,0
RequestQueue.RequestQueue() | 1,2,2,0
RequestQueue.setExternalRequests() | 1,1,2,0
RequestQueue.setInternalRequests() | 1,1,2,0
代码块深度 | 语句数
0 | 9
1 | 54
2 | 79
3 | 38
4 | 27
5 | 20
6 | 5
7 | 0
8 | 0
9 及以上 | 0
心得:
这次电梯调度题我终于拿下了完全正确!可以说是很大的进步,在题集六的混乱之后的第二天,我立马重振心情,把我的思路大致按照题集六重新理顺了一遍,最后自己再重新写了题集七,并没有复制粘贴,边写再边顺思路,很快就对了一半,紧接着再根据题目所给样例进行修改,完善逻辑,于是拿下了满分。
踩坑心得
第二次迭代
- [1]
输入样例
10
<3>
<3,UP>
<3,DOWN>
End
正确结果
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Open Door # Floor 3
Close Door
但是我开始在第三层却没有开两次门,就是没有考虑楼层相同但方向不同的情况。
- [2]
输入样例
1
20
<3,DOWN>
<2>
<5,UP>
<1>
<4,DOWN>
<3>
<2,DOWN>
<8>
<4>
正确结果
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Open Door # Floor 2
Close Door
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 2 Direction: DOWN
Current Floor: 1 Direction: DOWN
Open Door # Floor 1
Close Door
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
Current Floor: 8 Direction: UP
Open Door # Floor 8
Close Door
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
我的源码运行时一直显示非零返回,证明我的代码在某些分类讨论当中漏掉了一些情况,后面发现是在分类内外部需求是否为空的时候遗漏了内空外不空和内不空外空的情况。
- [3]
输入样例
1
20
<8,UP>
<5,UP>
<7,UP>
<2,UP>
<7,DOWN>
<5,DOWN>
<4,DOWN>
END
正确答案
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
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Open Door # Floor 8
Close Door
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
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
Current Floor: 4 Direction: DOWN
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
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
我的代码在从二楼去七楼的时候方向错误,检查发现决定电梯方向时考虑不周全,不仅要考虑电梯外部需求自带的方向,还要考虑电梯执行外部需求时的自身运行方向。
第三次迭代
- [1]
输入样例
1
20
<5,9>
<8>
<9,3>
<4>
<2>
End
正确结果
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
我刚开始在九楼开了两次门,经过idea设置断点调试后,发现时没有及时移除9楼的需求,导致二次开门,修改removeRequests方法。
改进建议
第一次迭代
点击查看代码详细分析
文件 “elevator1.java” 的度量详情
参数 值
========= =====
项目目录 C:\Users\13458\Desktop\elevator1
项目名称 elevator1
检查点名称 基线
文件名 elevator1.java
行数 197
语句数 148
分支语句百分比 25.0
方法调用语句数 85
带注释的行的百分比 0.0
类和接口数 2
每个类的方法数 6.50
每个方法的平均语句数 9.46
最复杂方法的行号 99
最复杂方法的名称 Elevator.findRequest ()
最大复杂度 22
最深代码块的行号 26
最大代码块深度 5
平均代码块深度 2.55
平均复杂度 4.46
2 个类中最复杂的方法: 复杂度、语句数、最大深度、调用次数
Elevator.addExternalRequest() 3,6,4,7
Elevator.addInternalRequest() 3,3,4,3
Elevator.checkFloor() 2,3,2,0
Elevator.closeDoor() 1,2,2,1
Elevator.Elevator() 1,7,2,0
Elevator.Elevator() 1,7,2,0
Elevator.findRequest() 22,34,4,28
Elevator.getExternalRequests() 1,1,2,0
Elevator.getInternalRequests() 1,1,2,0
Elevator.move() 10,19,5,12
Elevator.openDoor() 1,3,2,2
Elevator.processRequsts() 5,7,4,8
Main.main() 7,30,5,24
代码块深度 语句数
0 5
1 20
2 56
3 29
4 32
5 6
6 0
7 0
8 0
9 及以上 0
- [1] 缺乏注释
带注释的行的百分比为 0.0%,这会给后续的代码维护和理解带来极大困难,尤其是对于新接手项目的开发者,很难快速理解代码的功能和设计意图。
- [2] 部分方法复杂度高
存在复杂度较高的方法,如 Elevator.findRequest() 复杂度达到 22,Elevator.move() 复杂度为 10,Main.main() 复杂度为 7。这些高复杂度方法可能包含大量的条件判断和嵌套逻辑,使得代码难以理解和修改,并且增加了出错的风险。
- [3] 方法平均语句数较多
每个方法的平均语句数为 9.46,相对较多。这可能意味着部分方法承担了过多的功能,违反了单一职责原则,导致代码的可维护性和可测试性降低。
- [4] 分支语句占比有优化空间
分支语句百分比为 25.0%,虽然没有绝对的好坏标准,但较高的分支语句占比可能暗示代码中存在较多的条件判断,使得代码逻辑变得复杂,增加了维护的难度。
我需要增加注释,并且减少if-else的嵌套,同时做到方法职责单一性。
第二次迭代
点击查看代码详细分析
文件 “elevator2.java” 的度量详情
参数 | 值
========= | =====
项目目录 | C:\Users\13458\Desktop\elevator2
项目名称 | elevator2
检查点名称 | 基线
文件名 | elevator2.java
行数 | 383
语句数 | 278
分支语句百分比 | 28.1%
方法调用语句数 | 181
带注释的行的百分比 | 0.0%
类和接口数 | 7
每个类的方法数 | 5.00
每个方法的平均语句数 | 6.37
最复杂方法的行号 | 177
最复杂方法的名称 | Controller.determineDirection ()
最大复杂度 | 30
最深代码块的行号 | 151
最大代码块深度 | 5
平均代码块深度 | 2.56
平均复杂度 | 3.86
5 个类中最复杂的方法: | 复杂度、语句数、最大深度、调用次数
Controller.Controller() | 1,2,2,0
Controller.determineDirection() | 30,45,5,45
Controller.getClosest() | 1,2,2,3
Controller.getElevator() | 1,1,2,0
Controller.getNextFloor() | 23,38,4,33
Controller.getQueue() | 1,1,2,0
Controller.move() | 5,10,4,10
Controller.openDoors() | 1,2,2,2
Controller.processRequests() | 13,25,5,16
Controller.removeRequests() | 17,23,4,31
Controller.repeatRequest() | 3,6,3,6
Controller.setElevator() | 1,1,2,0
Controller.setQueue() | 1,1,2,0
Controller.shouldStop() | 3,4,3,1
Elevator.Elevator() | 1,5,2,0
Elevator.getCurrentFloor() | 1,1,2,0
Elevator.getDirection() | 1,1,2,0
Elevator.getMaxFloor() | 1,1,2,0
Elevator.getMinFloor() | 1,1,2,0
Elevator.getState() | 1,1,2,0
Elevator.isValidFloor() | 3,3,3,0
Elevator.setCurrentFloor() | 1,1,2,0
Elevator.setDirection() | 1,1,2,0
Elevator.setState() | 1,1,2,0
ExternalRequest.ExternalRequest() | 1,2,2,0
ExternalRequest.getDirection() | 1,1,2,0
ExternalRequest.getFloor() | 1,1,2,0
Main.main() | 12,36,4,30
RequestQueue.addExternalRequest() | 1,1,2,1
RequestQueue.addInternalRequest() | 1,1,2,1
RequestQueue.getExternalRequests() | 1,1,2,0
RequestQueue.getInternalRequests() | 1,1,2,0
RequestQueue.RequestQueue() | 1,0,0,0
RequestQueue.setExternalRequests() | 1,1,2,0
RequestQueue.setInternalRequests() | 1,1,2,0
代码块深度 | 语句数
0 | 9
1 | 46
2 | 79
3 | 83
4 | 47
5 | 14
6 | 0
7 | 0
8 | 0
9 及以上 | 0
- [1] 缺乏注释
带注释的行的百分比为 0.0%,这会给后续的代码维护和理解带来极大困难,尤其是对于新接手项目的开发者,很难快速理解代码的功能和设计意图。
- [2] 部分方法复杂度高
存在复杂度较高的方法,如 Controller.determineDirection () 复杂度达到 30,Controller.getNextFloor () 复杂度为 23,这些高复杂度方法可能包含大量的条件判断和嵌套逻辑,使得代码难以理解和修改,并且增加了出错的风险。
- [3] 可能存在代码重复
从方法调用语句数较多(181 条)来看,可能存在一些功能在多个地方重复实现的情况,这不仅增加了代码量,还可能导致维护成本上升。
我需要针对以上问题进行改进,增加注释,调整方法的复杂度,努力做到职责单一性把代码重复的部分单独写一个方法,就不用重复写。
第三次迭代
点击查看代码详细分析
文件 “elevator3.java” 的度量详情
参数 | 值
========= | =====
项目目录 | C:\Users\13458\Desktop\elevator3
项目名称 | elevator3
检查点名称 | 基线
文件名 | elevator3.java
行数 | 322
语句数 | 232
分支语句百分比 | 20.7%
方法调用语句数 | 139
带注释的行的百分比 | 0.0%
类和接口数 | 7
每个类的方法数 | 6.00
每个方法的平均语句数 | 4.02
最复杂方法的行号 | 255
最复杂方法的名称 | Controller.getNextFloor ()
最大复杂度 | 19
最深代码块的行号 | 195
最大代码块深度 | 6
平均代码块深度 | 2.43
平均复杂度 | 2.43
5 个类中最复杂的方法: | 复杂度、语句数、最大深度、调用次数
Controller.Controller() | 1,2,2,0
Controller.Controller() | 1,2,2,0
Controller.determineDirection() | 5,8,4,10
Controller.getClosest() | 3,6,2,3
Controller.getElevator() | 1,1,2,0
Controller.getNextFloor() | 19,26,6,45
Controller.getQueue() | 1,1,2,0
Controller.move() | 3,6,3,6
Controller.openDoors() | 1,3,2,3
Controller.processRequests() | 18,33,6,38
Controller.removeRequests() | 5,9,4,12
Controller.setElevator() | 1,1,2,0
Controller.setQueue() | 1,1,2,0
Controller.shouldStop() | 2,3,2,1
Elevator.Elevator() | 1,5,2,0
Elevator.getCurrentFloor() | 1,1,2,0
Elevator.getDirection() | 1,1,2,0
Elevator.getMaxFloor() | 1,1,2,0
Elevator.getMinFloor() | 1,1,2,0
Elevator.getState() | 1,1,2,0
Elevator.isValidFloor() | 3,3,3,0
Elevator.setCurrentFloor() | 1,1,2,0
Elevator.setDirection() | 1,1,2,0
Elevator.setState() | 1,1,2,0
Main.main() | 7,20,5,15
Passenger.getDestinationFloor() | 1,1,2,0
Passenger.getDirection() | 5,8,3,1
Passenger.getSourceFloor() | 1,1,2,0
Passenger.Passenger() | 1,2,2,0
Passenger.Passenger() | 1,3,2,0
Passenger.Passenger() | 1,3,2,0
Passenger.setDestinationFloor() | 1,1,2,0
Passenger.setSourceFloor() | 1,1,2,0
RequestQueue.addExternalRequest() | 1,1,2,1
RequestQueue.addInternalRequest() | 1,1,2,1
RequestQueue.getExternalRequests() | 1,1,2,0
RequestQueue.getExternalRequestsLength() | 1,1,2,1
RequestQueue.getInternalRequests() | 1,1,2,0
RequestQueue.RequestQueue() | 1,2,2,0
RequestQueue.RequestQueue() | 1,2,2,0
RequestQueue.setExternalRequests() | 1,1,2,0
RequestQueue.setInternalRequests() | 1,1,2,0
代码块深度 | 语句数
0 | 9
1 | 54
2 | 79
3 | 38
4 | 27
5 | 20
6 | 5
7 | 0
8 | 0
9 及以上 | 0
- [1] 缺乏注释
带注释的行的百分比为 0.0%,这会给后续的代码维护和理解带来极大困难,尤其是对于新接手项目的开发者,很难快速理解代码的功能和设计意图。
- [2] 存在复杂方法
存在一些复杂度较高的方法,如 Controller.getNextFloor() 复杂度为 19,Controller.processRequests() 复杂度为 18。这些方法的复杂度较高可能意味着其包含了较多的条件判断、循环等复杂逻辑,代码可读性和可维护性较差,后续修改时容易引入 bug。
- [3] 方法调用较多
方法调用语句数为 139,虽然一定程度上体现了模块化设计,但过多的方法调用可能会增加代码的理解难度,同时也可能存在方法之间的耦合度过高的问题,不利于代码的独立维护和复用。
- [4] 类的职责可能不够单一
虽然整体结构有一定模块化,但个别类中的方法数量较多,可能存在一个类承担了过多职责的情况,违反了单一职责原则,这可能导致类的功能不够清晰,增加维护成本。
我要多写注释,同时尽量优化复杂的方法,简化思路和写法,做到职责单一性,减少方法调用,降低耦合度。
总结
在完成这三次题目集的过程中,我收获颇丰,接触到了许多以往未曾知晓的语法细节与实用方法。像是枚举类型的巧妙运用,让我能够更清晰、规范地定义有限的取值集合;学会了如何高效地一次性读入一串字符,大大提升了数据输入处理的能力;还有 Integer 封装类的特性,加深了我对基本数据类型和引用数据类型之间转换的理解。与此同时,我对 ArrayList 和 LinkedList 的主要用法有了更为深入的认识。从它们底层的数据结构差异,到在不同场景下的性能表现,再到各种增删改查方法的灵活运用,都有了切实的实践体会。并且,通过解决这些题目,我大量练习了多个类的编写,深入理解了类与类之间相互调用的逻辑关系,极大地提升了自己在类与对象设计方面的能力。不得不说,这一系列题目是我目前所遇到的最具挑战性的任务。每一次遇到难题,都是对我坚持不懈毅力的考验,也是对心智的磨练。在这个过程中,我深刻领悟到了不到最后一刻决不放弃的精神。正是这种精神支撑着我,不断克服困难,最终完成了这些题目。在复盘时,我也清晰地认识到了自己的不足之处。比如,在实际应用 ArrayList 和 LinkedList 的相关方法时,还不够熟练自如,常常需要借助 AI 工具来查找具体的使用方式。这表明我在这方面的知识掌握还不够扎实,需要更加深入地研究和记忆这些数据结构的特性与方法。另外,对于这次学习过程中接触到的新知识点和代码逻辑,我还没有很好地记住和内化。我意识到,只有通过更多的练习,不断地实践和运用,才能真正将这些知识转化为自己的能力。