Lib3985

导航

第一次博客作业

题目集5-7总结报告

一、前言

题目集5-7是从基础语法到面向对象设计的完整学习路径,题目类型涵盖了:

  • 数组操作(判断数组相等性、检测连续元素等)
  • 字符串处理(正则表达式构建)
  • 数学计算(浮点数精度控制)
  • 类设计(封装原则应用)

特别说明:题目集5-7 是从基础语法到面向对象设计的完整学习路径,题目类型涵盖了数组操作、字符串处理、数学计算、类设计等多个核心领域。在基础数据结构方面,数组相关题目,包括判断数组相等性、检测连续元素、合并有序数组等经典题型,这些题目普遍要求正确处理边界条件和避免数组越界。字符串处理类题目以验证码校验为代表,重点在于正则表达式的精确构建,特别是量词使用和字符集定义,而日期类题目则更注重状态完整性和业务规则验证,需要处理闰年判断、月份天数变化等复杂逻辑。面向对象设计题目如银行账户类和圆形类,要求严格按照封装原则设计属性和方法,数学计算类题目包括三角形面积和投资回报计算,核心在于公式的正确实现和浮点数精度控制,尤其是百分比转换和复利计算需要特别注意运算顺序。输入输出处理贯穿所有题目,格式控制要求严格,包括保留小数位数、空格分隔等细节处理,任何多余的空格或格式错误都会导致测试失败。题目难度呈现明显梯度,从简单的三数排序到复杂的日期类系统设计,考察重点也从基础语法逐渐转向系统思维能力。所有题目都强调异常输入处理,要求对空值、负值、越界值等特殊情况做出防御性编程。下面是对最主要的电梯迭代题目分析。

二:设计与分析:

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

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

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

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

点击查看代码
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Pattern;

class Elevator {
    // 方向常量
    private static final int UP = 1;
    private static final int DOWN = -1;
    private static final int IDLE = 0;
    
    // 状态常量
    private static final String STOPPED = "STOPPED";
    private static final String MOVING = "MOVING";
    private static final String OPENING = "OPENING";
    private static final String CLOSING = "CLOSING";
    
    // 电梯属性
    private final int minFloor;
    private final int maxFloor;
    private int currentFloor;
    private int direction;
    private String status;
    
    // 请求队列(使用ArrayList)
    private final ArrayList<Integer> innerQueue = new ArrayList<>();
    private final ArrayList<Integer> outerUpQueue = new ArrayList<>();
    private final ArrayList<Integer> outerDownQueue = new ArrayList<>();
    
    // 正则表达式模式
    private static final Pattern INNER_PATTERN = Pattern.compile("^<\\s*\\d+\\s*>$");
    private static final Pattern OUTER_PATTERN = Pattern.compile("^<\\s*\\d+\\s*,\\s*(UP|DOWN)\\s*>$");

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor; // 默认停在1层
        this.direction = IDLE;
        this.status = STOPPED;
    }

    public void addInternalRequest(int floor) {
        if (floor >= minFloor && floor <= maxFloor) {
            innerQueue.add(floor);
        }
    }

    public void addExternalRequest(int floor, String dir) {
        if (floor >= minFloor && floor <= maxFloor) {
            if (dir.equals("UP")) {
                outerUpQueue.add(floor);
            } else if (dir.equals("DOWN")) {
                outerDownQueue.add(floor);
            }
        }
    }

    public ArrayList<Integer> getInternalRequests() {
        return innerQueue;
    }

    public ArrayList<Integer> getExternalRequests() {
        ArrayList<Integer> all = new ArrayList<>();
        all.addAll(outerUpQueue);
        all.addAll(outerDownQueue);
        return all;
    }

    public void processRequests() {
        // 初始方向设置
        if (direction == IDLE) {
            setInitialDirection();
        }
        
        // 处理初始层(1层)的请求
        if (shouldStop()) {
            status = OPENING;
            System.out.println("Open Door # Floor " + currentFloor);
            removeRequests(currentFloor);
            System.out.println("Close Door");
            status = CLOSING;
        }
        
        // 主处理循环
        while (!allQueuesEmpty()) {
            // 移动电梯
            moveElevator();
            
            // 处理当前层
            if (shouldStop()) {
                status = OPENING;
                System.out.println("Open Door # Floor " + currentFloor);
                removeRequests(currentFloor);
                System.out.println("Close Door");
                status = CLOSING;
            }
            
            // 更新方向
            updateDirection();
        }
        
        // 最终状态
        status = STOPPED;
        direction = IDLE;
    }

    private void setInitialDirection() {
        // 寻找最近的请求
        Integer nearestUp = null;
        Integer nearestDown = null;
        int minDistUp = Integer.MAX_VALUE;
        int minDistDown = Integer.MAX_VALUE;
        
        // 检查内部请求
        for (int floor : innerQueue) {
            int dist = floor - currentFloor;
            if (dist > 0 && dist < minDistUp) {
                minDistUp = dist;
                nearestUp = floor;
            } else if (dist < 0 && -dist < minDistDown) {
                minDistDown = -dist;
                nearestDown = floor;
            }
        }
        
        // 检查外部上行请求
        for (int floor : outerUpQueue) {
            int dist = floor - currentFloor;
            if (dist > 0 && dist < minDistUp) {
                minDistUp = dist;
                nearestUp = floor;
            }
        }
        
        // 检查外部下行请求
        for (int floor : outerDownQueue) {
            int dist = floor - currentFloor;
            if (dist < 0 && -dist < minDistDown) {
                minDistDown = -dist;
                nearestDown = floor;
            }
        }
        
        // 确定方向
        if (nearestUp != null && nearestDown != null) {
            direction = (minDistUp <= minDistDown) ? UP : DOWN;
        } else if (nearestUp != null) {
            direction = UP;
        } else if (nearestDown != null) {
            direction = DOWN;
        } else {
            direction = IDLE;
        }
    }

    private void moveElevator() {
        if (direction != IDLE) {
            status = MOVING;
            currentFloor += direction;
            System.out.printf("Current Floor: %d Direction: %s%n",
                currentFloor, direction == UP ? "UP" : "DOWN");
        }
    }

    private void updateDirection() {
        if (direction == UP) {
            if (!hasRequestsAbove()) {
                direction = hasRequestsBelow() ? DOWN : IDLE;
            }
        } else if (direction == DOWN) {
            if (!hasRequestsBelow()) {
                direction = hasRequestsAbove() ? UP : IDLE;
            }
        }
    }

    private boolean hasRequestsAbove() {
        for (int floor : innerQueue) {
            if (floor > currentFloor) return true;
        }
        for (int floor : outerUpQueue) {
            if (floor > currentFloor) return true;
        }
        return false;
    }

    private boolean hasRequestsBelow() {
        for (int floor : innerQueue) {
            if (floor < currentFloor) return true;
        }
        for (int floor : outerDownQueue) {
            if (floor < currentFloor) return true;
        }
        return false;
    }

    private boolean shouldStop() {
        // 内部请求
        if (innerQueue.contains(currentFloor)) return true;
        
        // 外部请求
        if (direction == UP && outerUpQueue.contains(currentFloor)) return true;
        if (direction == DOWN && outerDownQueue.contains(currentFloor)) return true;
        
        return false;
    }

    private void removeRequests(int floor) {
        innerQueue.removeIf(f -> f == floor);
        outerUpQueue.removeIf(f -> f == floor);
        outerDownQueue.removeIf(f -> f == floor);
    }

    private boolean allQueuesEmpty() {
        return innerQueue.isEmpty() && outerUpQueue.isEmpty() && outerDownQueue.isEmpty();
    }
}

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");
                    continue;
                }

                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");
                    continue;
                }
                floor = Integer.parseInt(request.replaceAll("[<>]", ""));
                elevator.addInternalRequest(floor);
            }
        }
        
        while(!elevator.getInternalRequests().isEmpty()
                || !elevator.getExternalRequests().isEmpty()) {
            elevator.processRequests();
        }
        
        input.close();
    }
}

报表内容:

图1:第一次作业类图设计

指标 数值 问题
代码行数 267 方法聚合度过高
最大复杂度 9 需拆分方法
注释比例 7.5% 低于20%的推荐标准

(1)设计分析:

第一次题目一共写了267行代码,注释占其中的7.5%,通过上表和类图也可以看得出来,在第一次题目中我写的类只有一个,然后就是一个main主类,平均类的方法数量是很大的,代码都集中在了一个类里面,代码的最大复杂性是9算是很大的复杂程度了,然后注释占比就太少了只有七点多是需要我改进的

(2)心得:

在第一次中虽然代码比较复杂也比较冗余到了一处,但是有了整体的一个运行思路,再接下来的题目中我就可以将现在的复杂代码进行拆分,将类的种类属性细致化,使得代码程序更加完善

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

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

电梯运行规则与前阶段单类设计相同,但要处理如下情况:
乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>

分析:相比于前一次的pta电梯作业,这次在输入控制上添加了不能重复的要求和最高,低楼层的限制。好在在一开始就考虑到这一点,所以在更改的时候只需要在输入类中添加输入前的要求判断保证数据正常才能输入到数组里,然后就是再细化类。

类图:

报表内容:

点击查看代码
import java.util.LinkedList;
import java.util.Scanner;

enum State {
    MOVING, STOPPED
}
enum Direction {
    UP, DOWN, IDLE
}

class Elevator {
    private int currentFloor;
    private int maxFloor;
    private int minFloor;
    private Direction direction;
    private State state;
    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        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){
            if(floor <= maxFloor){
                return true;
            }
        }
        return false;
    }
}

class ExternalRequest {
    private Integer floor;
    private Direction direction;

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

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

    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 addExternalRequest(int floor, Direction direction) {
        externalRequests.add(new ExternalRequest(floor, direction));
    }
    public void addInternalRequest(int floor) {
        internalRequests.add(floor);
    }

}

class Controller {
    private Elevator elevator;
    private RequestQueue queue;

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

    public void processRequests() {
        determineDirection();
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
        while (!queue.getInternalRequests().isEmpty() || !queue.getExternalRequests().isEmpty()) {
            int nextFloor;
            if (elevator.getDirection() == Direction.UP) {
                nextFloor = elevator.getCurrentFloor() + 1;
            } else {
                nextFloor = elevator.getCurrentFloor() - 1;
            }
            elevator.setCurrentFloor(nextFloor);
            System.out.println("Current Floor: " + nextFloor + " Direction: " + elevator.getDirection());
            if (shouldStop(nextFloor)) {
                System.out.println("Open Door # Floor " + nextFloor);
                System.out.println("Close Door");
                removeRequests(nextFloor);
            }
            determineDirection();
            // 检查是否还有未处理的请求
            if (queue.getInternalRequests().isEmpty() && queue.getExternalRequests().isEmpty()) {
                break;
            }
        }
    }

    private void determineDirection() {
        if (elevator.getDirection() == Direction.IDLE) {
            if (!queue.getInternalRequests().isEmpty()) {
                int target = queue.getInternalRequests().getFirst();
                if (elevator.getCurrentFloor() < target) {
                    elevator.setDirection(Direction.UP);
                } else {
                    elevator.setDirection(Direction.DOWN);
                }
            } else if (!queue.getExternalRequests().isEmpty()) {
                ExternalRequest req = queue.getExternalRequests().getFirst();
                elevator.setDirection(req.getDirection());
            }
        } else {
            boolean hasSameDir = checkInternal();
            if (!hasSameDir) {
                hasSameDir = checkExternal();
            }
            if (!hasSameDir) {
                elevator.setDirection(elevator.getDirection() == Direction.UP? Direction.DOWN : Direction.UP);
            }
        }
    }

    private boolean checkInternal() {
        for (int floor : queue.getInternalRequests()) {
            if ((elevator.getDirection() == Direction.UP && floor > elevator.getCurrentFloor()) ||
                    (elevator.getDirection() == Direction.DOWN && floor < elevator.getCurrentFloor())) {
                return true;
            }
        }
        return false;
    }

    private boolean checkExternal() {
        for (ExternalRequest req : queue.getExternalRequests()) {
            if (req.getDirection() == elevator.getDirection() &&
                    (elevator.getDirection() == Direction.UP? req.getFloor() > elevator.getCurrentFloor() : req.getFloor() < elevator.getCurrentFloor())) {
                return true;
            }
        }
        return false;
    }

    private boolean shouldStop(int floor) {
        if (queue.getInternalRequests().contains(floor)) {
            return true;
        }
        for (ExternalRequest req : queue.getExternalRequests()) {
            if (req.getFloor() == floor && req.getDirection() == elevator.getDirection()) {
                return true;
            }
        }
        return false;
    }

    private void removeRequests(int floor) {
        // 移除外部请求中当前方向和楼层的请求
        for (int i = queue.getExternalRequests().size() - 1; i >= 0; i--) {
            ExternalRequest req = queue.getExternalRequests().get(i);
            if (req.getFloor() == floor && req.getDirection() == elevator.getDirection()) {
                queue.getExternalRequests().remove(i);
            }
        }
        // 仅在方向匹配时移除内部请求
        if (queue.getInternalRequests().contains(floor) && shouldStopDueToInternal(floor)) {
            Integer targetFloor = floor;
            queue.getInternalRequests().remove(targetFloor);
        }
    }

    private boolean shouldStopDueToInternal(int floor) {
        // 判断是否因内部请求在当前方向停下
        return (elevator.getDirection() == Direction.UP && floor >= elevator.getCurrentFloor()) ||
                (elevator.getDirection() == Direction.DOWN && floor <= elevator.getCurrentFloor()) ||
                elevator.getDirection() == Direction.IDLE;
    }
}

public class Main {
    public static void main(String[] args) {
        int minFloor,maxFloor;
        Scanner scanner = new Scanner(System.in);
        minFloor = scanner.nextInt();
        scanner.nextLine();
        maxFloor = scanner.nextInt();
        scanner.nextLine();
        boolean judgment=true;
        Elevator elevator = new Elevator(minFloor, maxFloor);
        RequestQueue Rqueue = new RequestQueue();
        Controller controller = new Controller(elevator, Rqueue);

        String LR = null;
        while (judgment) {
            String line = scanner.nextLine();
            if (line.equalsIgnoreCase("end")) {
                break;
            }
            if (line.startsWith("<") && line.endsWith(">")) {
                line = line.substring(1, line.length() - 1);
                if (line.length()!=1) {
                    String[] parts = line.split(",");
                    int floor = Integer.parseInt(parts[0]);
                    Direction direction = Direction.valueOf(parts[1]);
                    if (elevator.isValidFloor(floor)) {
                        String currentReq = line;
                        if (LR == null || !currentReq.equals(LR)) {
                            Rqueue.addExternalRequest(floor, direction);
                            LR = currentReq;
                        }
                    }
                } else {
                    int floor = Integer.parseInt(line);
                    if (elevator.isValidFloor(floor)) {
                        String currentReq = line;
                        if (LR == null || !currentReq.equals(LR)) {
                            Rqueue.addInternalRequest(floor);
                            LR = currentReq;
                        }
                    }
                }
            }
        }

        controller.processRequests();
    }
}

(1)设计分析:

相较于第一次题目,这次的类图可以看出我声明了不同的类对象来包含对应方法,将方向与电梯状态设计成枚举类,由controller类里实现相关联的队列类电梯类里的操作。第二次题目的代码相较于第一次,首先是类的种类多了,用具体的对象来实现所属功能,而不是想第一次题目时将所有功能汇聚到一个大类中,使得分工调用不明确不清晰。通过报表中的模型数据可以看出每个类的平均方法由第一个题目的7下降到了4,所使用的分支语句也有所精简,但最大复杂度又上升到了13,说明有实现的方法还是并没有用清晰的逻辑实现。

(2)心得:

第二次电梯代码还是没有得分,而且因为时间截止前一直在赶代码,也并没有对代码进行好好注释使代码的易读性更高,和方法之间调用的合理性进行设计,代码总体看起来就是哪里看起来需要就哪里调用而不是合理的模块化,虽然代码最后运行出来的结果跟样例一样,但是没有通过任何一个测试点说明我的电梯代码的逻辑是有问题的,需要对获取电梯内外请求的方法和上下行的逻辑进行更改

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

类图:
报表:

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

enum Direction {
    UP, DOWN, IDLE
}

enum State {
    MOVING, STOPPED
}

class Passenger {
    Integer sourceFloor;
    Integer destinationFloor;


    public Passenger(Integer sourceFloor, Integer destinationFloor) {
        this.destinationFloor = destinationFloor;
        this.sourceFloor = sourceFloor;
    }

    public Passenger(Integer destinationFloor) {
        this.destinationFloor = destinationFloor;
        this.sourceFloor = null;
    }

    public Integer getDestinationFloor() {
        return destinationFloor;
    }

    public Integer getSourceFloor() {
        return sourceFloor;
    }

    public Direction getDirection() {
        if (sourceFloor != null) {
            if(sourceFloor == destinationFloor){
                return Direction.IDLE;
            }
            return sourceFloor > destinationFloor ? Direction.DOWN : Direction.UP;
        }
        return sourceFloor > destinationFloor ? Direction.DOWN : Direction.UP;
    }
}

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

    public void addInternalRequest(Passenger passenger) {
        internalRequests.add(passenger);
    }

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

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

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

    public int getExternalRequestsLength() {
        return externalRequests.size();
    }
}

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.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 boolean isValidFloor(int floor) {
        return floor >= minFloor && floor <= maxFloor;
    }
}

class Controller {
    private Elevator elevator;
    private RequestQueue queue;

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

    public void processRequests() {
        Integer nextFloor = getNextFloor();
        while (nextFloor!=null) {
            determineDirection(nextFloor);

            if (nextFloor == null) break;

            if (elevator.getCurrentFloor() == nextFloor) {
                openDoors();
            } else {
                while (shouldStop(nextFloor)) {
                    move(nextFloor);
                }
                openDoors();
                nextFloor=getNextFloor();
            }
        }
    }

    private void determineDirection(Integer nextFloor) {
            if (nextFloor != null) {
                if (elevator.getCurrentFloor() > nextFloor) {
                    elevator.setDirection(Direction.DOWN);
                } else if (elevator.getCurrentFloor() < nextFloor) {
                    elevator.setDirection(Direction.UP);
                }
                else if (!queue.getExternalRequests().isEmpty()) {
                    elevator.setDirection(queue.getExternalRequests().getFirst().getDirection());
                }
            }
        }
    private void move(int floor) {
        if (elevator.getCurrentFloor() > floor) {
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
        } else {
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        }
        System.out.printf("Current Floor: %d Direction: %s\n", elevator.getCurrentFloor(), elevator.getDirection());
    }

    private boolean shouldStop(int floor) {
        if(elevator.getCurrentFloor() == floor){
            return false;
        }
        return true;
    }

    private Integer getNextFloor()
    {
        Passenger firstExternal = null, firstInternal = null;
        if (!queue.getExternalRequests().isEmpty())
        {
            firstExternal = queue.getExternalRequests().getFirst();
        }
        if (!queue.getInternalRequests().isEmpty())
        {
            firstInternal = queue.getInternalRequests().getFirst();
        }
        if (firstExternal != null && firstInternal != null) {

            if (elevator.getCurrentFloor() > firstInternal.destinationFloor &&
                    elevator.getCurrentFloor() > firstExternal.sourceFloor) {
                if (elevator.getDirection() == Direction.UP || elevator.getDirection() == Direction.IDLE) {

                    removeRequests(firstInternal.destinationFloor > firstExternal.sourceFloor ? firstInternal.destinationFloor : firstExternal.sourceFloor);
                    return firstInternal.destinationFloor > firstExternal.sourceFloor ? firstInternal.destinationFloor : firstExternal.sourceFloor;
                } else if (elevator.getDirection() == Direction.DOWN || elevator.getDirection() == Direction.IDLE) {
                    removeRequests(firstInternal.destinationFloor > firstExternal.sourceFloor ? firstInternal.destinationFloor : firstExternal.sourceFloor);
                    return firstInternal.destinationFloor > firstExternal.sourceFloor ? firstInternal.destinationFloor : firstExternal.sourceFloor;
                }
            }
            //33
            if (elevator.getCurrentFloor() < firstInternal.destinationFloor &&
                    elevator.getCurrentFloor() > firstExternal.sourceFloor) {
                if (elevator.getDirection() == Direction.UP || elevator.getDirection() == Direction.IDLE) {
                    removeRequests(firstInternal.destinationFloor);
                    return firstInternal.destinationFloor;
                } else if (elevator.getDirection() == Direction.DOWN || elevator.getDirection() == Direction.IDLE) {
                    if (firstExternal.sourceFloor - firstExternal.destinationFloor > 0) {

                        removeRequests(firstExternal.sourceFloor);
                        return firstExternal.sourceFloor;
                    } else {
                        return firstInternal.destinationFloor;
                    }
                }
            }
            //22
            if (elevator.getCurrentFloor() > firstInternal.destinationFloor &&
                    elevator.getCurrentFloor() < firstExternal.sourceFloor) {
                if (elevator.getDirection() == Direction.UP || elevator.getDirection() == Direction.IDLE) {
                    if (firstExternal.sourceFloor - firstExternal.destinationFloor < 0) {
                        removeRequests(firstExternal.sourceFloor);
                        return firstExternal.sourceFloor;
                    } else {
                        return firstInternal.destinationFloor;
                    }
                }
            } else if (elevator.getDirection() == Direction.DOWN || elevator.getDirection() == Direction.IDLE) {
                removeRequests(firstInternal.destinationFloor);
                return firstInternal.destinationFloor;
            }

//11
            if (elevator.getCurrentFloor() < firstInternal.destinationFloor &&
                    elevator.getCurrentFloor() < firstExternal.sourceFloor) {
                if (elevator.getDirection() == Direction.UP || elevator.getDirection() == Direction.IDLE) {
                    if (firstExternal.sourceFloor - firstExternal.destinationFloor < 0) {
                        removeRequests(firstInternal.destinationFloor > firstExternal.sourceFloor ? firstExternal.sourceFloor : firstInternal.destinationFloor);
                        return firstInternal.destinationFloor > firstExternal.sourceFloor ? firstExternal.sourceFloor : firstInternal.destinationFloor;
                    } else {
                        removeRequests(firstInternal.destinationFloor);
                        return firstInternal.destinationFloor;
                    }
                } else if (elevator.getDirection() == Direction.DOWN || elevator.getDirection() == Direction.IDLE) {
                    removeRequests(firstInternal.destinationFloor > firstExternal.sourceFloor ? firstExternal.sourceFloor : firstInternal.destinationFloor);
                    return firstInternal.destinationFloor > firstExternal.sourceFloor ? firstExternal.sourceFloor : firstInternal.destinationFloor;
                }
            }
        }

        else if(firstExternal==null&&firstInternal!=null){
            removeRequests(firstInternal.destinationFloor);
            return firstInternal.destinationFloor;
        }else if(firstExternal!=null&&firstInternal==null){
            removeRequests(firstExternal.sourceFloor);
            return firstExternal.sourceFloor;
        }
        else if(firstExternal==null&&firstInternal==null){
            return null;
        }

        return null;
    }

    private void openDoors() {
        System.out.printf("Open Door # Floor %d\n", elevator.getCurrentFloor());
        System.out.printf("Close Door\n");
    }


    private void removeRequests(int floor) {

        Passenger firstExternal=null;
        if (!queue.getExternalRequests().isEmpty()){
            firstExternal=queue.getExternalRequests().getFirst();
        }
            if (!queue.getInternalRequests().isEmpty()) {
            Passenger firstInternal = queue.getInternalRequests().getFirst();
            if (firstInternal.getDestinationFloor() == floor) {
                if(firstExternal!=null&&firstExternal.getSourceFloor()==floor){
                   // queue.addInternalRequest(new Passenger(firstInternal.getDestinationFloor()));
                }
                queue.getInternalRequests().removeFirst();
            }
        }
        if (firstExternal!=null||!queue.getExternalRequests().isEmpty()) {
            if (firstExternal.getSourceFloor() == floor) {
                queue.addInternalRequest(new Passenger(
                        firstExternal.getDestinationFloor()));
                queue.getExternalRequests().removeFirst();
            }
        }

    }

}

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(",");
                        Passenger p1=new Passenger(Integer.parseInt(parts[0]),Integer.parseInt(parts[1]));
                                queue.addExternalRequest(p1);
                    }
                    else
                        {
                        int floor = Integer.parseInt(input);
                        //if (floor >= minFloor && floor <= maxFloor) {
                            queue.addInternalRequest(new Passenger(floor));
                        //}
                    }
                }
        }
        controller.processRequests();
        scanner.close();
    }
}    

(1)设计分析:

第三次类图中相较于第二次类图进行了将队列里由第二题的具体数据类型改为了存储乘客类对象数据,各个方法中对乘客类数据的请求进行操作,代码数也是写了327行,在类的设计时又第二次题目的传入内部队列为数据换成了队列存储的都是乘客对象,模拟现实逻辑,但报表中可以看出因为时间问题这次写的代码用了很多的ifelse的分支语句使得代码复杂度大大上升甚至到了45,所以代码是有着很高的可以简化提升的地方。

(2)心得:

这次的代码并不像前两次一样一分未得,最开始写完代码后,得了一半的分数,四个案例中有两个未通过,说明代码有漏洞,但很长时间一直修改并未发现代码错误在哪里,直到在通过对代码结果重复测试后,才发现原来是有两个判断上行下行的函数在进行判断时的条件并未写全,在一些情况下运行出来的结果与题目想要的结果不一,虽然临时改动但奈何时间还是截止了只改好了一个地方的逻辑,通过了三个案例并未得满分。这也让我意识到了在写代码时应该先设计一个大体框架,然后将内部逻辑细节完善完整并做好注释后再开始写对应代码才能更好避免这样的问题再次发生

三.踩坑与心得:

这三次题目都暴露出了我很多的问题,逻辑上的欠缺,每一次题目都没有考虑整体逻辑,所以每次运行完都是只是部分一样,像第二第三题就是这样导致分数没有拿到。很多时候都是考虑了上行没考虑下行,考虑了改变方向但没考虑全所有的改变方向的条件。还有像内部有第三层的请求外部也有,当运行到第三层的时候我将其全部出队了导致后面就不会再有第三层相关的输出语句这也是考虑逻辑上不完全所导致的错误

像在进行内部外部队列的出入时程序会报错,后来才发现是因为我并没有对队列进行判空,使得外部队列空的情况下依然对它进行了访问才出错了。

程序还有进入死循环一直重复输出一个楼层的情况经过检查是出队函数的地方的判断条件出现了逻辑短路,当&&前为假的时候他就不会去进入判断后面那个条件导致不会对最后一个数据出队
所以以上的问题和代码整体的复杂度可读性,逻辑设计都是我下一次需要注意不再踩坑的地方

四.改进建议:

对于代码来说,减少ifelse的使用,更多的用模块化来编写这样后续修改代码的时候就会很方便而不是再一堆的分支语句里面找逻辑错误。代码的注释也应该多一些,在设计逻辑问题的时候应该先在脑海中试运行一下会出现什么样的结果逻辑上有没有漏洞。设计代码的时候多用模块化,可以有搭建总体的大框架的能力。目前的代码在电梯问题上还是与现实的情况有所差别,只是单一原则运行而现实的电梯中会出现多种的情况,希望之后技术提升了之后可以将这个代码改进的与现实问题更相符合一点,可以处理同时发生的多种请求状况。

五.总结:

通过这三次题目集的系统训练,我对Java面向对象编程有了更深入的理解,特别是在电梯调度系统的三次迭代开发中收获最大,让我印象深刻的是在实现LOOK算法时,通过手动模拟各种呼叫场景(比如电梯上行时遇到反向请求),终于搞清楚了调度优先级的设计逻辑。虽然一开始没能完全做出来,但在尝试不同解决方案的过程中,我学会了如何权衡算法效率与代码复杂度,比如测试发现简单的批量处理同方向请求比复杂的动态权重计算更适合我们的场景。
另外希望有更多工具使用的指导,刚开始用SourceMonitor时连基本的指标都看不懂。以及对各种作业的要求更加明晰。总的来说,这阶段的训练让我明白编程不是单纯写代码,更是培养工程化思维和解决问题能力的过程。
我的心态也经历了从"急于求成"到"循序渐进"的转变。第一次看到题目要求时那种"这怎么可能实现"的恐慌感,在拆分问题、逐步验证的过程中慢慢变成了"试试看总能解决"的沉稳。特别是在最后的高难度扩展题中,虽然没能完美实现所有功能,但学会了接受"阶段性成果"的价值——就像真实项目开发中,与其执着于100分的理想方案,不如先交付80分的可用版本。

posted on 2025-04-20 22:12  周婉辰  阅读(23)  评论(0)    收藏  举报