我的第一次博客作业

一:前言:
学习Java语言也快三个月了,就在我认为还可以像对付C语言那样处理Java课时,三次大题量的电梯类题目却直接将我“击破”,从此刻开始我才认识到两种语言学习的不同,我需要更多的信心与练习。在这三次作业里,每个题目不同的类的设计与方法的处理都十分考验我们的编程能力。从此,编程世界的另一扇大门已缓缓开启,正等待着我们逐步探索..

二:代码设计与分析:
--第五次作业:

点击查看代码
import java.util.Scanner;
class Elevator {
    private int minFloor;
    private int maxFloor;
    private int currentFloor;
    private String direction;
    private String state;
    private Queue<Integer> internalRequests;
    private Map<Integer, List<String>> externalUpRequests;
    private Map<Integer, List<String>> externalDownRequests;

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.direction = "STILL";
        this.state = "STOP";
        this.internalRequests = new PriorityQueue<>();
        this.externalUpRequests = new HashMap<>();
        this.externalDownRequests = new HashMap<>();
    }

    public void addInternalRequest(int floor) {
        if (isValidFloor(floor)) {
            internalRequests.add(floor);
        } else {
            System.out.println("无效的楼层请求: " + floor);
        }
    }
    private boolean isValidFloor(int floor) {
        return floor >= minFloor && floor <= maxFloor;
    }

    public void run() {
        while (!internalRequests.isEmpty() || !externalUpRequests.isEmpty() || !externalDownRequests.isEmpty()) {
            if (direction.equals("STILL")) {
                if (!internalRequests.isEmpty()) {
                    direction = internalRequests.peek() > currentFloor ? "UP" : "DOWN";
                } else if (!externalUpRequests.isEmpty()) {
                    int nextUpFloor = Collections.min(externalUpRequests.keySet());
                    direction = nextUpFloor > currentFloor ? "UP" : "DOWN";
                } else if (!externalDownRequests.isEmpty()) {
                    int nextDownFloor = Collections.max(externalDownRequests.keySet());
                    direction = nextDownFloor > currentFloor ? "UP" : "DOWN";
                }
            }
            state = "MOVING";
            if (direction.equals("UP")) {
                while (currentFloor < maxFloor) {
                    currentFloor++;
                    printCurrentFloor();
                    if (shouldStop()) {
                        stopAndHandleRequests();
                    }
                    if (internalRequests.isEmpty() && externalUpRequests.isEmpty()) {
                        direction = "DOWN";
                        break;
                    }
                }
            } else if (direction.equals("DOWN")) {
                while (currentFloor > minFloor) {
                    currentFloor--;
                    printCurrentFloor();
                    if (shouldStop()) {
                        stopAndHandleRequests();
                    }
                    if (internalRequests.isEmpty() && externalDownRequests.isEmpty()) {
                        direction = "UP";
                        break;
                    }
                }
            }
        }
        state = "STOP";
        direction = "STILL";
    }
    private void printCurrentFloor() {
        System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
    }
    private boolean shouldStop() {
        return internalRequests.contains(currentFloor) || externalUpRequests.containsKey(currentFloor) || externalDownRequests.containsKey(currentFloor);
    }
    private void stopAndHandleRequests() {
        state = "OPENING";
        System.out.println("Open Door # Floor " + currentFloor);
        internalRequests.remove(currentFloor);
        externalUpRequests.remove(currentFloor);
        externalDownRequests.remove(currentFloor);
        state = "CLOSING";
        System.out.println("Close Door");
    }
}
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);
        String input;
        while (!(input = scanner.nextLine().trim()).equalsIgnoreCase("end")) {
            if (input.startsWith("<") && input.endsWith(">")) {
                input = input.substring(1, input.length() - 1);
                if (input.contains(",")) {
                    String[] parts = input.split(",");
                    int floor = Integer.parseInt(parts[0]);
                    String direction = parts[1];
                    elevator.addExternalRequest(floor, direction);
                } else {
                    int floor = Integer.parseInt(input);
                    elevator.addInternalRequest(floor);
                }
            }
        }

        elevator.run();
    }
}    

在我的代码里,我先创建了 Elevator 类,定义了电梯的最小、最大和当前楼层等属性,还设置了存储内外部请求的队列和映射。addInternalRequest 方法用于添加内部请求,会检查楼层有效性。run 方法处理请求,根据请求确定方向,运行中更新楼层、判断是否停止。shouldStop 和 stopAndHandleRequests 方法分别用于判断停梯和处理请求。在 Main 类的 main 方法中,我从用户输入获取楼层信息创建电梯对象,根据输入添加请求,输入 end 后启动电梯运行,处理完请求后电梯停止并输出轨迹。
类图:![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420203902594-155645704.png)
复杂度分析:![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420203935014-1253213672.png) ![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420203948501-1666704469.png).
以下是对图片内容的解读:
行数:118 行
语句数:88 条
分支语句百分比:21.6%
方法调用语句数:50 条
注释行百分比:0.0% ,代码无任何注释
类和接口数量:2 个
每个类的平均方法数:4.00 个
每个方法的平均语句数):11.64 条
最复杂方法的行号:Elevator.run() ,位于 34 行
最大复杂度为21,方法是Elevator.run()
平均复杂度:4.75
最深代码块行号:53 行
最大代码块深度为 6
平均代码块深度:2.84
----以下是对我代码的总结分析:
①我注意到自己在代码注释方面严重缺失,注释行百分比为 0.0 。这使得代码就像一本没有目录和注解的随手。②,整体代码的语句较多,复杂度残次不齐,调用较为混乱。尤其Elevator.run() 方法的最大复杂度达到了 21 ,远远超出合理范围,而且此方法承担了太多职责,可维护性与扩展性大打折扣。③仅有 2 个类和接口,分支逻辑较为复杂,容易遗漏边界条件。④最大代码块深度为 6 ,平均代码块深度也有 2.84,说明代码中存在大量的嵌套结构,例如循环中嵌套条件判断,条件判断中又嵌套其他逻辑等。这种深层嵌套使得代码缩进过多,视觉上难以快速定位和理解逻辑关系,也增加了出错的概率。 这次作业让我明白:不能只局限于简单的代码操作,对更多需求、类的分析才能不断增强我的编程能力。
**--第六次作业:**
点击查看代码
import java.util.Scanner;
class Elevator {
    private int minFloor;
    private int maxFloor;
    private int currentFloor;
    private String direction;
    private String state;
    private Queue<Integer> internalRequests;
    private Map<Integer, List<String>> externalUpRequests;
    private Map<Integer, List<String>> externalDownRequests;

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.direction = "STILL";
        this.state = "STOP";
        this.internalRequests = new PriorityQueue<>();
        this.externalUpRequests = new HashMap<>();
        this.externalDownRequests = new HashMap<>();
    }
    private boolean isValidFloor(int floor) {
        return floor >= minFloor && floor <= maxFloor;
    }

    public void run() {
        while (!internalRequests.isEmpty() || !externalUpRequests.isEmpty() || !externalDownRequests.isEmpty()) {
            if (direction.equals("STILL")) {
                if (!internalRequests.isEmpty()) {
                    direction = internalRequests.peek() > currentFloor ? "UP" : "DOWN";
                } else if (!externalUpRequests.isEmpty()) {
                    int nextUpFloor = Collections.min(externalUpRequests.keySet());
                    direction = nextUpFloor > currentFloor ? "UP" : "DOWN";
                } else if (!externalDownRequests.isEmpty()) {
                    int nextDownFloor = Collections.max(externalDownRequests.keySet());
                    direction = nextDownFloor > currentFloor ? "UP" : "DOWN";
                }
            }
            state = "MOVING";
            if (direction.equals("UP")) {
                while (currentFloor < maxFloor) {
                    currentFloor++;
                    printCurrentFloor();
                    if (shouldStop()) {
                        stopAndHandleRequests();
                    }
                    if (internalRequests.isEmpty() && externalUpRequests.isEmpty()) {
                        direction = "DOWN";
                        break;
                    }
                }
            } else if (direction.equals("DOWN")) {
                while (currentFloor > minFloor) {
                    currentFloor--;
                    printCurrentFloor();
                    if (shouldStop()) {
                        stopAndHandleRequests();
                    }
                    if (internalRequests.isEmpty() && externalDownRequests.isEmpty()) {
                        direction = "UP";
                        break;
                    }
                }
            }
        }
        state = "STOP";
        direction = "STILL";
    }
    private void printCurrentFloor() {
        System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
    }
    private boolean shouldStop() {
        return internalRequests.contains(currentFloor) || externalUpRequests.containsKey(currentFloor) || externalDownRequests.containsKey(currentFloor);
    }
    private void stopAndHandleRequests() {
        state = "OPENING";
        System.out.println("Open Door # Floor " + currentFloor);
        internalRequests.remove(currentFloor);
        externalUpRequests.remove(currentFloor);
        externalDownRequests.remove(currentFloor);
        state = "CLOSING";
        System.out.println("Close Door");
    }
}
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);
        String input;
        while (!(input = scanner.nextLine().trim()).equalsIgnoreCase("end")) {
            if (input.startsWith("<") && input.endsWith(">")) {
                input = input.substring(1, input.length() - 1);
                if (input.contains(",")) {
                    String[] parts = input.split(",");
                    int floor = Integer.parseInt(parts[0]);
                    String direction = parts[1];
                    elevator.addExternalRequest(floor, direction);
                } else {
                    int floor = Integer.parseInt(input);
                    elevator.addInternalRequest(floor);
                }
            }
        }
        elevator.run();
    }
}    

在我的代码里,我仍然先创建 Elevator 类,定义了电梯的最小、最大和当前楼层等属性,以及存储内外部请求的队列与映射。虽未完整实现,但 addInternalRequest 应可添加内部请求并检查楼层有效性。run 方法是核心,会持续处理请求,根据情况确定电梯运行方向,运行中更新楼层并判断是否停止。shouldStop 用于判断是否停梯,stopAndHandleRequests 处理停梯操作。在 Main 类的 main 方法中,我从用户输入获取楼层信息创建电梯对象,根据输入添加请求。输入 end 后,启动电梯运行,处理完请求电梯停止并输出轨迹。
类图:![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420221157622-1865622476.png)
复杂度分析:![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420221648078-912448568.png) ![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420221702146-1915990186.png)
以下是对图片内容的解读:
行数: 109行
语句数: 83条
分支语句百分比:20.5%
方法调用语句数:47 条
注释行百分比:0.0% ,代码无任何注释
类和接口数量:2个
每个类的平均方法数: 3.50个
每个方法的平均语句数: 9.29条
最复杂方法的行号:26,Elevator.run()
最大复杂度为21,方法也是Elevator.run()
平均复杂度:5.00
最深代码块行号:行
最大代码块深度为 :6
平均代码块深度:2.88
这次代码的不足:
①同样的,这次代码也没有用任何注释,可读性不高。②最大代码块深度为 6,平均代码块深度为 2.88 。不仅使代码缩进过多,视觉上难以理解,还容易在逻辑判断时出错,影响代码的正确性和可维护性。③整体方法调用语句数有 47 条,方法间调用频繁。虽体现了模块化,但可能存在不必要的调用或调用层次过深,导致代码结构混乱,难以理清方法间的依赖关系和执行顺序。 综上,出现的问题很多在第五次题目集中也出现了,代表我对题目的理解仍然不到位,代码没有明显改进。在这方面还有待提高。
**第七次题目:**
点击查看代码
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 乘客类
class Passenger {
    private int sourceFloor;
    private int destinationFloor;

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

    public int getSourceFloor() {
        return sourceFloor;
    }

    public int getDestinationFloor() {
        return destinationFloor;
    }
}

// 队列类
class Queue {
    private List<Integer> internalQueue;
    private List<Passenger> externalQueue;

    public Queue() {
        internalQueue = new ArrayList<>();
        externalQueue = new ArrayList<>();
    }

    public boolean isExternalQueueEmpty() {
        return externalQueue.isEmpty();
    }

    public boolean isInternalQueueEmpty() {
        return internalQueue.isEmpty();
    }

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

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

    public Passenger getNextExternalPassenger() {
        return externalQueue.get(0);
    }

    public Passenger removeNextExternalPassenger() {
        return externalQueue.remove(0);
    }

    public List<Integer> getInternalQueue() {
        return internalQueue;
    }
}

// 电梯类
class Elevator {
    private int minFloor;
    private int maxFloor;
    private int currentFloor;
    private String direction;
    private Queue queue;

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.direction = "UP";
        this.queue = new Queue();
    }

    public void addExternalRequest(Passenger passenger) {
        queue.addExternalRequest(passenger);
    }

    public void addInternalRequest(int floor) {
        queue.addInternalRequest(floor);
    }

    public void processRequests() {
        while (!queue.isExternalQueueEmpty() || !queue.isInternalQueueEmpty()) {
            int nextFloor;
            if (queue.isExternalQueueEmpty()) {
                nextFloor = getNextInternalFloor();
            } else {
                Passenger nextPassenger = queue.getNextExternalPassenger();
                nextFloor = nextPassenger.getSourceFloor();
            }

            while (currentFloor != nextFloor) {
                if (currentFloor < nextFloor) {
                    currentFloor++;
                    direction = "UP";
                } else {
                    currentFloor--;
                    direction = "DOWN";
                }
                System.out.println("Current Floor: " + currentFloor + " Direction: " + direction);
            }

            if (!queue.isExternalQueueEmpty() && queue.getNextExternalPassenger().getSourceFloor() == currentFloor) {
                Passenger passenger = queue.removeNextExternalPassenger();
                System.out.println("Open Door # Floor " + currentFloor);
                System.out.println("Close Door");
                addInternalRequest(passenger.getDestinationFloor());
            }

            if (queue.getInternalQueue().contains(currentFloor)) {
                System.out.println("Open Door # Floor " + currentFloor);
                System.out.println("Close Door");
                queue.getInternalQueue().remove((Integer) currentFloor);
            }
        }
    }

    private int getNextInternalFloor() {
        if (direction.equals("DOWN")) {
            int min = Integer.MAX_VALUE;
            for (int floor : queue.getInternalQueue()) {
                if (floor < min) {
                    min = floor;
                }
            }
            return min;
        } else {
            int max = Integer.MIN_VALUE;
            for (int floor : queue.getInternalQueue()) {
                if (floor > max) {
                    max = floor;
                }
            }
            return max;
        }
    }
}

// 控制类
class ElevatorController {
    private Elevator elevator;

    public ElevatorController(int minFloor, int maxFloor) {
        this.elevator = new Elevator(minFloor, maxFloor);
    }

    public void processInput() {
        Scanner scanner = new Scanner(System.in);
        int minFloor = scanner.nextInt();
        int maxFloor = scanner.nextInt();
        scanner.nextLine(); // 消耗掉换行符

        while (true) {
            String request = scanner.nextLine().trim();
            if (request.equalsIgnoreCase("end")) {
                break;
            }
            if (request.startsWith("<") && request.endsWith(">")) {
                request = request.substring(1, request.length() - 1);
                if (request.contains(",")) {
                    String[] parts = request.split(",");
                    int sourceFloor = Integer.parseInt(parts[0]);
                    int destinationFloor = Integer.parseInt(parts[1]);
                    Passenger passenger = new Passenger(sourceFloor, destinationFloor);
                    elevator.addExternalRequest(passenger);
                } else {
                    int floor = Integer.parseInt(request);
                    elevator.addInternalRequest(floor);
                }
            }
        }
        elevator.processRequests();
        scanner.close();
    }
}

// 主类
public class ElevatorScheduling {
    public static void main(String[] args) {
        ElevatorController controller = new ElevatorController(1, 20);
        controller.processInput();
    }
}    
. 此代码的基本类设计与前面相同,仍然先创建 Elevator 类,定义了电梯的最小、最大和当前楼层等属性,以及存储内外部请求的队列与映射。而在请求管理方面,我设置了存储内外部请求的数据结构。对于内部请求,我使用了 internalRequests 这个优先队列来存储。优先队列的好处就在于它能自动对请求进行排序,这样在处理请求时,我可以更高效地根据请求的优先级来安排电梯的运行顺序,就像给电梯安排了一个智能的任务清单。对于外部请求,我分别用 externalUpRequests 和 externalDownRequests 这两个映射来区分上行和下行请求。这样做的好处是非常明显的,当有乘客在不同楼层发出上行或下行的请求时,我可以清晰地将这些请求分类管理。就好比把不同方向的乘客请求分别放进了不同的 “盒子” 里,需要处理的时候能快速找到对应的请求,大大提高了请求管理的效率和准确性。通过这样的设计,我能更清晰、更有条理地对电梯的各种请求进行管理和处理。
类图:![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420224000524-805551621.png)
复杂度分析:![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420224519538-901972779.png) ![](https://img2024.cnblogs.com/blog/3638191/202504/3638191-20250420224544113-1764374535.png)

图片内容解读如下:
行数: 190行
语句数: 113条
分支语句百分比:17.7%
方法调用语句数:49 条
注释行百分比:3.2%
类和接口数量:1个
每个类的平均方法数: 19.00个
每个方法的平均语句数: 5.63条
最复杂方法的行号:181, Main.main()
最大复杂度为1,方法也是Main.main()
平均复杂度:1
最深代码块行号:98行
最大代码块深度为 :4
平均代码块深度:1.54
在这次的题目里,我添加了适量的注释,以保证最基本的可读性。内部请求用优先队列、外部请求用映射区分上下行,能高效处理不同类型请求,提升电梯调度效率。但还是有一些不足的地方:①电梯调度策略相对简单,未考虑如高峰时段调度、多电梯协同等复杂场景;代码中一些固定参数(如楼层范围在主函数硬编码),不利于灵活调整和扩展功能。②单个类方法数过多(每个类平均 19 个方法 ),可能导致类职责不够单一,影响代码可维护性与复用性。
三--踩坑心得
开发电梯调度程序时,我收获不少经验教训。起初,代码结构设计虽有一定条理,按功能分了类,可实际操作才发现注释太少,后期回看代码,好多逻辑都得重新梳理,理解成本大增。输入处理这块也掉坑里了,没做异常处理,根本没考虑用户输错数据咋办,程序一下就崩了。还有,以为简单的调度策略够用,结果发现应对不了复杂场景,比如早晚高峰。另外,方法数量在类里分布不合理,一个类塞太多方法,职责混乱。这次经历让我明白,写代码不能只图功能实现,注释、健壮性、扩展性这些都得兼顾,才能编出高质量的程序。
例图:
四--总结:
本次开发的电梯调度程序,通过 Java 语言实现了基本的电梯调度功能。代码整体采用面向对象设计,将不同功能封装在不同类中,如 Passenger 类存储乘客信息,Elevator 类负责电梯运行逻辑,ElevatorController 类处理用户输入,结构较为清晰,便于维护和扩展。
然而,代码仍存在一些不足之处,需要进一步学习和研究。首先,注释过少,这严重影响了代码的可读性和可维护性。后续需要养成良好的注释习惯,详细解释关键逻辑和方法的用途。其次,异常处理方面存在缺失,程序在面对非法输入或运行时异常时较为脆弱。应学习如何完善异常处理机制,增强程序的健壮性。
在扩展性上,当前的调度策略较为简单,难以应对复杂的实际场景,如多电梯协同调度、高峰时段优化等。这需要深入研究更高级的算法和策略,以优化电梯调度效率。此外,代码的复杂度分布不均衡,单个类中的方法数量过多,经常违反单一职责原则。需要进一步学习设计模式,合理拆分功能,使代码结构更加合理。
总体而言,本次开发是一次宝贵的实践经验,通过不断学习和改进,有望使程序更加完善和实用。
同时希望老师上课的方式可以更生动些,实验要求可以简洁些。

posted @ 2025-04-20 23:24  夏守航24201229  阅读(12)  评论(0)    收藏  举报