第一次博客作业,有关电梯的程序代码分析

一,前言

本次PTA中第五到第七次的题目集中,对电梯程序进行了迭代编写,虽说我并没有完成全部的测试点,但从中我也学习到了许多知识,如ArrayList的运用,enum枚举等方法的运用,让我对java程序的迭代有了更深的了解,懂得深入理解题目的意义,与现实相接,切实的解决与生活相关的问题,在编写代码的过程中,懂得在Java程序中单一职责的重要性,尤其是当程序的代码行数特别多的时候,要保持代码的时效性,迭代性,可读性。这样才是一个合格的程序,所以首先拿到题目,我们应该理解题意,构造类图,有思路的去写,而不是想到什么写什么。下面对我的代码进行分析。

二,代码的设计与分析

1,第一次单部电梯调度程序

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

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

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

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

1.1 源码:
点击查看代码
import java.util.*;

enum Direction {
    UP, DOWN
}

class Elevator {
    private int minFloor;
    private int maxFloor;
    private int currentFloor;
    private Direction direction;
    private LinkedList<Integer> internalRequests = new LinkedList<>();
    private Map<Integer, Integer> internalRequestCounts = new HashMap<>();
    private TreeSet<Integer> externalFloors = new TreeSet<>();
    private Map<Integer, EnumSet<Direction>> externalRequests = new HashMap<>();

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.direction = Direction.UP;
    }

    public void addInternalRequest(int floor) {
        if (floor >= minFloor && floor <= maxFloor) {
            internalRequests.add(floor);
            internalRequestCounts.put(floor, internalRequestCounts.getOrDefault(floor, 0) + 1);
        }
    }

    public void addExternalRequest(int floor, Direction dir) {
        if (floor >= minFloor && floor <= maxFloor) {
            externalFloors.add(floor);
            externalRequests.computeIfAbsent(floor, k -> EnumSet.noneOf(Direction.class)).add(dir);
        }
    }

    public void processRequests() {
        System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);

        while (!internalRequests.isEmpty() || !externalFloors.isEmpty()) {
            handleDirection();
        }
    }

    private void handleDirection() {
        Integer target = getMainTarget();
        if (target == null) return;

        direction = target > currentFloor ? Direction.UP : Direction.DOWN;

        while (currentFloor != target) {
            currentFloor += direction == Direction.UP ? 1 : -1;
            System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
            handlePossibleStop();
        }
        handlePossibleStop();
    }

    private Integer getMainTarget() {
        if (!internalRequests.isEmpty()) {
            return internalRequests.getFirst();
        }

        if (direction == Direction.UP) {
            Integer upTarget = externalFloors.ceiling(currentFloor);
            if (upTarget != null) return upTarget;
        } else {
            Integer downTarget = externalFloors.floor(currentFloor);
            if (downTarget != null) return downTarget;
        }

        if (!externalFloors.isEmpty()) {
            direction = externalFloors.first() > currentFloor ? Direction.UP : Direction.DOWN;
            return direction == Direction.UP ? externalFloors.first() : externalFloors.last();
        }
        return null;
    }

    private void handlePossibleStop() {
        if (shouldStop(currentFloor)) {
            System.out.println("Open Door # Floor " + currentFloor);
            processInternalStop();
            processExternalStop();
            System.out.println("Close Door");
        }
    }

    private boolean shouldStop(int floor) {
        return (internalRequests.contains(floor) ||
                (externalRequests.containsKey(floor) &&
                        externalRequests.get(floor).contains(direction)));
    }

    private void processInternalStop() {
        if (internalRequests.peek() == currentFloor) {
            internalRequests.poll();
            internalRequestCounts.merge(currentFloor, -1, Integer::sum);
            if (internalRequestCounts.get(currentFloor) <= 0) {
                internalRequestCounts.remove(currentFloor);
            }
        }
    }

    private void processExternalStop() {
        EnumSet<Direction> dirs = externalRequests.get(currentFloor);
        if (dirs != null && dirs.contains(direction)) {
            dirs.remove(direction);
            if (dirs.isEmpty()) {
                externalRequests.remove(currentFloor);
                externalFloors.remove(currentFloor);
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int min = input.nextInt(), max = input.nextInt();
        input.nextLine();

        Elevator elevator = new Elevator(min, max);

        while (true) {
            String line = input.nextLine().trim();
            if (line.equals("end")) break;

            if (line.contains(",")) {
                String[] parts = line.replaceAll("[<>]", "").split(",");
                int floor = Integer.parseInt(parts[0]);
                Direction dir = Direction.valueOf(parts[1].toUpperCase());
                elevator.addExternalRequest(floor, dir);
            } else {
                int floor = Integer.parseInt(line.replaceAll("[<>]", ""));
                elevator.addInternalRequest(floor);
            }
        }

        elevator.processRequests();
    }
}
1.2 分析

(1) 使用PowerDesigner所绘制的类图

(2) 从PowerDesigner所绘制的类图来看,我对第一次的电梯程序分为电梯类,enum枚举类,main类。
a. 电梯类中我采用了

addInternalRequest(int floor);来处理内部请求

public void addInternalRequest(int floor) {
        if (floor >= minFloor && floor <= maxFloor) {
            internalRequests.add(floor);
            internalRequestCounts.put(floor, internalRequestCounts.getOrDefault(floor, 0) + 1);
        }
    }

addExternalRequest(int floor, Direction dir);来处理外部请求

public void addExternalRequest(int floor, Direction dir) {
        if (floor >= minFloor && floor <= maxFloor) {
            externalFloors.add(floor);
            externalRequests.computeIfAbsent(floor, k -> EnumSet.noneOf(Direction.class)).add(dir);
        }
    }

b. enmu枚举中
UP为方向向上,DOWN为方向向下。

enum Direction {
    UP, DOWN
}

c. 主类中
采用正则表达式来规范请求的输入
正则表达式在import java.util.;中,所以在源码第一行就声明了import java.util.;
正则表达式的输入

while (true) {
            String line = input.nextLine().trim();
            if (line.equals("end")) break;
            
            if (line.contains(",")) {
                String[] parts = line.replaceAll("[<>]", "").split(",");
                int floor = Integer.parseInt(parts[0]);
                Direction dir = Direction.valueOf(parts[1].toUpperCase());
                elevator.addExternalRequest(floor, dir);
            } else {
                int floor = Integer.parseInt(line.replaceAll("[<>]", ""));
                elevator.addInternalRequest(floor);
            }
        }

(3)使用SourceMontor生成报表内容
image

(4)根据SourceMontor所绘制的报表内容
a. 142行,属于中等规模,方法调用59,说明代码模块化程度尚可,通过方法调用实现功能拆分。类和接口数量: 3。3 个类或接口,结构相对清晰。(优点)

b. 分支语句比例 21.7%有一定比例的分支逻辑,代码中存在较多条件判断 if - else和switch 程序执行路径相对多样。但这样也会出现一定的复杂性,会造成运行时间过长。

c. 含注释行的百分比为0,这是一个不好的现象,注释有助于增强代码的可读性,更容易理解,更好的进行迭代

d. 每个方法平均语句数6.27,方法内语句数适中,说明方法功能粒度把控尚可,不过最复杂方法(Line Number of Most Complex Method: 60 ,Name of Most Complex Method: Elevator.getMainTarget () )有 60 行,按正常来说,一个方法的行数

e. 最大复杂度:8.存在复杂度较高的方法,可能是逻辑嵌套、条件判断较多导致,理解和测试难度较大。

f. 最大代码块深度 4 和 平均代码块深度2.23,说明代码存在一定程度的嵌套,最大 4 层嵌套可能导致逻辑不够清晰,调试困难。

g.平均复杂度(Average Complexity: 3.55):整体平均复杂度不算极高。

1.3 运行

按照输入样例输入
image

输出
image

1.4 小结

本次的单部电梯的调试是我们java课程的第一次的大作业,整体难度不大,但我做起来很困难,主要是因为自己在做题过程中太过懈怠,没有用一个良好的心态去应对,有许多的新东西并没有学,还是用着c语言那中面向过程的思维和语法,通过这次作业,深知自己应该认真对待每一次的题目,将自己的思维方式从面向过程转向面向对象的必要性,这样我们才能进步。

2,第二次单部电梯调度程序

对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类。电梯运行规则与前阶段单类设计相同,但要处理如下情况:
乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>

2.1 源码
点击查看代码
import java.util.*;

enum Direction {
    UP, DOWN, IDLE
}

enum State {
    MOVING, STOPPED
}

class ExternalRequest {
    private final Integer floor;
    private final Direction direction;

    public ExternalRequest(Integer floor, Direction direction) {
        this.floor = floor;
        this.direction = direction;
    }

    public Integer getFloor() {
        return floor;
    }

    public Direction getDirection() {
        return direction;
    }

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ExternalRequest that = (ExternalRequest) o;
        return Objects.equals(floor, that.floor) && direction == that.direction;
    }

    public int hashCode() {
        return Objects.hash(floor, direction);
    }
}

class RequestQueue {
    private final LinkedList<Integer> internalRequests = new LinkedList<>();
    private final LinkedList<ExternalRequest> externalRequests = new LinkedList<>();

    public LinkedList<Integer> getInternalRequests() {
        return internalRequests;
    }

    public LinkedList<ExternalRequest> getExternalRequests() {
        return externalRequests;
    }

    public void addInternalRequest(int floor) {
        if (!internalRequests.contains(floor)) {
            internalRequests.add(floor);
        }
    }

    public void addExternalRequest(int floor, Direction direction) {
        ExternalRequest req = new ExternalRequest(floor, direction);
        if (!externalRequests.contains(req)) {
            externalRequests.add(req);
        }
    }
//去重逻辑
    public void removeInternalRequest(int floor) {
        internalRequests.remove(Integer.valueOf(floor));
    }

    public void removeExternalRequest(int floor) {
        externalRequests.removeIf(req -> req.getFloor() == floor);
    }
}

class Elevator {
    private final int minFloor;
    private final int maxFloor;
    private int currentFloor;
    private Direction direction;
    private State state;

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.direction = Direction.UP;
        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 getMinFloor() {
        return minFloor;
    }

    public int getMaxFloor() {
        return maxFloor;
    }

    public boolean isValidFloor(int floor) {
        return floor >= minFloor && floor <= maxFloor;
    }
}

class Controller {
    private final Elevator elevator;
    private final RequestQueue queue;

    public Controller(Elevator elevator, RequestQueue queue) {
        this.elevator = elevator;
        this.queue = queue;
    }
//获取所有的请求的层数
    private List<Integer> getAllSortedFloors() {
        Set<Integer> allFloors = new HashSet<>();
        allFloors.addAll(queue.getInternalRequests());
        for (ExternalRequest req : queue.getExternalRequests()) {
            allFloors.add(req.getFloor());
        }
        List<Integer> sortedFloors = new ArrayList<>(allFloors);
        Collections.sort(sortedFloors);
        return sortedFloors;
    }
//移动并消除
    private void moveAndRemoveRequest(int floor, Direction dir) {
        move(elevator.getCurrentFloor(), floor, dir);
        queue.removeInternalRequest(floor);
        queue.removeExternalRequest(floor);
    }

    public void processRequests() {
        List<Integer> sortedFloors = getAllSortedFloors();

        elevator.setDirection(Direction.UP);
        for (int floor : sortedFloors) {
            if (floor > elevator.getCurrentFloor()) {
                moveAndRemoveRequest(floor, Direction.UP);
            }
        }

        elevator.setDirection(Direction.DOWN);
        Collections.reverse(sortedFloors);
        for (int floor : sortedFloors) {
            if (floor < elevator.getCurrentFloor()) {
                moveAndRemoveRequest(floor, Direction.DOWN);
            }
        }
    }
//电梯的移动的,判断是否需要开门
    private void move(int start, int target, Direction dir) {
        int step = dir == Direction.UP ? 1 : -1;
        for (int i = start; i != target; i+=step) {
            elevator.setCurrentFloor(i);
            System.out.println("Current Floor: " + i + " Direction: " + dir);
        }
        elevator.setCurrentFloor(target);
        if (start != target) {
            System.out.println("Current Floor: " + target + " Direction: " + dir);
        }
        openCloseDoors(target);
    }

    private void openCloseDoors(int floor) {
        System.out.println("Open Door # Floor " + floor);
        System.out.println("Close Door");
    }
}

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 line = scanner.nextLine().trim();
            if ("end".equalsIgnoreCase(line)) break;

            if (!line.startsWith("<") || !line.endsWith(">")) continue;

            line = line.substring(1, line.length() - 1);
            if (line.contains(",")) {
                String[] parts = line.split(",");
                int floor = Integer.parseInt(parts[0]);
                Direction dir = Direction.valueOf(parts[1]);
                if (elevator.isValidFloor(floor)) {
                    queue.addExternalRequest(floor, dir);
                }
            } else {
                int floor = Integer.parseInt(line);
                if (elevator.isValidFloor(floor)) {
                    queue.addInternalRequest(floor);
                }
            }
        }
        controller.processRequests();
    }
}
2.2 分析

(1)使用PowerDesigner所绘制的类图
image

(2)从PowerDesigner所绘制的类图来看,我对第二次电梯程序分为ExternalRequest 类,RequestQueue 类,Elevator 类,Controller 类,Main 类,首先第二次的代码实在第一次的代码的基础上进行迭代,细读题目要求,核心的要义为两个,其一是去除那些非法的输入,例如不在最低楼层和最高楼层内的输入为无效输入,直接过滤。再就是遇到像<5><5><5>或者<3><3><3>这样的输入,去重操作,将其过滤为<5>或者<3>
a. 在第一次的代码的基础上添加去重操作,
例如在Controller类中的moveAndRemoveRequest方法

private void moveAndRemoveRequest(int floor, Direction dir) {
        move(elevator.getCurrentFloor(), floor, dir);
        queue.removeInternalRequest(floor);
        queue.removeExternalRequest(floor);
    }

(3)使用SourceMontor生成报表内容
image

a. 行数223,方法调用次数132,说明代码模块化很明显,履行者单一职责,类别有7个,面向对象,分支率为百分之13.6,相较于第一次程序代码选择结构优化提高(优点)

b. 每个类平均3.57个方法,在一个方法中最长的代码行数为188,这严重的超过了一个方法在可控范围内的代码行数,这使得我的代码极难去操作迭代。最大的复杂度为9,部分复杂度太高使得代码很难操作。平均复杂度为1.65相较于第一的程序,本次的效率的得到了提高,但还是答案错误
image
我认为是我的代码局部的逻辑太过复杂,阅读调试过程中极为不便,导致我并没有找出其中存在的逻辑错误在哪里

2.3 运行

按照输入样例输入
image

ide运行结果
image
存在许多重复内容(去重逻辑的问题)
pta运行结果
image

2.4 小结

本次的电梯程序我并没有成功的通过测试点,本次代码的核心就是添加一个去重操作,但我的代码可读性可调试性太差,自己对代码的理解,构造方法的理解太差,我并没有成功的实现这个去重逻辑,这是我本次电梯代码的主要问题。

3,第三次单部电梯调度程序

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

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

3.1 源码
点击查看代码
import java.util.*;

enum Direction {
    UP, DOWN, IDLE
}

enum State {
    MOVING, STOPPED
}

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;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Passenger passenger = (Passenger) o;
        return sourceFloor == passenger.sourceFloor && destinationFloor == passenger.destinationFloor;
    }

    @Override
    public int hashCode() {
        return Objects.hash(sourceFloor, destinationFloor);
    }
}

class RequestQueue {
    private final LinkedList<Integer> internalRequests = new LinkedList<>();
    private final LinkedList<Passenger> externalRequests = new LinkedList<>();

    public LinkedList<Integer> getInternalRequests() {
        return internalRequests;
    }

    public LinkedList<Passenger> getExternalRequests() {
        return externalRequests;
    }

    public void addInternalRequest(int floor) {
        if (!internalRequests.contains(floor)) {
            internalRequests.add(floor);
        }
    }

    public void addExternalRequest(Passenger passenger) {
        if (!externalRequests.contains(passenger)) {
            externalRequests.add(passenger);
        }
    }

    public void removeInternalRequest(int floor) {
        internalRequests.remove(Integer.valueOf(floor));
    }

    public void removeExternalRequest(Passenger passenger) {
        externalRequests.remove(passenger);
    }
}

class Elevator {
    private final int minFloor;
    private final int maxFloor;
    private int currentFloor;
    private Direction direction;
    private State state;

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.direction = Direction.UP;
        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 getMinFloor() {
        return minFloor;
    }

    public int getMaxFloor() {
        return maxFloor;
    }

    public boolean isValidFloor(int floor) {
        return floor >= minFloor && floor <= maxFloor;
    }
}

class Controller {
    private final Elevator elevator;
    private final RequestQueue queue;

    public Controller(Elevator elevator, RequestQueue queue) {
        this.elevator = elevator;
        this.queue = queue;
    }

    private List<Integer> getAllSortedFloors() {
        Set<Integer> allFloors = new HashSet<>();
        allFloors.addAll(queue.getInternalRequests());
        for (Passenger passenger : queue.getExternalRequests()) {
            allFloors.add(passenger.getSourceFloor());
            allFloors.add(passenger.getDestinationFloor());
        }
        List<Integer> sortedFloors = new ArrayList<>(allFloors);
        Collections.sort(sortedFloors);
        return sortedFloors;
    }

    private void moveAndRemoveRequest(int floor, Direction dir) {
        move(elevator.getCurrentFloor(), floor, dir);
        queue.removeInternalRequest(floor);
        Iterator<Passenger> iterator = queue.getExternalRequests().iterator();
        while (iterator.hasNext()) {
            Passenger passenger = iterator.next();
            if (passenger.getSourceFloor() == floor) {
                queue.addInternalRequest(passenger.getDestinationFloor());
                iterator.remove();
            }
        }
    }

    public void processRequests() {
        List<Integer> sortedFloors = getAllSortedFloors();

        elevator.setDirection(Direction.UP);
        for (int floor : sortedFloors) {
            if (floor > elevator.getCurrentFloor()) {
                moveAndRemoveRequest(floor, Direction.UP);
            }
        }

        elevator.setDirection(Direction.DOWN);
        Collections.reverse(sortedFloors);
        for (int floor : sortedFloors) {
            if (floor < elevator.getCurrentFloor()) {
                moveAndRemoveRequest(floor, Direction.DOWN);
            }
        }
    }

    private void move(int start, int target, Direction dir) {
        int step = dir == Direction.UP ? 1 : -1;
        for (int i = start; i != target; i += step) {
            elevator.setCurrentFloor(i);
            System.out.println("Current Floor: " + i + " Direction: " + dir);
        }
        elevator.setCurrentFloor(target);
        if (start != target) {
            System.out.println("Current Floor: " + target + " Direction: " + dir);
        }
        openCloseDoors(target);
    }

    private void openCloseDoors(int floor) {
        System.out.println("Open Door # Floor " + floor);
        System.out.println("Close Door");
    }
}

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 line = scanner.nextLine().trim();
            if ("end".equalsIgnoreCase(line)) break;

            if (!line.startsWith("<") || !line.endsWith(">")) continue;

            line = line.substring(1, line.length() - 1);
            if (line.contains(",")) {
                String[] parts = line.split(",");
                int sourceFloor = Integer.parseInt(parts[0]);
                int destinationFloor = Integer.parseInt(parts[1]);
                if (elevator.isValidFloor(sourceFloor) && elevator.isValidFloor(destinationFloor)) {
                    Passenger passenger = new Passenger(sourceFloor, destinationFloor);
                    queue.addExternalRequest(passenger);
                }
            } else {
                int floor = Integer.parseInt(line);
                if (elevator.isValidFloor(floor)) {
                    queue.addInternalRequest(floor);
                }
            }
        }
        controller.processRequests();
    }
}
3.2 分析

(1)使用PowerDesigner所绘制出来的类图
image

(2)根据PowerDesigner所绘制的图形,我分为了Passenger类,RequestQueue类,Elevator类,Controller类,Main类,Direction枚举类,State枚举类
a. RequestQueue 类中的请求管理方法

public void addInternalRequest(int floor) {
    if (!internalRequests.contains(floor)) {
        internalRequests.add(floor);
    }
}

public void addExternalRequest(Passenger passenger) {
    if (!externalRequests.contains(passenger)) {
        externalRequests.add(passenger);
    }
}

public void removeInternalRequest(int floor) {
    internalRequests.remove(Integer.valueOf(floor));
}

public void removeExternalRequest(Passenger passenger) {
    externalRequests.remove(passenger);
}

b. Controller 类中的 move 方法

private void move(int start, int target, Direction dir) {
    int step = dir == Direction.UP ? 1 : -1;
    for (int i = start; i != target; i += step) {
        elevator.setCurrentFloor(i);
        System.out.println("Current Floor: " + i + " Direction: " + dir);
    }
    elevator.setCurrentFloor(target);
    if (start != target) {
        System.out.println("Current Floor: " + target + " Direction: " + dir);
    }
    openCloseDoors(target);
}

(3) 使用SourceMontor生成报表内容

image

(4)根据SourceMontor所生成的报表

a. 有136条执行指令,说明代码模块化比较好,履行单一职责,最复杂的方法行数为31行,各个方法的效率得到极大的提高。最大复杂度为5,相比之下,效率得到一定提高。
b. 注释率为7.9%,选择结构和循环结构太多,会增加时间的复杂度。

3.3 运行

按照输入样例输入
image
ide运行结果
image
Pta运行结果
image

3.4 小结

本次的电梯程序我并没有完成,主要是自己并没有认真的用心的去对待,本次的程序是将前两次的程序进行迭代,将此程序迭代为健全的电梯程序。此次程序的核心是将乘客的请求的换成自己想要去往的楼层,本次程序我并没有成功的通过测试点。我想的是将乘客请求想要去的楼层,先判断方向,再去判断距离的远近,再判断是否需要调转方向。但是出现了差错

三,踩坑心得

在第一次程序中,我一直遇到运行超时的错误
image
所以我就一直在想,应该如何让解决,是选择结构太多还是循环次数太多,后来经过我调试,
我发现是我的循环卡住了,所以我将循环的次数限制为10次,此时不报错运行超时,而是答案错误了
image
所以我又想是不是次数太少,并没有涵盖所有的情况,所以我又将循环的次数限制为100次,结果还是答案错误。
但我细想,如果循环的次数不根据乘客的请求来的话,那如果没有乘客请求的时候,电梯也会自己运行,这样放在现实生活中着实有些吓人(😄)。
所以我们一定要根据现实来进行构思,不能单纯的为了通过测试点。要解决实际问题。

四,改进建议

(1)在第一次和第二次的程序中其中最复杂的方法的代码行数一个为60行,一个为188行,每一个方法的最大行数不应该超过50行,因为一旦超过50行,这个方法的耦合度就太高了,可以将它模块化提高效率.

(2)可以添加适当的注释

(3)对于代码的选择结构,可以将选择结构中的大部分内容改为调用方法,这样既简单,可读性又高。

五,总结

(1)这次的电梯迭代作业,让我掌握了java的基本语法,以及基本形成面向对象设计的思维,同时我也注意到自己浮躁的心态,我需要端正自己的心态继续学习,不能因为一次的挫折一逸再逸,这样吃亏的还是自己
(2)希望老师在每次的大作业截至后,提供一个思路模板,这样我感觉可以更好地激发我们的思维,有方向的去探寻。

posted @ 2025-04-19 19:50  用热吻逃避我  阅读(79)  评论(0)    收藏  举报