题目集5~7总结blog

一、前言

总得来说这三次的题目集 特别是三次电梯题目,对我来说就是一个感觉那就是困难,我也不怕老师瞧不起我,我可以诚实的告诉老师,我一次电梯题目都没有拿过满分,这几次的题目集都是每次做完电梯题目之前的题目后我都会小有成就感,但是每当看到电梯题目又成功的浇灭了我来之不易的一点小小的成就感,虽然说这几次的电梯题目非常困难,但也培养了我的逻辑思维和抽象思维、现在我就来总结一下这几次的题目集

1.第五次题目集:题目包括身份证的校验、求解一元二次方程、和利用正则表达式校验验证码、最后就是电梯题目,这次的电梯题目主要是实现单部电梯的基本调度问题,需要我们整理出初步的电梯运行逻辑,主要考察类的基本设计、队列管理和简单调度算法。

2.第六次题目集:题目包括点与线求点之间的距离、雨刷器调档问题、和电梯题目的迭代升级,此次的电梯题目相比于去第一次中的Elevator类,此次要求我们将一个类的功能拆分成多个类来实现,并增加了增加了输入验证和去重功能。主要考察对于不同类的调用能力。

3.第七次题目集:题目包括销售步枪问题、求圆周率问题、和电梯题目的再一次迭代升级,此次电梯题目增加的Passenger类,完善修改了外部请求功能,使逻辑关系变得更加精密,但是也更难以实现。

设计与分析

第五次电梯:

这是电梯题目的类图关系:

当我第一次看到这个类图关系,着实被下了一大跳,这么难的题目居然要我这个大一的学生来写,不过现在看来,一步一步的去解决也能做到,虽然我没有得到满分但是我相信我能够做到,

这是我的电梯题目的源码:

import java.util.LinkedList;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.regex.Pattern;

enum Direction {
    UP, DOWN
}

enum State {
    MOVING, STOPPED
}

class ExternalRequest {
    private int floor;
    private Direction direction;

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

    public int getFloor() {
        return floor;
    }

    public Direction getDirection() {
        return direction;
    }
}

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

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

    public void addExternalRequest(ExternalRequest request) {
        externalRequests.add(request);
    }

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

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

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

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

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

class Elevator {
    private int currentFloor;
    private Direction direction = Direction.UP; // 初始方向默认为UP
    private State state = State.STOPPED;
    private final int maxFloor;
    private final int minFloor;
    private final RequestQueue requestQueue;

    public Elevator(int minFloor, int maxFloor) {
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
        this.currentFloor = minFloor;
        this.requestQueue = new RequestQueue();
    }

    // Getters and setters
    public RequestQueue getRequestQueue() { return requestQueue; }
    public int getCurrentFloor() { return currentFloor; }
    public void setCurrentFloor(int floor) { currentFloor = floor; }
    public Direction getDirection() { return direction; }
    public void setDirection(Direction dir) { direction = dir; }
    public State getState() { return state; }
    public void setState(State s) { state = s; }

    public void addExternalRequest(int floor, Direction direction) {
        if (floor >= minFloor && floor <= maxFloor) {
            requestQueue.addExternalRequest(new ExternalRequest(floor, direction));
        }
    }

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

class Controller {
    private final Elevator elevator;

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

    public void processRequests() {
        // 输出初始状态
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
        boolean initialDirectionSet = false;

        while (elevator.getRequestQueue().hasRequests()) {
            determineDirection(initialDirectionSet);
            move();
            initialDirectionSet = true;
        }
    }

    private void determineDirection(boolean initialDirectionSet) {
        if (elevator.getState() == State.STOPPED && !initialDirectionSet) {
            RequestQueue queue = elevator.getRequestQueue();
            int current = elevator.getCurrentFloor();

            if (!queue.getInternalRequests().isEmpty()) {
                int firstInternalRequest = queue.getInternalRequests().get(0);
                elevator.setDirection(firstInternalRequest > current ? Direction.UP : Direction.DOWN);
            } else if (!queue.getExternalRequests().isEmpty()) {
                ExternalRequest firstExternalRequest = queue.getExternalRequests().get(0);
                elevator.setDirection(firstExternalRequest.getDirection());
            }
        } else if (elevator.getState() == State.STOPPED) {
            RequestQueue queue = elevator.getRequestQueue();
            int current = elevator.getCurrentFloor();
            
            boolean hasUp = queue.getInternalRequests().stream().anyMatch(f -> f > current) ||
                          queue.getExternalRequests().stream().anyMatch(req -> 
                              req.getFloor() > current || 
                              (req.getFloor() == current && req.getDirection() == Direction.UP));

            boolean hasDown = queue.getInternalRequests().stream().anyMatch(f -> f < current) ||
                            queue.getExternalRequests().stream().anyMatch(req -> 
                                req.getFloor() < current || 
                                (req.getFloor() == current && req.getDirection() == Direction.DOWN));

            switch (elevator.getDirection()) {
                case UP:
                    if (!hasUp && hasDown) elevator.setDirection(Direction.DOWN);
                    break;
                case DOWN:
                    if (!hasDown && hasUp) elevator.setDirection(Direction.UP);
                    break;
            }
        }
    }

    private void move() {
        Direction dir = elevator.getDirection();
        if (dir == Direction.UP) {
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        } else if (dir == Direction.DOWN) {
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
        } else {
            return;
        }

        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + dir);

        if (shouldStop()) {
            handleStop();
        } else {
            elevator.setState(State.MOVING);
        }
    }

    private boolean shouldStop() {
        int current = elevator.getCurrentFloor();
        RequestQueue queue = elevator.getRequestQueue();
        
        boolean internalStop = queue.getInternalRequests().contains(current);
        boolean externalStop = queue.getExternalRequests().stream().anyMatch(req -> 
            req.getFloor() == current && (
                req.getDirection() == elevator.getDirection() ||
                shouldHandleOppositeDirection(req)
            )
        );
        
        return internalStop || externalStop;
    }

    private boolean shouldHandleOppositeDirection(ExternalRequest req) {
        Direction currentDir = elevator.getDirection();
        if (currentDir == Direction.UP) {
            return req.getDirection() == Direction.DOWN && 
                   !hasRequests(req.getFloor(), Direction.UP);
        }
        if (currentDir == Direction.DOWN) {
            return req.getDirection() == Direction.UP && 
                   !hasRequests(req.getFloor(), Direction.DOWN);
        }
        return false;
    }

    private boolean hasRequests(int floor, Direction dir) {
        return elevator.getRequestQueue().getInternalRequests().stream().anyMatch(f -> 
            dir == Direction.UP ? f > floor : f < floor
        ) || elevator.getRequestQueue().getExternalRequests().stream().anyMatch(req -> 
            dir == Direction.UP ? req.getFloor() > floor : req.getFloor() < floor
        );
    }

    private void handleStop() {
        int current = elevator.getCurrentFloor();
        System.out.println("Open Door # Floor " + current);
        elevator.getRequestQueue().removeInternalRequest(current);
        elevator.getRequestQueue().removeExternalRequest(current);
        System.out.println("Close Door");
        elevator.setState(State.STOPPED);
    }
}

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

        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (line.equalsIgnoreCase("end")) break;
            inputs.add(line);
        }

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

        try {
            int min = Integer.parseInt(inputs.get(0));
            int max = Integer.parseInt(inputs.get(1));
            if (min >= max) {
                System.out.println("Wrong Format");
                return;
            }

            Elevator elevator = new Elevator(min, max);
            Controller controller = new Controller(elevator);

            Pattern externalPattern = Pattern.compile("<\\d+,\\s*(UP|DOWN)>", Pattern.CASE_INSENSITIVE);
            Pattern internalPattern = Pattern.compile("<\\d+>");

            for (int i = 2; i < inputs.size(); i++) {
                String req = inputs.get(i).replaceAll("\\s", "");
                try {
                    if (externalPattern.matcher(req).matches()) {
                        String[] parts = req.substring(1, req.length()-1).split(",");
                        int floor = Integer.parseInt(parts[0]);
                        Direction dir = Direction.valueOf(parts[1].toUpperCase());
                        elevator.addExternalRequest(floor, dir);
                    } else if (internalPattern.matcher(req).matches()) {
                        int floor = Integer.parseInt(req.substring(1, req.length()-1));
                        elevator.addInternalRequest(floor);
                    }
                } catch (Exception e) {
                    // 忽略格式错误
                }
            }
            controller.processRequests();
        } catch (NumberFormatException e) {
            System.out.println("Wrong Format");
        }
    }
}

以下是我对于我自己代码的类与方法的说明:

Direction 和 State 枚举类:定义电梯的方向(UP,DOWN)和状态(MOVING,STOPPED)

ExternalRequest 类:记录外部请求的楼层和方向。

RequestQueue 类:内部请求和外部请求队列。

Elevator 类:当前楼层、方向、状态、最大和最小楼层限制,以及请求队列。

以下是我用SourceMontor的生成报表内容:

代码行数 275 语句数 170 分支语句占比 17.6% 方法调用语句数 94 含注释的代码行占比 1.5% 类和接口数 7 每类方法数 4.14 每方法平均语句数 4.10 最复杂方法的行号 121 最复杂方法的名称 Controller.determineDirection() 最大复杂度 14 最深代码块的行号 256 最大代码块深度 6 平均代码块深度 2.26 平均复杂度 2.24

主要问题:

Elevator类承接的功能实现太多的功能,不利于代码的修改和维护。

内外部的请求逻辑太过混乱,遇到一些特殊的请求程序不能正确的运行。

改进方案:

Elevator类的部分功能拆分到新建的类中去,

所以我们的第六次题目集来了。。。。。

第六次电梯:

这是电梯题目的类图关系:

这是我此次代码做出修改的地方:

新增加一个Controller类

class Controller {
    private final Elevator elevator;

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

    public void processRequests() {
        // 输出初始状态
        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + elevator.getDirection());
        boolean initialDirectionSet = false;

        while (elevator.getRequestQueue().hasRequests()) {
            determineDirection(initialDirectionSet);
            move();
            initialDirectionSet = true;
        }
    }

    private void determineDirection(boolean initialDirectionSet) {
        if (elevator.getState() == State.STOPPED && !initialDirectionSet) {
            RequestQueue queue = elevator.getRequestQueue();
            int current = elevator.getCurrentFloor();

            if (!queue.getInternalRequests().isEmpty()) {
                int firstInternalRequest = queue.getInternalRequests().get(0);
                elevator.setDirection(firstInternalRequest > current ? Direction.UP : Direction.DOWN);
            } else if (!queue.getExternalRequests().isEmpty()) {
                ExternalRequest firstExternalRequest = queue.getExternalRequests().get(0);
                elevator.setDirection(firstExternalRequest.getDirection());
            }
        } else if (elevator.getState() == State.STOPPED) {
            RequestQueue queue = elevator.getRequestQueue();
            int current = elevator.getCurrentFloor();
            
            boolean hasUp = queue.getInternalRequests().stream().anyMatch(f -> f > current) ||
                          queue.getExternalRequests().stream().anyMatch(req -> 
                              req.getFloor() > current || 
                              (req.getFloor() == current && req.getDirection() == Direction.UP));

            boolean hasDown = queue.getInternalRequests().stream().anyMatch(f -> f < current) ||
                            queue.getExternalRequests().stream().anyMatch(req -> 
                                req.getFloor() < current || 
                                (req.getFloor() == current && req.getDirection() == Direction.DOWN));

            switch (elevator.getDirection()) {
                case UP:
                    if (!hasUp && hasDown) elevator.setDirection(Direction.DOWN);
                    break;
                case DOWN:
                    if (!hasDown && hasUp) elevator.setDirection(Direction.UP);
                    break;
            }
        }
    }

    private void move() {
        Direction dir = elevator.getDirection();
        if (dir == Direction.UP) {
            elevator.setCurrentFloor(elevator.getCurrentFloor() + 1);
        } else if (dir == Direction.DOWN) {
            elevator.setCurrentFloor(elevator.getCurrentFloor() - 1);
        } else {
            return;
        }

        System.out.println("Current Floor: " + elevator.getCurrentFloor() + " Direction: " + dir);

        if (shouldStop()) {
            handleStop();
        } else {
            elevator.setState(State.MOVING);
        }
    }

    private boolean shouldStop() {
        int current = elevator.getCurrentFloor();
        RequestQueue queue = elevator.getRequestQueue();
        
        boolean internalStop = queue.getInternalRequests().contains(current);
        boolean externalStop = queue.getExternalRequests().stream().anyMatch(req -> 
            req.getFloor() == current && (
                req.getDirection() == elevator.getDirection() ||
                shouldHandleOppositeDirection(req)
            )
        );
        
        return internalStop || externalStop;
    }

    private boolean shouldHandleOppositeDirection(ExternalRequest req) {
        Direction currentDir = elevator.getDirection();
        if (currentDir == Direction.UP) {
            return req.getDirection() == Direction.DOWN && 
                   !hasRequests(req.getFloor(), Direction.UP);
        }
        if (currentDir == Direction.DOWN) {
            return req.getDirection() == Direction.UP && 
                   !hasRequests(req.getFloor(), Direction.DOWN);
        }
        return false;
    }

    private boolean hasRequests(int floor, Direction dir) {
        return elevator.getRequestQueue().getInternalRequests().stream().anyMatch(f -> 
            dir == Direction.UP ? f > floor : f < floor
        ) || elevator.getRequestQueue().getExternalRequests().stream().anyMatch(req -> 
            dir == Direction.UP ? req.getFloor() > floor : req.getFloor() < floor
        );
    }

    private void handleStop() {
        int current = elevator.getCurrentFloor();
        System.out.println("Open Door # Floor " + current);
        elevator.getRequestQueue().removeInternalRequest(current);
        elevator.getRequestQueue().removeExternalRequest(current);
        System.out.println("Close Door");
        elevator.setState(State.STOPPED);
    }
}

类与方法的说明:

Controller 类控制一个电梯实例

processRequests():处理所有请求直到队列为空。
determineDirection():根据当前状态和请求确定电梯方向。
move():电梯根据方向移动,并在必要时停止。
shouldStop():判断是否需要在当前楼层停止。
shouldHandleOppositeDirection():辅助判断是否处理相反方向的请求。
hasRequests():检查指定方向的请求。
 
以下是我用SourceMontor的生成报表内容:
代码行数 339 语句数 206 分支语句占比 17.0% 方法调用语句数 131 含注释的代码行占比 0.6% 类和接口数 7 每类方法数 6.14 每方法平均语句数 3.21 最复杂方法的行号 20 最复杂方法的名称 Main.processInputRequests()
主要问题:
controll类的代码太过于冗杂,其实有很多方法并没有使用。
电梯的工能实现并不完整。
改进方法:
删除一些没有实际运用的方法
继续将功能呢过多的类拆分成几个小类
增强代码的可维护性和可读性
 
终于终于 第七次电梯它来了:
这是此次题目的类图关系:
我们可以看到此次的题目新增加了passenger类。然后删除了ExternalRequest
然后对于输出格式也做出了相应的变化和调整
新增加的passenger类代码如下
class Passenger
{
    Integer sourceFloor=null;
    Integer destinationFloor=null;

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

    public Passenger(Integer destinationFloor)
    {
        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<destinationFloor)
        {
            return Direction.UP;
        }
        else if(sourceFloor>destinationFloor)
        {
            return Direction.DOWN;
        }
        return Direction.IDLE;
    }
}
以下是我用SourceMontor对此次代码的分析生成报表内容:
 
代码行数:339语句数:206分支语句占比:17.0%方法调用语句数:131含注释的代码行占比:0.6%类和接口数:7每类方法数:6.14每方法平均语句数:3.21最复杂方法的行号:20最复杂方法的名称Main.processInputRequests()
主要问题:
Controller.determineDirection()方法的复杂度过高,可能需要重构以降低复杂度,提高可维护性。
注释比例极低(1.2%),建议增加注释以提高代码的可读性和可维护性。
分支语句比例较低(18.3%),表明代码逻辑较为简单。
三、踩坑心得
在这几次的代码书写中,我犯了无数个错误,所以我觉得这个部分是最有用的一个部分,做的好的地发我们可以继续保持发扬,做的不好的地方则需要我们总结经验教训,方便我们日后再次书写代码不会烦同样的错误。
1.在这几次的代码书写中,最让我深恶痛绝的错误就是我没有注意输入的要求,比如,我在最开始的时候,输入的结果始终没有和预期的结果一样,原来是我忘记了电梯的初始化楼层也是要求窝嫩输入的。
2.对于正则表达式的应用,极为的不熟练,经常在书写时漏掉逗号和反斜杠号。
3.最为重要的一点是 在整个编写代码的途中,第一次看到题目时没有具体明确的思路,脑袋里完全就是一团散沙,对于类的构造也是迷迷糊糊的写的,要是没有老师提供的类图关系,我真的不知道该从何下手。
4.还有问题就是在于每次迭代升级的过程中,不能全部推倒重来,而是要在原有代码的基础与逻辑下继续完善和润色代码,就好比是建造一个房子,每次对房子的改进都是在原有的基础上添砖加瓦,没有把整个房子推到重来的方式。
5.还有就是对于数组ArrayList的使用不够熟练,经常出现代码报错,语法错误。我甚至尝试过用TreeMap来输入我的电梯请求,但是我发现我对此的掌握甚少,唉,只要是对于知识点不熟悉可以说是寸步难行。
四、改进建议
怎么说呢,对于我自己写的代码,我觉得就是一坨又丑又长的粑粑,代码的可读性不够高,逻辑复杂但是又没有深度。但是你说他差,但是它又能正确的运行出题目要求的结果,这导致我都不知道该从何修改我的代码。所以我自己给自己提出以下几点改进的建议。
1.我认为在开始书写代码之前需要好好给自己打个草稿,明确自己的思路,逻辑,抽象出程序的主要功能,各个类之间的关系这样才能方便我更有逻辑的全局的书写我的代码。
2.加强对于基础知识点的掌握,这样才能增加我代码的可读性和逻辑的缜密性。
3.对于代码,不要拘泥于一个类去实现多个功能,这样不利于代码的修改,应该适当的将相关联的方法重新拆分出一个新的类出来。
4.可以对自己写出的代码在合适的地方给出相应的注释,免得时间一长,自己都不知道这几行代码是干嘛的。
五、总结
1.通过这三周痛苦但是努力的电梯题目的书写,我找到了自己当前能力薄弱的地方,在逻辑思维的缜密需要多下功夫。
2.对于自己的基础知识的掌握太过于薄弱,需要在课堂上,课下都要多花时间多下功夫。
3.对于类之间关系的理解还是处于半懵半懂的状态,没有构建属于自己的知识网络。
5.不能对于困难的题目有畏难情绪,在难的题目也要一步一步的来,尽力去写,总结成功的经验,吸取失败的教训,会变得越来越好的。
当然我也在这几次题目中学到了不少东西
1.对于类的构造方法越来越熟悉
2.对于程序的逻辑思维能力得到了提升
3.学会了在不损坏之前代码的前提下对代码进行升级重构
对于这个课程的建议,我希望老师能够抽出点时间评讲一下我们做过的一些比较有困难的题目,这样可以让我们更加深刻的记住知识点。
测试点可以多增加几个,可以让我们这些能力较弱的同学也能去拿点分。
 
 
 
 
 
 

 

posted @ 2025-04-20 12:10  四季抗病毒  阅读(24)  评论(0)    收藏  举报