第一次Blog作业

一、前言
JAVA的学习已经快半个学期了,在上个学期学习的C语言的基础之下,JAVA的不同点在于有更多丰富的库,其语法和结构相较于C语言更为复杂,这此的5-7题目集结构分为前面的基础题与后面大分值的电梯迭代作业,对于前几题,主要考察的是对我们基础JAVA语法的掌控,但后续的电梯迭代作业则需要我们考虑更多,包括类的设计,时间复杂度等问题,第五个题目集的前四题都与正则表达式相关,知识点都是围绕如何正确使用正则表达式展开,但在电梯迭代的设计上需要花很多时间去打磨,算法逻辑设计,类设计,处理类与类之间的关系等都需要花费我很多的时间。但我也受益匪浅。

二、设计与分析
第五次作业:
我的源代码:import java.util.*;

enum Direction {
UP, DOWN, STOPPED
}

class Elevator {
private final int minFloor;
private final int maxFloor;
private int currentFloor;
private Direction direction;
private Queue internalQueue;
private Queue<Map.Entry<Integer, Direction>> externalQueue;

public Elevator(int minFloor, int maxFloor) {
    this.minFloor = minFloor;
    this.maxFloor = maxFloor;
    this.currentFloor = minFloor;
    this.direction = Direction.STOPPED;
    this.internalQueue = new LinkedList<>();
    this.externalQueue = new LinkedList<>();
}

public void addInternalRequest(int floor) {
    if (isValidFloor(floor)) {
        internalQueue.offer(floor);
    }
}

public void addExternalRequest(int floor, Direction dir) {
    if (isValidFloor(floor)) {
        externalQueue.offer(new AbstractMap.SimpleEntry<>(floor, dir));
    }
}

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

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

    while (!internalQueue.isEmpty() || !externalQueue.isEmpty()) {
        if (direction == Direction.STOPPED) {
            determineDirection();
        }

        move();

        if (shouldStop()) {
            openDoor();
            removeRequests();
            closeDoor();
        }

        checkDirectionChange();
    }
}

private void determineDirection() {
    if (!internalQueue.isEmpty() && !externalQueue.isEmpty()) {
        int internalFloor = internalQueue.peek();
        Map.Entry<Integer, Direction> externalReq = externalQueue.peek();

        if ((internalFloor > currentFloor && externalReq.getValue() == Direction.UP) ||
                (internalFloor < currentFloor && externalReq.getValue() == Direction.DOWN)) {
            direction = internalFloor > currentFloor ? Direction.UP : Direction.DOWN;
        } else {
            direction = externalReq.getValue();
        }
    } else if (!internalQueue.isEmpty()) {
        int floor = internalQueue.peek();
        direction = floor > currentFloor ? Direction.UP : Direction.DOWN;
    } else if (!externalQueue.isEmpty()) {
        direction = externalQueue.peek().getValue();
    }
}

private void move() {
    if (direction == Direction.UP) {
        currentFloor++;
    } else if (direction == Direction.DOWN) {
        currentFloor--;
    }
    System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
}

private boolean shouldStop() {
    if (!internalQueue.isEmpty() && internalQueue.peek() == currentFloor) {
        return true;
    }

    if (!externalQueue.isEmpty()) {
        Map.Entry<Integer, Direction> req = externalQueue.peek();
        if (req.getKey() == currentFloor) {
            return direction == req.getValue() ||
                    (direction == Direction.UP && currentFloor == maxFloor) ||
                    (direction == Direction.DOWN && currentFloor == minFloor);
        }
    }

    return false;
}

private void removeRequests() {
    if (!internalQueue.isEmpty() && internalQueue.peek() == currentFloor) {
        internalQueue.poll();
    }

    if (!externalQueue.isEmpty() && externalQueue.peek().getKey() == currentFloor) {
        externalQueue.poll();
    }
}

private void checkDirectionChange() {
    boolean hasUpRequests = false;
    boolean hasDownRequests = false;

    for (int floor : internalQueue) {
        if (floor > currentFloor) hasUpRequests = true;
        if (floor < currentFloor) hasDownRequests = true;
    }

    for (Map.Entry<Integer, Direction> req : externalQueue) {
        if (req.getValue() == Direction.UP && req.getKey() > currentFloor) hasUpRequests = true;
        if (req.getValue() == Direction.DOWN && req.getKey() < currentFloor) hasDownRequests = true;
    }

    if (direction == Direction.UP && !hasUpRequests) {
        direction = hasDownRequests ? Direction.DOWN : Direction.STOPPED;
    } else if (direction == Direction.DOWN && !hasDownRequests) {
        direction = hasUpRequests ? Direction.UP : Direction.STOPPED;
    }
}

private void openDoor() {
    System.out.println("Open Door # Floor " + currentFloor);
}

private void closeDoor() {
    System.out.println("Close Door");
}

}

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
List inputs = new ArrayList<>();

    while (input.hasNext()) {
        String data = input.next();
        if (data.equalsIgnoreCase("end")) break;
        inputs.add(data);
    }
    input.close();

    if (inputs.size() < 2) {
        System.out.println("Invalid input");
        return;
    }

    try {
        int minFloor = Integer.parseInt(inputs.get(0));
        int maxFloor = Integer.parseInt(inputs.get(1));

        Elevator elevator = new Elevator(minFloor, maxFloor);

        for (int i = 2; i < inputs.size(); i++) {
            String request = inputs.get(i);
            if (request.contains(",")) {
                if (!request.matches("<\\d+,\\s*(UP|DOWN)>")) {
                    System.out.println("Wrong Format: " + request);
                    continue;
                }
                String[] parts = request.replaceAll("[<>]", "").split(",");
                int floor = Integer.parseInt(parts[0].trim());
                Direction dir = Direction.valueOf(parts[1].trim().toUpperCase());
                elevator.addExternalRequest(floor, dir);
            } else {
                if (!request.matches("<\\d+>")) {
                    System.out.println("Wrong Format: " + request);
                    continue;
                }
                int floor = Integer.parseInt(request.replaceAll("[<>]", ""));
                elevator.addInternalRequest(floor);
            }
        }

        elevator.processRequests();

    } catch (NumberFormatException e) {
        System.out.println("Invalid floor number");
    } catch (IllegalArgumentException e) {
        System.out.println("Invalid direction");
    }
}

}

代码分析

我的代码实现了一个简单的电梯控制系统,包含两个主要类:Elevator(电梯)和Main(主程序),以及一个辅助枚举Direction。构造函数
初始化电梯的基本状态和请求队列
请求添加方法
addInternalRequest():处理电梯内部按钮请求
addExternalRequest():处理楼层外部按钮请求
都包含有效性检查(isValidFloor())
核心处理流程
processRequests():主处理循环
determineDirection():决定电梯运行方向 move():移动电梯到相邻楼层 shouldStop():判断是否应在当前楼层停止 removeRequests():移除已处理的请求
checkDirectionChange():检查是否需要改变方向

类图:
复杂度图:

其中sourcemonitor图中解释如下:
行数:187 行
语句数:115 条
分支语句百分比:27.0% ,意味着超过四分之一语句是分支逻辑(if-else)
方法调用语句数:67 条
注释行百分比:0.0% ,即代码无注释
类和接口数量:3 个
每个类的平均方法数:4.33 个
每个方法的平均语句数):7.08 条
最复杂方法的行号 102 行,方法为 Elevator.checkDirectionChange()
最大复杂度为15,方法也是Elevator.checkDirectionChange()
最深代码块行号:159 行
最大代码块深度为 6
平均代码块深度:2.50
平均复杂度:4.31

程序分析:
checkDirectionChange()方法
复杂度高达15(远高于平均4.31)
包含16语句和4个方法调用
问题:承担了过多方向判断逻辑,应拆分
main()方法
复杂度11,33个语句
块深度达到6层
问题:处理输入、解析请求、错误处理全部集中
注释缺失
0%的代码行有注释
特别是复杂方法缺乏解释性注释
请求优先级
当前实现简单使用队列(FIFO),可能导致效率不高
可考虑按方向优化请求处理顺序
错误处理
可以增加更详细的错误信息和日志
并发考虑
当前设计是单线程的,实际电梯系统可能需要考虑并发请求
测试覆盖
需要增加更多边界条件测试(如最高/最低楼层请求)
性能优化
对于高楼层的电梯,线性检查所有请求可能效率不高

改进:
拆分高复杂度方法
将checkDirectionChange()拆分为:
checkUpRequests()
checkDownRequests()
determineNewDirection()
重构main方法
提取输入处理为parseInput()方法
提取请求解析为parseRequest()方法
提取错误处理为单独方法
增加注释
为每个方法添加JavaDoc
为复杂逻辑段添加行内注释
中长期改进
引入设计模式
考虑使用状态模式处理电梯方向状态
使用策略模式处理不同的请求调度算法
增强测试覆盖
为高复杂度方法添加单元测试
特别是边界条件测试
代码审查重点
关注checkDirectionChange和shouldStop的逻辑正确性
验证深层嵌套块的可读性

第六次作业:
我的源代码:import java.util.LinkedList;
import java.util.Scanner;

enum Direction {
UP, DOWN, IDLE
}

enum State {
MOVING, STOPPED
}

class Request {
private int floor;
private Direction direction; // null表示电梯内请求

public Request(int floor, Direction direction) {
    this.floor = floor;
    this.direction = direction;
}

public int getFloor() {
    return floor;
}

public Direction getDirection() {
    return direction;
}

public boolean isExternal() {
    return direction != null;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Request request = (Request) obj;
    return floor == request.floor && direction == request.direction;
}

}

class RequestQueue {
private LinkedList internalRequests = new LinkedList<>();
private LinkedList externalUpRequests = new LinkedList<>();
private LinkedList externalDownRequests = new LinkedList<>();

public void addRequest(Request request) {
    if (request.isExternal()) {
        if (request.getDirection() == Direction.UP && !externalUpRequests.contains(request)) {
            externalUpRequests.add(request);
        } else if (request.getDirection() == Direction.DOWN && !externalDownRequests.contains(request)) {
            externalDownRequests.add(request);
        }
    } else {
        if (!internalRequests.contains(request)) {
            internalRequests.add(request);
        }
    }
}

public boolean hasRequests() {
    return !internalRequests.isEmpty() || !externalUpRequests.isEmpty() || !externalDownRequests.isEmpty();
}

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

public LinkedList<Request> getExternalUpRequests() {
    return new LinkedList<>(externalUpRequests);
}

public LinkedList<Request> getExternalDownRequests() {
    return new LinkedList<>(externalDownRequests);
}

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

public void removeExternalRequest(int floor, Direction direction) {
    if (direction == Direction.UP) {
        externalUpRequests.removeIf(req -> req.getFloor() == floor);
    } else {
        externalDownRequests.removeIf(req -> req.getFloor() == floor);
    }
}

}

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

public Elevator(int minFloor, int maxFloor) {
    this.minFloor = minFloor;
    this.maxFloor = maxFloor;
    this.currentFloor = minFloor;
    this.direction = Direction.IDLE;
    this.state = State.STOPPED;
    this.requestQueue = new RequestQueue();
}

public void addRequest(Request request) {
    if (isValidFloor(request.getFloor())) {
        requestQueue.addRequest(request);
    }
}

public void processRequests() {
    while (requestQueue.hasRequests()) {
        determineDirection();
        move();
    }
    direction = Direction.IDLE;
    state = State.STOPPED;
}

private void determineDirection() {
    if (direction == Direction.IDLE) {
        Request closest = findClosestRequest();
        if (closest != null) {
            if (closest.getFloor() > currentFloor) {
                direction = Direction.UP;
            } else if (closest.getFloor() < currentFloor) {
                direction = Direction.DOWN;
            } else {
                stopAtCurrentFloor();
            }
        }
    }
}

private Request findClosestRequest() {
    Request closest = null;
    int minDistance = Integer.MAX_VALUE;

    for (Request req : requestQueue.getInternalRequests()) {
        int distance = Math.abs(req.getFloor() - currentFloor);
        if (distance < minDistance) {
            minDistance = distance;
            closest = req;
        }
    }

    for (Request req : requestQueue.getExternalUpRequests()) {
        int distance = Math.abs(req.getFloor() - currentFloor);
        if (distance < minDistance) {
            minDistance = distance;
            closest = req;
        }
    }

    for (Request req : requestQueue.getExternalDownRequests()) {
        int distance = Math.abs(req.getFloor() - currentFloor);
        if (distance < minDistance) {
            minDistance = distance;
            closest = req;
        }
    }

    return closest;
}

private void move() {
    if (direction == Direction.IDLE) return;

    if (shouldStop(currentFloor)) {
        stopAtCurrentFloor();
        return;
    }

    if (direction == Direction.UP) {
        currentFloor++;
    } else {
        currentFloor--;
    }

    System.out.printf("Current Floor: %d Direction: %s\n", currentFloor, direction);

    if (shouldStop(currentFloor)) {
        stopAtCurrentFloor();
    }
}

private boolean shouldStop(int floor) {
    // 检查内部请求
    for (Request req : requestQueue.getInternalRequests()) {
        if (req.getFloor() == floor) {
            return true;
        }
    }

    // 检查外部请求
    if (direction == Direction.UP) {
        for (Request req : requestQueue.getExternalUpRequests()) {
            if (req.getFloor() == floor) {
                return true;
            }
        }
    } else if (direction == Direction.DOWN) {
        for (Request req : requestQueue.getExternalDownRequests()) {
            if (req.getFloor() == floor) {
                return true;
            }
        }
    }

    // 当前方向无请求时检查反方向请求
    if ((direction == Direction.UP && !hasRequestsInDirection(Direction.UP)) ||
        (direction == Direction.DOWN && !hasRequestsInDirection(Direction.DOWN))) {
        for (Request req : requestQueue.getExternalUpRequests()) {
            if (req.getFloor() == floor) {
                return true;
            }
        }
        for (Request req : requestQueue.getExternalDownRequests()) {
            if (req.getFloor() == floor) {
                return true;
            }
        }
    }

    return false;
}

private boolean hasRequestsInDirection(Direction dir) {
    if (dir == Direction.UP) {
        for (Request req : requestQueue.getInternalRequests()) {
            if (req.getFloor() > currentFloor) return true;
        }
        for (Request req : requestQueue.getExternalUpRequests()) {
            if (req.getFloor() > currentFloor) return true;
        }
    } else {
        for (Request req : requestQueue.getInternalRequests()) {
            if (req.getFloor() < currentFloor) return true;
        }
        for (Request req : requestQueue.getExternalDownRequests()) {
            if (req.getFloor() < currentFloor) return true;
        }
    }
    return false;
}

private void stopAtCurrentFloor() {
    System.out.printf("Open Door # Floor %d\n", currentFloor);
    System.out.println("Close Door");

    // 移除当前楼层所有内部请求
    requestQueue.removeInternalRequest(currentFloor);

    // 根据方向移除外部请求
    if (direction == Direction.UP) {
        requestQueue.removeExternalRequest(currentFloor, Direction.UP);
    } else if (direction == Direction.DOWN) {
        requestQueue.removeExternalRequest(currentFloor, Direction.DOWN);
    }

    // 如果当前方向无请求,检查是否需要改变方向
    if ((direction == Direction.UP && !hasRequestsInDirection(Direction.UP)) ||
        (direction == Direction.DOWN && !hasRequestsInDirection(Direction.DOWN))) {
        if (direction == Direction.UP && hasRequestsInDirection(Direction.DOWN)) {
            direction = Direction.DOWN;
        } else if (direction == Direction.DOWN && hasRequestsInDirection(Direction.UP)) {
            direction = Direction.UP;
        }
    }
}

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

}

public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

    int minFloor = scanner.nextInt();
    int maxFloor = scanner.nextInt();
    scanner.nextLine(); // 消耗换行符
    
    Elevator elevator = new Elevator(minFloor, maxFloor);
    
    while (true) {
        String input = scanner.nextLine().trim();
        if (input.equalsIgnoreCase("end")) {
            break;
        }
        
        try {
            if (input.startsWith("<") && input.endsWith(">")) {
                String content = input.substring(1, input.length() - 1);
                if (content.contains(",")) {
                    // 外部请求
                    String[] parts = content.split(",");
                    int floor = Integer.parseInt(parts[0]);
                    Direction direction = Direction.valueOf(parts[1]);
                    elevator.addRequest(new Request(floor, direction));
                } else {
                    // 内部请求
                    int floor = Integer.parseInt(content);
                    elevator.addRequest(new Request(floor, null));
                }
            }
        } catch (Exception e) {
            // 忽略无效输入
        }
    }
    
    elevator.processRequests();
}

}

代码分析:
类设计概述

  1. 枚举类型
    Direction: 定义电梯运行方向(UP, DOWN, IDLE)
    State: 定义电梯状态(MOVING, STOPPED)
  2. 核心类
    Request: 表示电梯请求(内部或外部)
    RequestQueue: 管理不同类型的请求队列
    Elevator: 电梯主体类,实现核心逻辑
    Main: 程序入口,处理输入和启动电梯
    详细类分析
  3. Request类
    职责:封装电梯请求信息
    属性:
    floor: 请求的目标楼层
    direction: 请求方向(外部请求才有方向,内部请求为null)
    方法:
    构造方法:初始化楼层和方向
    getter方法:获取楼层和方向
    isExternal(): 判断是否为外部请求
    equals(): 重写equals方法用于比较请求
  4. RequestQueue类
    职责:管理所有电梯请求,分为三类队列
    属性:
    internalRequests: 电梯内部请求队列
    externalUpRequests: 外部上行请求队列
    externalDownRequests: 外部下行请求队列
    方法:
    addRequest(): 添加请求到相应队列(避免重复)
    hasRequests(): 检查是否有任何请求
    各种getter方法:获取各队列的拷贝
    removeInternalRequest(): 移除特定楼层的内部请求
    removeExternalRequest(): 移除特定楼层和方向的外部请求
  5. Elevator类
    职责:实现电梯的核心运行逻辑
    属性:
    minFloor/maxFloor: 电梯运行范围
    currentFloor: 当前楼层
    direction: 当前运行方向
    state: 当前状态
    requestQueue: 请求队列实例
    主要方法:
    addRequest(): 添加请求到队列
    processRequests(): 主处理循环
    determineDirection(): 确定运行方向
    findClosestRequest(): 寻找最近的请求
    move(): 处理电梯移动
    shouldStop(): 判断是否应在当前楼层停止
    hasRequestsInDirection(): 检查特定方向是否有请求
    stopAtCurrentFloor(): 处理到达楼层后的操作
    isValidFloor(): 验证楼层是否有效
  6. Main类
    职责:程序入口,处理用户输入
    功能:
    读取电梯最小和最大楼层
    创建电梯实例
    循环读取输入直到"end"命令
    解析输入格式为请求并添加到电梯
    启动电梯处理请求

类图:

复杂度图:

其中sourcemonitor图中解释如下:
行数:317 行
语句数:187 条
分支语句百分比:31.1% ,意味着约三分之一语句是分支逻辑(if - else)
方法调用语句数:80 条
注释行百分比:3.5% ,即代码中注释占比较少
类和接口数量:6 个
每个类的平均方法数:3.83 个
每个方法的平均语句数:5.78 条
最复杂方法的行号:46 行,方法为 RequestQueue.addRequest()
最大复杂度为 8,方法为 RequestQueue.addRequest()
最深代码块行号:295 行
最大代码块深度为 6
平均代码块深度:2.19
平均复杂度:2.95

程序分析:多电梯支持:当前设计是单电梯系统
更复杂的调度算法:可以优化寻找最近请求的算法
异常处理:可以增加更详细的错误处理
日志系统:可以添加更详细的运行日志
性能优化:对于高楼层的电梯系统,可能需要优化请求查找算法
第六次题目集是对第一次电梯的迭代,一次作业主要花费时间在于算法的设计,每次比较内外部请求队列的队头并且选择合适的请求出队,而第二次作业主要花费时间在于如何去设计类,如何去处理类之间的关系才能使代码的可读性和可维护性更高。

第七次作业:

我的源代码:import java.util.Scanner;
import java.util.LinkedList;
import java.util.ArrayList;

enum Direction {
UP, DOWN, IDLE;
}

enum State {
MOVING, STOPPED, OPEN_DOOR, CLOSE_DOOR;
}

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

public Elevator(int minFloor, int maxFloor) {
    this.minFloor = minFloor;
    this.maxFloor = maxFloor;
    this.currentFloor = minFloor;
    this.state = State.STOPPED;
    this.direction = Direction.IDLE;
}

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) {
    return floor >= minFloor && floor <= maxFloor;
}

public void moveUp() {
    currentFloor++;
}

public void moveDown() {
    currentFloor--;
}

}

class Passenger {
private Integer sourceFloor;
private Integer destinationFloor;

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

public Integer getSourceFloor() {
    return sourceFloor;
}

public Integer getDestinationFloor() {
    return destinationFloor;
}

public Direction getDirection() {
    if (destinationFloor > sourceFloor) {
        return Direction.UP;
    } else if (destinationFloor < sourceFloor) {
        return Direction.DOWN;
    }
    return Direction.IDLE;
}

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

}

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

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

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

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

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

public void removeInternalRequest(Passenger passenger) {
    internalRequests.remove(passenger);
}

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

public boolean hasRequests() {
    return !internalRequests.isEmpty() || !externalRequests.isEmpty();
}

}

class Controller {
private Elevator elevator;
private RequestQueue queue;

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

public void processRequests() {
    while (queue.hasRequests()) {
        determineDirection();
        move();
    }
    elevator.setDirection(Direction.IDLE);
    elevator.setState(State.STOPPED);
}

private void determineDirection() {
    if (elevator.getDirection() == Direction.IDLE) {
        // Find the closest request
        Passenger nextRequest = findNextRequest();
        if (nextRequest != null) {
            if (nextRequest.getSourceFloor() > elevator.getCurrentFloor()) {
                elevator.setDirection(Direction.UP);
            } else if (nextRequest.getSourceFloor() < elevator.getCurrentFloor()) {
                elevator.setDirection(Direction.DOWN);
            } else {
                // Current floor is the source floor
                if (nextRequest.getDestinationFloor() > elevator.getCurrentFloor()) {
                    elevator.setDirection(Direction.UP);
                } else {
                    elevator.setDirection(Direction.DOWN);
                }
            }
        }
    }
}

private Passenger findNextRequest() {
    Passenger closest = null;
    int minDistance = Integer.MAX_VALUE;

    // Check external requests first
    for (Passenger p : queue.getExternalRequests()) {
        int distance = Math.abs(p.getSourceFloor() - elevator.getCurrentFloor());
        if (distance < minDistance) {
            minDistance = distance;
            closest = p;
        }
    }

    // Check internal requests
    for (Passenger p : queue.getInternalRequests()) {
        int distance = Math.abs(p.getDestinationFloor() - elevator.getCurrentFloor());
        if (distance < minDistance) {
            minDistance = distance;
            closest = p;
        }
    }

    return closest;
}

private void move() {
    if (elevator.getDirection() == Direction.IDLE) {
        return;
    }

    while (shouldContinueMoving()) {
        // Move one floor
        if (elevator.getDirection() == Direction.UP) {
            elevator.moveUp();
        } else {
            elevator.moveDown();
        }
        elevator.setState(State.MOVING);

        // Output current floor and direction
        System.out.println("Current Floor: " + elevator.getCurrentFloor() +
                " Direction: " + elevator.getDirection());

        // Check if we should stop at this floor
        if (shouldStop(elevator.getCurrentFloor())) {
            openDoors(elevator.getCurrentFloor());
            removeRequests(elevator.getCurrentFloor());
            closeDoors();
        }
    }
}

private boolean shouldContinueMoving() {
    if (elevator.getDirection() == Direction.UP) {
        // Check if there are any requests above current floor in our direction
        for (Passenger p : queue.getExternalRequests()) {
            if (p.getSourceFloor() > elevator.getCurrentFloor() &&
                    (p.getDirection() == Direction.UP || p.getSourceFloor() == elevator.getCurrentFloor())) {
                return true;
            }
        }
        for (Passenger p : queue.getInternalRequests()) {
            if (p.getDestinationFloor() > elevator.getCurrentFloor()) {
                return true;
            }
        }
    } else if (elevator.getDirection() == Direction.DOWN) {
        // Check if there are any requests below current floor in our direction
        for (Passenger p : queue.getExternalRequests()) {
            if (p.getSourceFloor() < elevator.getCurrentFloor() &&
                    (p.getDirection() == Direction.DOWN || p.getSourceFloor() == elevator.getCurrentFloor())) {
                return true;
            }
        }
        for (Passenger p : queue.getInternalRequests()) {
            if (p.getDestinationFloor() < elevator.getCurrentFloor()) {
                return true;
            }
        }
    }
    return false;
}

private boolean shouldStop(int floor) {
    // Check external requests
    for (Passenger p : queue.getExternalRequests()) {
        if (p.getSourceFloor() == floor) {
            // Only stop if the passenger wants to go in our direction
            if (elevator.getDirection() == Direction.UP && p.getDirection() == Direction.UP) {
                return true;
            } else if (elevator.getDirection() == Direction.DOWN && p.getDirection() == Direction.DOWN) {
                return true;
            } else if (elevator.getDirection() == Direction.IDLE) {
                return true;
            }
        }
    }

    // Check internal requests
    for (Passenger p : queue.getInternalRequests()) {
        if (p.getDestinationFloor() == floor) {
            return true;
        }
    }

    return false;
}

private void openDoors(int floor) {
    System.out.println("Open Door # Floor " + floor);
    elevator.setState(State.OPEN_DOOR);
}

private void closeDoors() {
    System.out.println("Close Door");
    elevator.setState(State.CLOSE_DOOR);
}

private void removeRequests(int currentFloor) {
    // Remove external requests first
    ArrayList<Passenger> toRemoveExternal = new ArrayList<>();
    for (Passenger p : queue.getExternalRequests()) {
        if (p.getSourceFloor() == currentFloor) {
            // Add destination to internal requests
            if (p.getDestinationFloor() != currentFloor) {
                queue.addInternalRequest(new Passenger(currentFloor, p.getDestinationFloor()));
            }
            toRemoveExternal.add(p);
        }
    }
    queue.getExternalRequests().removeAll(toRemoveExternal);

    // Remove internal requests
    ArrayList<Passenger> toRemoveInternal = new ArrayList<>();
    for (Passenger p : queue.getInternalRequests()) {
        if (p.getDestinationFloor() == currentFloor) {
            toRemoveInternal.add(p);
        }
    }
    queue.getInternalRequests().removeAll(toRemoveInternal);
}

}

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().trim();
        if (input.equalsIgnoreCase("end")) {
            break;
        }

        try {
            if (input.startsWith("<") && input.endsWith(">")) {
                String content = input.substring(1, input.length() - 1);
                if (content.contains(",")) {
                    // External request: <source,destination>
                    String[] parts = content.split(",");
                    int source = Integer.parseInt(parts[0].trim());
                    int destination = Integer.parseInt(parts[1].trim());

                    if (elevator.isValidFloor(source) && elevator.isValidFloor(destination) && source != destination) {
                        queue.addExternalRequest(new Passenger(source, destination));
                    }
                } else {
                    // Internal request: <floor>
                    int floor = Integer.parseInt(content.trim());
                    if (elevator.isValidFloor(floor)) {
                        queue.addInternalRequest(new Passenger(elevator.getCurrentFloor(), floor));
                    }
                }
            }
        } catch (NumberFormatException e) {
            // Ignore invalid input
        }
    }

    scanner.close();

    // Process the requests
    controller.processRequests();
}

}

代码分析:
Elevator:电梯类,跟踪当前状态、方向和位置
Passenger:乘客类,表示乘客的请求
RequestQueue:请求队列,管理内部和外部请求
Controller:控制器,处理请求并控制电梯移动
Main:主程序,处理输入并启动系统
这一次代码相较于上次的代码来说主要改进了格式,我们主要的改进点在正则表达式的编写

类图:

复杂度图:

其中sourcemonitor图中解释如下:
行数:375 行
语句数:212 条
分支语句百分比:25.0% ,意味着约四分之一语句是分支逻辑(if - else)
方法调用语句数:113 条
注释行百分比:5.1% ,即代码中注释占比较少
类和接口数量:7 个
每个类的平均方法数:5.00 个
每个方法的平均语句数:4.37 条
最复杂方法的行号:237 行,方法为 Controller.shouldContinueMoving()
最大复杂度:15 ,方法为 Controller.shouldContinueMoving()
最深代码块行号:355 行
最大代码块深度:7
平均代码块深度:2.45
平均复杂度:2.86

程序分析:
缺乏多电梯支持:当前系统只支持单个电梯,无法扩展为多电梯系统。
请求处理效率低:
使用简单的链表存储请求,查找效率低(O(n))
每次移动都要遍历所有请求检查是否需要停止
findNextRequest方法效率低,需要遍历所有请求
方向判断逻辑不完善:
电梯方向切换逻辑过于简单
没有实现"扫描算法"或"LOOK算法"等常见电梯调度算法
状态管理问题:
电梯状态转换不够严谨(如直接从MOVING到OPEN_DOOR)
缺少状态转换验证
输入处理脆弱:
对异常输入处理不足
没有验证源楼层和目标楼层的关系(如向下时请求更高楼层)
并发问题:
没有考虑多线程环境下的请求处理
请求队列不是线程安全的
缺乏测试性:
高度耦合的类结构
难以进行单元测试
日志和监控不足:
只有简单的控制台输出
没有记录电梯运行历史
改进建议
架构改进:
引入电梯调度器接口,支持多种调度算法
将电梯控制逻辑与请求处理分离
使用观察者模式监控电梯状态变化
性能优化:
使用优先级队列存储请求,按方向和楼层排序
实现更高效的调度算法(如SCAN, LOOK)
使用空间分区技术优化请求查找
功能增强:
支持多电梯协同工作
添加超载检测和报警功能
实现紧急停止功能
添加维护模式
代码质量改进:
增加输入验证和异常处理
实现更严谨的状态机
添加详细的日志记录
编写单元测试和集成测试
并发处理:
使用线程安全的数据结构
添加适当的同步机制
考虑使用消息队列处理请求
用户界面:
添加更友好的输入提示
实现图形化界面显示电梯状态
提供运行统计信息
当前实现提供了一个基础的电梯控制系统,但在效率、扩展性和健壮性方面存在不足。通过采用更先进的调度算法、改进数据结构和增强系统架构,可以显著提升系统性能和可维护性。特别是添加多电梯支持和并发处理能力将使系统更接近真实世界的电梯控制系统。

三、踩坑总结:
1.第一次题目集:我设计电梯类后,对于测试样例,一直有一行是不对的,答案错误,后来我就只想改那一行,后来发现当我动了代码后,整个代码就出错了,所以在以后的代码设计时,当出现错误后,我们应该考虑是否要重新设计算法,以免越改越错。
2.第二次题目集:在第一次的基础上,这次的代码主要是运行超时的问题,即程序一直在循环分析,后面我改进了结束循环的条件,让后问题就解决了;所以在以后的代码设计时,对于循环,我们不仅要考虑是否越界,也要考虑结束循环的条件。
3.第三次题目集:这次的题目集没有出现什么大的问题,主要是编译错误等问题,细心检查代码,进行debug后即可。

四、改进建议
架构改进:
引入电梯调度器接口,支持多种调度算法
将电梯控制逻辑与请求处理分离
使用观察者模式监控电梯状态变化
性能优化:
使用优先级队列存储请求,按方向和楼层排序
实现更高效的调度算法(如SCAN, LOOK)
使用空间分区技术优化请求查找
功能增强:
支持多电梯协同工作
添加超载检测和报警功能
实现紧急停止功能
添加维护模式
代码质量改进:
增加输入验证和异常处理
实现更严谨的状态机
添加详细的日志记录
编写单元测试和集成测试
并发处理:
使用线程安全的数据结构
添加适当的同步机制
考虑使用消息队列处理请求
用户界面:
添加更友好的输入提示
实现图形化界面显示电梯状态
提供运行统计信息
同时建议将电梯的实际情况考虑进来,即符合实际的电梯运行

五、总结:对于这三次题目集,主要学习了正则表达式,以及用不同的方法解决同样的问题,就比如计算Π,提供了很新颖的方式,同时电梯的迭代设计,也一步一步的引导我们去编写和完善代码,不断改进问题,通过这三次数据结构与算法的课程实践,我深刻认识到编程学习是一场思维与耐力的双重马拉松,每一次调试、每一行代码都承载着成长的重量。尽管最终程序在边界条件处理上仍有不足,但这段跌宕起伏的探索过程却赋予了我远超预期的收获。在技术成长方面,我从最初对指针操作的战战兢兢,到现在能够自主设计链表结构;从对递归算法的困惑不解,到能够分析时间复杂度并优化算法性能,实现了认知边界的不断拓展。在工程实践上,我逐渐建立起版本控制的意识,学会了通过Git管理项目迭代,更深刻体会到测试驱动开发的重要性——那些反复出现的Segmentation fault教会我严谨比聪明更重要。这三次的题目集让我受益匪浅。

posted @ 2025-04-20 20:41  24201513-丁琦  阅读(48)  评论(0)    收藏  举报