第一次blog作业

一、前言

  1. 第一次题目集的知识点包括正则表达式的运用、以及电梯调度问题,题量有五道题,其中电梯调度问题包括:基础类设计、状态管理、请求队列管理以及调度算法。难度主要在于电梯调度问题,其中的算法包括理清电梯移动逻辑、停层判断、移除请求,主要是方向切换逻辑和请求队列的同步处理难以理解。
  2. 第二次题目集主要考察编程时对类设计要考虑类与类之间的关系,题量有三题,其中难点仍在于第一次题目集电梯调度问题的迭代,这次电梯调度问题引入电梯类、乘客请求类、队列类以及控制类,知识点包括类设计要体现单一职责原则,题目要求取消独立的请求类,将请求封装到乘客类中,处理外部请求时需将目的楼层加入内部队列,可以参考类图设计。难度在于需要处理更多的类交互,逻辑较为复杂。
  3. 第三次题目集对类与类间的关系进行更深一步的考察,题量有三题,包括销售步枪问题、蒙特卡罗方法求圆周率以及电梯调度问题的第二次迭代,其中蒙特卡罗方法求圆周率稍微复杂,但也并不难理解,而电梯调度问题仍旧解决不了,这次的电梯调度问题的迭代加入乘客类,取消乘客请求类,知识点在于算法的处理及请求的处理,可以参考类图设计。

二、设计与分析
1.对于第一次题目集,对于前面正则表达式的运用没有问题,能够理解并且编写代码,但是对于电梯调度问题,却无从下手,初次编写电梯调度问题的代码,主要设计了两个枚举类,包括电梯的运行状态和运行方向,设计了电梯类(class Elevator)和主类,代码如下:

点击查看代码
import java.util.Scanner;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
enum Direction {
    UP, DOWN, IDLE
}
enum ElevatorState {
    STOPPED, MOVING, OPENING, CLOSING
}
class Elevator{
    private int minFloor;
    private int maxFloor;
    private int currentFloor;
    private Direction currentDirection;
    private ElevatorState currentState;
    private Queue<Integer> internalRequests;
    private Queue<int[]> externalUpRequests;
    private Queue<int[]> externalDownRequests;
    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.currentDirection = Direction.IDLE;
        this.currentState = ElevatorState.STOPPED;
        this.internalRequests = new LinkedList<>();
        this.externalUpRequests = new LinkedList<>();
        this.externalDownRequests = new LinkedList<>();
    }
    public boolean isValidFloor(int floor){
        return floor >= minFloor && floor <= maxFloor;
    }
    public void addInternalRequest(int floor){
        if (isValidFloor(floor)) {
            internalRequests.add(floor);
            if (currentState == ElevatorState.STOPPED) {
                currentDirection = getNextDirection();
                currentState = ElevatorState.MOVING;
            }
        }
    }
    public void addExternalRequest(int floor, Direction direction) {
        if (isValidFloor(floor)) {
            int[] request = new int[] {floor, direction == Direction.UP ? 1 : 0};
            if (direction == Direction.UP) {
                externalUpRequests.add(request);
            } else {
                externalDownRequests.add(request);
            }
            if (currentState == ElevatorState.STOPPED) {
                currentDirection = getNextDirection();
                currentState = ElevatorState.MOVING;
            }
        }
    }
    public void processRequests() {
        /*if (currentFloor == 1) {
            System.out.println("Current Floor: 1 Direction: UP");
        }*/
        if (currentDirection != Direction.IDLE) {
            System.out.println("Current Floor: " + currentFloor + " Direction: " + currentDirection);
        }
        while (!internalRequests.isEmpty() || !externalUpRequests.isEmpty() || !externalDownRequests.isEmpty()) {
            if (currentDirection == Direction.IDLE) {
                currentDirection = getNextDirection();
            }
            move();
        }
        /*while (shouldStop()) {
            openDoor();
            processCurrentFloorRequests();
            closeDoor();
        }*/
        currentState = ElevatorState.STOPPED;
    }
    public void move() {
        if (currentDirection == Direction.UP) {
            currentFloor ++;
        } else if (currentDirection == Direction.DOWN) {
            currentFloor --;
        }
        System.out.println("Current Floor: " + currentFloor + " Direction: " + currentDirection);
        if (shouldStop()) {
            openDoor();
            processCurrentFloorRequests();
            closeDoor();
        }
        if (isCurrentDirectionEmpty()) {
            currentDirection = getNextDirection();
        }
    }
    public boolean shouldStop() {
        return internalRequests.contains(currentFloor) ||
            (currentDirection == Direction.UP && hasUpRequestOnCurrentFloor()) ||
            (currentDirection == Direction.DOWN && hasDownRequestOnCurrentFloor());
    }
    public void openDoor() {
        currentState = ElevatorState.OPENING;
        System.out.println("Open Door # Floor " + currentFloor);
    }
    public void processCurrentFloorRequests() {
        /*internalRequests.removeIf(floor -> floor == currentFloor);
        externalUpRequests.removeIf(request -> request[0] == currentFloor && request[1] == 1);
        externalDownRequests.removeIf(request -> request[0] == currentFloor && request[1] == 0);*/
        /*for (int[] request : externalUpRequests) {
            if (request[0] == currentFloor && request[1] ==1) {
                externalUpRequests.remove(request);
                break;
            }
        }
        for (int[] request : externalDownRequests) {
            if (request[0] == currentFloor && request[1] ==0) {
                externalDownRequests.remove(request);
                break;
            }
        }*/
        if (currentDirection ==Direction.DOWN) {
            internalRequests.removeIf(floor -> floor == currentFloor);
        } else {
            externalUpRequests.removeIf(request -> request[0] == currentFloor && request[1] == 1);
            externalDownRequests.removeIf(request -> request[0] == currentFloor && request[1] == 0);
        }
    }
    public void closeDoor() {
        currentState = ElevatorState.CLOSING;
        System.out.println("Close Door");
        currentState = ElevatorState.MOVING;
    }
    public boolean isCurrentDirectionEmpty() {
        /*if (currentDirection == Direction.UP) {
            boolean internalEmpty = true;
            for (int floor : internalRequests) {
                if (floor > currentFloor) {
                    internalEmpty = false;
                    break;
                }
            }
            boolean externalEmpty = true;
            for (int[] request : externalUpRequests) {
                if (request[0] > currentFloor){
                    externalEmpty = false;
                    break;
                }
            }
            return internalEmpty && externalEmpty;
        } else if (currentDirection == Direction.DOWN) {
            boolean internalEmpty = true;
            for (int floor : internalRequests) {
                if (floor < currentFloor) {
                    internalEmpty = false;
                    break;
                }
            }
            boolean externalEmpty = true;
            for (int[] request : externalDownRequests) {
                if (request[0] < currentFloor) {
                    externalEmpty = false;
                    break;
                }
            }
            return internalEmpty && externalEmpty;
        }
        return true;*/
        if (currentDirection == Direction.UP) {
            for (int floor : internalRequests) {
                if (floor > currentFloor) {
                    return false;
                }
            }
            for (int[] request : externalUpRequests) {
                if (request[0] > currentFloor) {
                    return false;
                }
            }
            return true;
        } else if (currentDirection == Direction.DOWN) {
            for (int floor : internalRequests) {
                if (floor < currentFloor) {
                    return false;
                }
            }
            for (int[] request : externalDownRequests) {
                if (request[0] < currentFloor) {
                    return false;
                }
            }
            return true;
        }
        return true;
    }
    public Direction getNextDirection() {
        if (!internalRequests.isEmpty()) {
            int nextFloor = internalRequests.peek();
            return nextFloor > currentFloor ? Direction.UP : Direction.DOWN;
        } else if (!externalUpRequests.isEmpty()) {
            int nextFloor = externalUpRequests.peek()[0];
            return nextFloor > currentFloor ? Direction.UP : Direction.DOWN;
        } else if (!externalDownRequests.isEmpty()) {
            int nextFloor = externalDownRequests.peek()[0];
            return nextFloor > currentFloor ? Direction.UP : Direction.DOWN;
        }
        return Direction.IDLE;
    }
    public boolean hasUpRequestOnCurrentFloor() {
        for (int[] request : externalUpRequests) {
            if (request[0] == currentFloor) {
                return true;
            }
        }
        return false;
    }
    public boolean hasDownRequestOnCurrentFloor() {
        for (int[] request : externalDownRequests) {
            if (request[0] == currentFloor) {
                return true;
            }
        }
        return false;
    }
    public Queue<Integer> getInternalRequests() {
        return internalRequests;
    }
    public Queue<int[]> getExternalRequests() {
        Queue<int[]> allExternalRequests = new LinkedList<>();
        allExternalRequests.addAll(externalUpRequests);
        allExternalRequests.addAll(externalDownRequests);
        return allExternalRequests;
    }
}
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 = ""; //提取出的乘客请求字符串
        ArrayList<String> list = new ArrayList<>(); //用于接收用户输入的数组
        data = input.next();
        while(!data.equalsIgnoreCase("End")){ //输入以“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 = Direction.valueOf(parts[1].trim().toUpperCase());
                elevator.addExternalRequest(floor, direction);//外部请求入队,格式为<楼层数,方向>
            }else{
                if (!request.matches("<\\d+>")) {//内部请求
                    System.out.println("Wrong Format");
                }
                floor = Integer.parseInt(request.replaceAll("[<>]", ""));
                elevator.addInternalRequest(floor);//内部请求入队,格式为<楼层数>
            }
        }
        /*while (!elevator.getInternalRequests().isEmpty()
                 || !elevator.getExternalRequests().isEmpty()){
            elevator.processRequests(); //一次性处理所有的内、外部乘客请求
        }*/
        elevator.processRequests();
        input.close();
    }
}
SourceMontor的生成报表内容如下:

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

2.对于第二次题目集,主要考察类设计之间的关系,其中第一题设计点与线类较为简单,第二题汽车风挡玻璃雨刷问题的类设计难度中等,类与类之间的关系明了但仍需仔细进行设计,第三题的电梯调度问题的迭代仍解决不了,初次编写代码,除了两个枚举类:电梯运行方向和运行状态,还包括主类、电梯类、乘客请求类、队列类以及控制类,具体代码如下:

点击查看代码
import java.util.Scanner;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
enum Direction {
    UP, DOWN, IDLE
}
enum State {
    STOPPED, MOVING
}
class Elevator {
    private int minFloor;
    private 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.IDLE;
        this.state = State.STOPPED;
    }
    public int getMinFloor() {
        return minFloor;
    }
    public int getMaxFloor() {
        return maxFloor;
    }
    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 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 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) {
        if (!internalRequests.contains(floor)) {
            internalRequests.add(floor);
        }
    }
    public void addExternalRequest(int floor, Direction direction) {
        ExternalRequest request = new ExternalRequest(floor, direction);
        if (!externalRequests.contains(request)) {
            externalRequests.add(request);
        }
    }
}
class Controller {
    private Elevator elevator;
    private RequestQueue queue;
    public Controller() {
        
    }
    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() {
        while (!queue.getInternalRequests().isEmpty() || !queue.getExternalRequests().isEmpty()) {
            determineDirection();
            if (elevator.getDirection() == Direction.IDLE) {
                break;
            }
            move();
        }
    }
    private void determineDirection() {
        LinkedList<Integer> internal = queue.getInternalRequests();
        LinkedList<ExternalRequest> external = queue.getExternalRequests();
        if (!internal.isEmpty() || !external.isEmpty()) {
            int nextFloor = getNextFloor();
            if (nextFloor > elevator.getCurrentFloor()) {
                elevator.setDirection(Direction.UP);
            } else {
                elevator.setDirection(Direction.DOWN);
            }
        }  else {
                elevator.setDirection(Direction.IDLE);
            }
    }
    private int getNextFloor() {
        LinkedList<Integer> internal = queue.getInternalRequests();
        LinkedList<ExternalRequest> external = queue.getExternalRequests();
        int nextFloor = Integer.MAX_VALUE;
        if (!internal.isEmpty()) {
            nextFloor = internal.getFirst();
        } else if (!external.isEmpty()) {
            nextFloor = external.getFirst().getFloor();
        }
        for (int floor : internal) {
            nextFloor = getClosest (floor, nextFloor);
        }
        for (ExternalRequest request : external) {
            nextFloor = getClosest (request.getFloor(), nextFloor);
        }
        return nextFloor;
    }
    private int getClosest(int a, int b) {
        int c = elevator.getCurrentFloor();
        if (Math.abs(c - a) < Math.abs(c - b)) {
            return a;
        }
        return b;
    }
    private void move() {
        if (elevator.getCurrentFloor() == 1 && elevator.getDirection() == Direction.UP) {
            System.out.println("Current Floor: 1 Direction: UP");
        }
        elevator.setState(State.MOVING);
        while (true) {
            if (elevator.getDirection() == Direction.UP) {
                elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
            } else {
                elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
            }
            System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
            if (shouldStop(elevator.getCurrentFloor())) {
                openDoors();
                removeRequests(elevator.getCurrentFloor());
                closeDoors();
            }
            if (!hasMoreRequestsInDirection()) {
                break;
            }
        }
        elevator.setState(State.STOPPED);
    }
    private boolean shouldStop(int floor) {
        if (queue.getInternalRequests().contains(floor)) {
            return true;
        }
        for (ExternalRequest request : queue.getExternalRequests()) {
            if (request.getFloor() == floor && request.getDirection() == elevator.getDirection()) {
                return true;
            }
        }
        return false;
    }
    private void openDoors() {
        System.out.println("Open Door # Floor " + elevator.getCurrentFloor());
    }
    private void closeDoors() {
        System.out.println("Close Door");
    }
    private void removeRequests(int currentFloor) {
        /*queue.getInternalRequests().removeIf(floor -> floor == currentFloor);
        queue.getExternalRequests().removeIf(request -> request.getFloor() == currentFloor && request.getDirection() == elevator.getDirection());*/
        LinkedList<ExternalRequest> request = queue.getExternalRequests();
        if (queue.getInternalRequests().contains(currentFloor) && request.getFloor().contains(currentFloor)) {
            queue.getExternalRequests().removeIf(request -> request.getFloor() == currentFloor && request.getDirection() == elevator.getDirection());
        } else {
            queue.getInternalRequests().removeIf(floor -> floor == currentFloor);
        }
    }
    private boolean hasMoreRequestsInDirection() {
        if (elevator.getDirection() == Direction.UP) {
            for (int floor : queue.getInternalRequests()) {
                if (floor > elevator.getCurrentFloor()) {
                    return true;
                }
            }
            for (ExternalRequest request : queue.getExternalRequests()) {
                if (request.getFloor() > elevator.getCurrentFloor() && request.getDirection() == Direction.UP) {
                    return true;
                }
            }
        } else if (elevator.getDirection() == Direction.DOWN) {
            for (int floor : queue.getInternalRequests()) {
                if (floor < elevator.getCurrentFloor()) {
                    return true;
                }
            }
            for (ExternalRequest request : queue.getExternalRequests()) {
                if (request.getFloor() < elevator.getCurrentFloor() && request.getDirection() == Direction.DOWN) {
                    return true;
                }
            }
        }
        return false;
    }
}
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 = ""; //提取出的乘客请求字符串
        ArrayList<String> list = new ArrayList<>(); //用于接收用户输入的数组
        data = input.next();
        while(!data.equalsIgnoreCase("End")){ //输入以“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();
        Controller controller = new Controller(elevator, queue);
        for(int i = 2; i < list.size(); i++){//从第三行开始为乘客请求
            request = list.get(i);
            if(request.contains(",")){//外部请求
                if (!request.matches("<\\d+,\\s*(UP|DOWN)>")) {
                    System.out.println("Wrong Format");
                }
                String[] parts = request.replaceAll("[<>]", "").split(",");
                floor = Integer.parseInt(parts[0].trim());
                direction = Direction.valueOf(parts[1].trim().toUpperCase());
                queue.addExternalRequest(floor, direction);//外部请求入队,格式为<楼层数,方向>
            }else{
                if (!request.matches("<\\d+>")) {//内部请求
                    System.out.println("Wrong Format");
                }
                floor = Integer.parseInt(request.replaceAll("[<>]", ""));
                queue.addInternalRequest(floor);//内部请求入队,格式为<楼层数>
            }
        }
        /*while (!elevator.getInternalRequests().isEmpty()
                 || !elevator.getExternalRequests().isEmpty()){
            elevator.processRequests(); //一次性处理所有的内、外部乘客请求
        }*/
        controller.processRequests();
        input.close();
    }
}
SourceMontor的生成报表内容如下:

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

3.对于第三次题目集,销售步枪问题较为简单,只需简单理解便能编程解决问题,蒙特卡罗方法求圆周率要多加理解才能理解题目意思,其中类设计时更加巧妙,也不难解决,而电梯调度问题的第二次迭代核心仍在于算法处理上,对于类设计多加留心便可符合题目要求,初次编程时,在之前电梯调度问题设计了电梯类、乘客类、队列类以及控制类,具体代码如下:

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

enum Direction {
    UP, DOWN, IDLE
}
enum State {
    MOVING, STOPPED
}
class Elevator {
    private int currentFloor;
    private Direction direction;
    private State state;
    private int minFloor;
    private int maxFloor;
    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) {
        return (floor >= minFloor && floor <= maxFloor);
    }
}
class Passenger {
    private Integer sourceFloor = null;
    private Integer destinationFloor = null;
    public Passenger() {
        
    }
    public Passenger(Integer sourceFloor, Integer destinationFloor) {
        this.sourceFloor = sourceFloor;
        this.destinationFloor = destinationFloor;
    }
    public Integer getSourceFloor() {
        return sourceFloor;
    }
    public void setSourceFloor(Integer sourceFloor) {
        this.sourceFloor = sourceFloor;
    }
    public Integer getDestinationFloor() {
        return destinationFloor;
    }
    public void setDestinationFloor(Integer destinationFloor) {
        this.destinationFloor = destinationFloor;
    }
    public Direction getDirection() {
        if (sourceFloor == null || destinationFloor == null) {
            return Direction.IDLE;
        }
        if (sourceFloor < destinationFloor) {
            return Direction.UP;
        } else if (sourceFloor > destinationFloor) {
            return Direction.DOWN;
        } else {
            return Direction.IDLE;
        }
    }
}
class RequestQueue {
    private LinkedList<Passenger> internalRequests = new LinkedList<>();
    private LinkedList<Passenger> externalRequests = new LinkedList<>();
    public RequestQueue() {
        
    }
    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);
    }
}
class Controller {
    private Elevator elevator;
    private RequestQueue queue;
    public Controller() {
        
    }
    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() {
        while (!queue.getInternalRequests().isEmpty() || !queue.getExternalRequests().isEmpty()) {
            determineDirection();
            int nextFloor = getNextFloor();
            while (elevator.getCurrentFloor() != nextFloor) {
                int current = elevator.getCurrentFloor();
                elevator.setCurrentFloor(current + (elevator.getDirection() == Direction.UP ? 1 : -1));
                System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
                if (shouldStop(elevator.getCurrentFloor())) {
                    openDoors(elevator.getCurrentFloor());
                }
            }
            if (shouldStop(elevator.getCurrentFloor())) {
                openDoors(elevator.getCurrentFloor());
            }
        }
    }
    private void determineDirection() {
        if (elevator.getDirection() == Direction.IDLE) {
            if (!queue.getInternalRequests().isEmpty()) {
                Passenger firstInternal = queue.getInternalRequests().getFirst();
                elevator.setDirection(elevator.getCurrentFloor() < firstInternal.getDestinationFloor() ? Direction.UP : Direction.DOWN);
            } else if (!queue.getExternalRequests().isEmpty()) {
                Passenger firstExternal = queue.getExternalRequests().getFirst();
                elevator.setDirection(elevator.getCurrentFloor() < firstExternal.getSourceFloor() ? Direction.UP : Direction.DOWN);
            }
        }
    }
    private void move() {
        int current = elevator.getCurrentFloor();
        if (elevator.getDirection() == Direction.UP) {
            elevator.setCurrentFloor(current + 1);
        } else if (elevator.getDirection() == Direction.DOWN) {
            elevator.setCurrentFloor(current - 1);
        }
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
    }
    private boolean shouldStop(int floor) {
        for (Passenger p : queue.getInternalRequests()) {
            if (p.getDestinationFloor() == floor) {
                return true;
            }
        }
        for (Passenger p : queue.getExternalRequests()) {
            if (p.getSourceFloor() == floor && elevator.getDirection() == p.getDirection()) {
                return true;
            }
        }
        return false;
    }
    private int getNextFloor() {
        if (elevator.getDirection() == Direction.UP) {
            int max = elevator.getMaxFloor();
            for (int i = elevator.getCurrentFloor() + 1; i <= max; i++) {
                if (shouldStop(i)) {
                    return i;
                }
            }
            return max;
        } else {
            int min = elevator.getMinFloor();
            for (int i = elevator.getCurrentFloor() - 1; i >= min; i--) {
                if (shouldStop(i)) {
                    return i;
                }
            }
            return min;
        }
    }
    private int getClosest(Integer a, Integer b) {
        if (a == null) return b;
        if (b == null) return a;
        int current = elevator.getCurrentFloor();
        int distA = Math.abs(current - a);
        int distB = Math.abs(current - b);
        return distA <= distB ? a : b;
    }
    private void openDoors(int floor) {
        System.out.println("Open Door # Floor " + floor);
        System.out.println("Close Door");
        removeRequests(floor);
    }
    private void removeRequests(int floor) {
        queue.getInternalRequests().removeIf(p -> p.getDestinationFloor() == floor);
        queue.getExternalRequests().removeIf(p -> {
            if (p.getSourceFloor() == floor) {
                queue.addInternalRequest(new Passenger(null, p.getDestinationFloor()));
                return true;
            }
            return false;
        });
    }
}
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 (scanner.hasNextLine()) {
            String input = scanner.nextLine().trim();
            if (input.equalsIgnoreCase("end")) {
                break;
            }
            if (input.startsWith("<")) {
                input = input.substring(1, input.length() - 1);
                if (input.contains(",")) {
                    String[] parts = input.split(",");
                    int source = Integer.parseInt(parts[0]);
                    int dest = Integer.parseInt(parts[1]);
                    queue.addExternalRequest(new Passenger(source, dest));
                } else {
                    int floor = Integer.parseInt(input);
                    queue.addInternalRequest(new Passenger(null, floor));
                }
            }
        }
        controller.processRequests();
    }
}

SourceMontor的生成报表内容如下:

分析:
对于电梯调度问题的第二次迭代,
(1)电梯运行规则与前阶段相同,但有如下变动情况:
乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)
(2)加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类,具体设计可参考如下类图。

三、踩坑心得
在代码提交过程中,遇到的问题主要有编译错误,答案错误和运行超时。
1.编译错误:
(1)枚举作用域错误
错误:cannot find symbol class Direction
原因:Direction枚举未定义为公共类。
解决方法:将枚举类声明为public。
(2)构造函数私有
错误:Elevator(int,int) has private access
原因:误将Elevator类的构造函数声明为private,导致外部无法实例化。
解决方法:将构造函数改为public。
(3)拼写错误
错误:cannot find symbol variable elevtor
原因:参数拼写错误,将elevator写为elevtor。
解决方法:编程时要多加细心。
2.答案错误
编译无误之后,测试用例如下:
1
20
< 3,UP >
<5>
< 6,DOWN >
<7>
<3>
end
发现运行结果从7楼下来之后只会停在6楼,不会继续下降至3楼,原因是在移除请求方法时,当电梯上升至3楼,会同时将外部的3楼请求与内部的3楼请求一起移除,导致请求缺失,并且三次题目集都未解决这个问题。
3.逻辑错误
在想到2中的错误原因后,对移除请求的方法做了修改,对内部请求移除和外部请求移除的条件加以特定条件限制,结果运行显示运行超时,且三次题目集都未解决这个问题。

四、改进建议
1.在编程之前,先理清类与类之间的关系,做好类设计,如何再分别对每个类进行编程,最终考虑好类之间的调用关系,使完整的代码逻辑合理。
2.编程时要多加仔细,避免犯拼写错误,声明属性错误,变量名或方法名定义错误等低级错误。
3.要提高编程能力,提升解决复杂问题的思维能力,避免在面对稍微复杂的问题时毫无头绪或手足无措。

五、总结
通过三次题目集的训练,我学会了在编程中使用正则表达式来提高编程效率,加深了对类与类间关系的理解,并能在编程中体现出来,同时也学会根据所给类图进行编程。而在处理复杂问题的方面上还有欠缺,需要进一步学习编写复杂的算法来解决实际生活中的问题。对作业的建议,不用使主要难题所占的分数太大,一次题目集的分数应合理分配。

posted @ 2025-04-20 18:21  憾长存  阅读(35)  评论(0)    收藏  举报