Java题目集_OOP5~7 电梯迭代作业分析

一、前言

  • 在学习了一个月的Java后,终于是迎来了本次的题目集5 ~ 7,在被电梯运行逻辑及题目要求折磨了三周后,满腔热血(身心俱疲)写下此篇博客来分享自己曾经走过的弯路及自己在此篇题目集所get到的经验与教训。
  • 题目集的难度初始为中等,但会不断迭代升级,对学生的要求进一步提升。
  • 题目集难度不断迭代,启发学生不断完善代码,设计的代码能够贴合现实情况,合理设计类与类的关系。
  • 题目集考察了正则表达式的运用,及单一职责原则的设计原则。
  • 题目集的题量适中,属于正常水准。

二、设计与分析

1、题目集NCHU_OOP5 (第一次作业)

I.题目描述:

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

II.问题分析:

题目要求电梯采用串行处理请求,电梯应忽视无效请求(貌似 NCHU_OOP5 的测试点并没有测试相关要求),电梯有三种方向(停止,上行,下行),四种状态(开门,关门,静止,运行),电梯优先处理同方向请求,若无同方向请求则转向再次判定,若无请求则停止。
同时题目还要求电梯能够处理顺路请求,并且电梯每次只会从请求队列中的队头取出请求进行方向判断

III.初次尝试:

第一次尝试时,由于不了解题目所要求的电梯运行逻辑,故自顾自瞎写一通,未能注意到最下方的关于运行逻辑的pdf文档,导致浪费了许多时间。
pdf链接: https://images.ptausercontent.com/b980fd0a-0919-48a1-bc7d-c4748c4e1ea5.pdf
pdf文档中解释了电梯在特定样例下的运行逻辑,但在当时我仍然未能完全理解其完整的判断逻辑,故而在逻辑处理方面花费大量时间
完成后的代码在判断电梯运行方向的方法中存在逻辑不够完善的问题,导致对一些测试用例会输出错误的答案,但OOP5的测试点仅有一个,所以第一次我侥幸通过,可这也为我写题目集 OOP6 埋下了巨雷

IV.代码分析:

1.OOP5 初次代码:
点击查看代码

class elevator{
    private int maxFloor;
    private int minFloor;
    private int nowFloor;
    private int turn; //1 上 2 下 0 止
    private int state;//0 停止 1 移动 2 开门 3 关门

    class Request{
        private int floor;
        private int turn;
        private boolean isOut;

        public Request(){
            this.floor = 1;
            this.turn = 0;
            this.isOut = true;
        }

        public Request(int floor,int turn,boolean isout){
            this.floor = floor;
            this.turn = turn;
            this.isOut = isout;
        }

        public int getFloor(){
            return floor;
        }

        public int getTurn(){
            return turn;
        }

        public void setTurn(int turn){
            this.turn = turn;
        }

        public void setFloor(int floor){
            this.floor = floor;
        }

        public boolean requestIsOut(){
            return this.isOut;
        }

        public boolean checkLegal(){
            if(this.floor > maxFloor || this.floor < minFloor) return false;
            return (this.floor != maxFloor || this.turn != 1)
                    && (this.floor != minFloor || this.turn != 2);
        }
    }
    class myQue{
        private Request[] deque;
        private int size;
        private int l,r;
        private final int maxSize = 10000;

        public myQue(){
            deque = new Request[maxSize];
            size = 0;
            l = 0;
            r = 0;
        }

        public boolean isEmpty(){
            return size <= 0;
        }

        public boolean isFull(){
            return size >= maxSize;
        }

        public Request peek(){
            return deque[l];
        }

        public boolean push(Request request){
            if(isFull()) return false;
            deque[r++] = request;
            size++;
            return true;
        }

        public boolean remove(){
            if(isEmpty()) return false;
            l++;
            size--;
            return true;
        }


        public int getSize(){
            return size;
        }

        public void clear(){
            l = 0;
            r = 0;
            size = 0;
        }


    }

    private myQue requestOutQueue = new myQue();
    private myQue requestInterQueue = new myQue();

    //l 装载上行  r 装载下行

    public elevator(){
        maxFloor = 1;
        minFloor = 1;
        nowFloor = 1;
        turn = 1;
        state = 0;
    }

    public elevator(int minFloor,int maxFloor){
        this.maxFloor = maxFloor;
        this.minFloor = minFloor;
        this.nowFloor = 1;
        this.turn = 1;
        this.state = 0;
    }

    public void setMaxFloor(int maxFloor) {
        this.maxFloor = maxFloor;
    }

    public void setMinFloor(int minFloor) {
        this.minFloor = minFloor;
    }

    private Request createRequest(int floor,int turn,boolean isout){
        return new Request(floor,turn,isout);
    }

    private boolean waitRequest(){
        return requestInterQueue.isEmpty() && requestOutQueue.isEmpty();
    }

    private boolean collectRequest(Request request){
        if(request.checkLegal()){
            if(request.requestIsOut()){
                this.requestOutQueue.push(request);
            }
            else{
                this.requestInterQueue.push(request);
            }
            return true;
        }
        else return false;
    }

    private void showNowFloorStop(){
        System.out.printf("Open Door # Floor %d\n",nowFloor);
        if(!waitRequest()) System.out.print("Close Door\n");
        else System.out.print("Close Door");
    }

    private void showNowFloorUnstop(){
        String theTurn = this.turn == 1 ? "UP" : "DOWN";
        System.out.printf("Current Floor: %d Direction: %s\n",nowFloor,theTurn);
    }

    private boolean elevtorMoveUp(){
        if(this.nowFloor < this.maxFloor) this.nowFloor++;
        else return false;
        return true;
    }

    private boolean elevtorMoveDown(){
        if(this.nowFloor > this.minFloor) this.nowFloor--;
        else return false;
        return true;
    }

    public boolean needToContinue(String input){
        if(input.equalsIgnoreCase("end") || input.isEmpty()) return false;
        else{
            Request newrequest;
            if(input.matches("<(-?\\d+)(,\\w{2,4})?>")){
                int index = input.indexOf(',');
                int nfloor = 0;
                if(index != -1) {
                    nfloor = Integer.parseInt(input.substring(1,index));
                    int nturn = input.substring(index + 1, input.length() - 1).equals("UP") ? 1 : 2;
                    newrequest = createRequest(nfloor, nturn, true);
                }
                else{
                    nfloor = Integer.parseInt(input.substring(1,input.length()-1));
                    newrequest = createRequest(nfloor,0,false);
                }
            }
            else{
                return true;
            }
            collectRequest(newrequest);
            return true;
        }
    }

    public void mannager(){
        if(waitRequest()){
            this.state = 0;
            this.turn = 0;
            return;
        }
        Request nowrequest;
        while(!waitRequest()){
            if(!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()){
                int innerturn = requestInterQueue.peek().getFloor() - nowFloor > 0 ? 1 : 2;
                int outturn = requestOutQueue.peek().getTurn();
                if(innerturn == this.turn && outturn != this.turn){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(outturn == this.turn && innerturn != this.turn){
                    nowrequest = requestOutQueue.peek();
                    requestOutQueue.remove();
                }
                else {
                    if(Math.abs(requestInterQueue.peek().floor - this.nowFloor)
                    < Math.abs(requestOutQueue.peek().floor - this.nowFloor)){
                        nowrequest = requestInterQueue.peek();
                        requestInterQueue.remove();
                    }
                    else{
                        nowrequest = requestOutQueue.peek();
                        requestOutQueue.remove();
                    }
                }
            }
            else if(!requestInterQueue.isEmpty()){
                nowrequest = requestInterQueue.peek();
                requestInterQueue.remove();
            }
            else{
                nowrequest = requestOutQueue.peek();
                requestOutQueue.remove();
            }

            /*if(nowrequest.requestIsOut() && !requestOutQueue.isEmpty())
                while(requestOutQueue.peek().getFloor() == this.nowFloor
                && requestOutQueue.peek().getTurn() == nowrequest.getTurn()
                     ) requestOutQueue.remove();
            else while(!requestInterQueue.isEmpty()
                    && requestInterQueue.peek().getFloor() == this.nowFloor) requestInterQueue.remove();
*/

            this.turn = nowrequest.floor - this.nowFloor >= 0 ? (nowrequest.floor == this.nowFloor ? 0 : 1) : 2;
            if(!nowrequest.requestIsOut()) nowrequest.turn = nowrequest.floor - this.nowFloor >= 0 ?
                    (nowrequest.floor == this.nowFloor ? 0 : 1) : 2;
            //int initturn = this.turn;

            if(state == 0) {
                if(nowrequest.getFloor() != this.nowFloor) {
                    showNowFloorUnstop();
                    state = 1;
                }
            }
            int n = 0;
            while(this.nowFloor != nowrequest.floor){

                boolean again = false;

                if(this.turn == 1) {
                    if (!elevtorMoveUp()) break;
                }
                else {
                    if (!elevtorMoveDown()) break;
                }

                showNowFloorUnstop();

                if(!requestOutQueue.isEmpty()
                        && requestOutQueue.peek().floor == this.nowFloor
                        && requestOutQueue.peek().turn == nowrequest.getTurn()){
                    n = this.nowFloor;
                    again = true;
                    showNowFloorStop();
                    this.state = 1;
                    while(!requestOutQueue.isEmpty()
                            && requestOutQueue.peek().getFloor() == this.nowFloor
                            && requestOutQueue.peek().getTurn() == nowrequest.getTurn()) requestOutQueue.remove();
                }
                if(!requestInterQueue.isEmpty()
                && requestInterQueue.peek().getFloor() == this.nowFloor
                ){
                    if(!again) showNowFloorStop();
                    this.state = 1;
                    n = this.nowFloor;
                    while(!requestInterQueue.isEmpty()
                    && requestInterQueue.peek().getFloor() == this.nowFloor) requestInterQueue.remove();
                }

            }

            if(this.nowFloor != n) showNowFloorStop();
            if(nowrequest.requestIsOut()) this.turn = nowrequest.getTurn();
            if(requestOutQueue.isEmpty() && requestInterQueue.isEmpty()) this.state = 0;
        }
    }
}

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

        one.setMinFloor(input.nextInt());
        one.setMaxFloor(input.nextInt());
        input.nextLine();

        while(one.needToContinue(input.nextLine()));

        one.mannager();
    }
}

2.代码类图:

在本次的题目集5中,按照题目集的单类要求,我设计了一个电梯类与一个测试类(入口),在电梯类中,我并未使用老师推荐的LinkedList类,而是自己用数组模拟队列操作,故elevator类中我额外设计了一个Request类与myQue类。
以下是类图:

3.SourceMonitor工具评估:

SM评估图片如下:

评估分析:

点击查看分析
Lines:代码行数 320 。
Statements:语句数 210 。
Percent Branch Statements:分支语句占比 21.4% 。
Method Call Statements:方法调用语句数 84 。
Percent Lines with Comments:含注释行占比 3.1% 。
Classes and Interfaces:类和接口数量 4 。
Methods per Class:平均每个类的方法数 7.50 。
Average Statements per Method:平均每个方法的语句数 5.40 。
复杂度相关
Line Number of Most Complex Method:最复杂方法所在行号 203 ,方法名 elevator.mannager() ,复杂度 40 。
Line Number of Deepest Block:最深代码块行号 225 ,最大块深度 6 。
Average Block Depth:平均块深度 2.84 。
Average Complexity:平均复杂度 3.13 。
  • 由SM评估图片不难发现代码性能较差,分支语句占比较高,占比21.4%,同时最大复杂度为40,最大深度为6,都是位于elevator类中的manager方法中,因此,优化manager方法十分重要,在后续的OOP题目中我对manager进行了一定程度的优化。
  • manager方法复杂的原因主要在于我将取出请求与判断电梯方向的方法与manager方法杂糅在了一起,方法的职责分工定位不够清晰,导致时间复杂度大幅度增加
  • 与此同时,代码中的注释极其稀少,代码的可读性较差
  • 由于采用了静态数组模拟队列,相较于LinkedList,空间复杂度可能会更高

V.题目集 NCHU_OOP5 总结

由于是第一次尝试以面向对象的思想来设计类,因此类之间的关系可能并未规划良好,注释也稀少,代码可读性较差,同时,由于时间因素,我在电梯逻辑处理这一块并未能够顾及到所有可能性。方法中分工不清晰,复杂度大幅度增加。虽然题目集OOP5成功通过,但这无疑是一个失败的代码。

2.题目集 NCHU_OOP6 (第二次迭代作业)

I.题目描述:

对之前电梯调度程序进行迭代性设计,目的为解决电梯类职责过多的问题,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客请求类、队列类以及控制类。
电梯运行规则与前阶段单类设计相同,但要处理如下情况:

乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>

II.问题分析:

此次题目新增要求,必须采用多类设计,并且在此题开始正式要求处理非法请求,测试点也更新为两个,同时题目也要求要处理重复请求,不难看出题目难度开始增加。

III.初次尝试:

拥有OOP5 代码基础,从elevator类中分离出Request类与myQue类并不是难事,而处理非法请求更容易,增加if判断即可。
处理重复请求则是在此时引起我的思考:OOP5 中不是要求处理顺路请求吗,那么对于重复请求,在电梯运行过程中,不是会自动清空吗,似乎不用新加判断逻辑。
处于严谨性考虑,借助两个变量分别记录队尾的元素,再与新进入的元素进行判断,不论是否重复,均更新记录变量lastRequestOut和lastRequestInter。
并且为优化manager方法,我将manager中的取出请求整合成一个方法:getNextRequest。

此时代码看上去似乎可行,但我仍然忽视了一个致命错误:方向逻辑判断错误。源代码针对请求的判断仅有短短6句,明显无法涵盖所有情况。因此我新增了部分判断逻辑。
原逻辑中判断逻辑:
1.无请求,停止
2.有外部请求无内部请求,取外部请求
3.无外部请求有内部请求,取内部请求
4.内外部请求均有,且请求方向不同,取同方向请求
5.内外部请求均有,且请求方向相同,取同最近方向

改动后的判断逻辑:
1.无请求,停止
2.有外部请求无内部请求,取外部请求
3.无外部请求有内部请求,取内部请求
4.内外部请求均有,内部请求同向,外部请求同向,外部请求不在电梯方向上,则取内部请求
5.内外部请求均有,内部请求不同向,外部请求同向,且请求位于电梯同方向上,则取外部请求
6.内外部请求均有,内部请求不同向,外部请求不同向,但外部请求在电梯同方向上,则取外部请求
7.内外部请求均有,内部请求不同向,外部请求不同向,但外部请求不在电梯同方向上,电梯方向反转
8.内外部请求均有,内部请求同向,外部请求不同向,外部请求不在电梯方向上,则取内部请求
9.内外部请求均有,内部请求同向,外部请求不同向,外部请求在电梯方向上,则取内部请求
10.内外部请求均有,内部请求不同向,外部请求同向,外部请求不在电梯方向上,则电梯反转
11.内外部请求均有,内部请求同向,外部请求同向,外部请求在电梯方向上,则取最近请求

改动后判断代码如下:

点击查看代码
if(waitRequest()){
            Elevator.setState(0);
            Elevator.setTurn(0);
            return null;
        }
        Request nowrequest = null;
        if(!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()) {
            while (!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()) {
                int innerturn = requestInterQueue.peek().getFloor() - Elevator.getNowFloor() >= 0 ? 1 : 2;
                int outturn = requestOutQueue.peek().getTurn();
                int trueturn = requestOutQueue.peek().getFloor() - Elevator.getNowFloor() >= 0 ? 1 : 2;

                if(innerturn == Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    if(Math.abs(requestInterQueue.peek().getFloor() - Elevator.getNowFloor())
                            < Math.abs(requestOutQueue.peek().getFloor() - Elevator.getNowFloor())){
                        nowrequest = requestInterQueue.peek();
                        requestInterQueue.remove();
                    }
                    else if(Math.abs(requestInterQueue.peek().getFloor() - Elevator.getNowFloor())
                            == Math.abs(requestOutQueue.peek().getFloor() - Elevator.getNowFloor())){
                        nowrequest = requestInterQueue.peek();
                        requestOutQueue.remove();
                        requestInterQueue.remove();
                    }
                    else{
                        nowrequest = requestOutQueue.peek();
                        requestOutQueue.remove();
                    }
                }
                else if(innerturn == Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    nowrequest = requestOutQueue.peek();
                    requestOutQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    Elevator.reverseTurn();
                    continue;
                }
                else if(innerturn == Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(innerturn == Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    nowrequest = requestOutQueue.peek();
                    requestOutQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    Elevator.reverseTurn();
                    continue;
                }
                break;
            }

补充OOP5 的判断代码:

点击查看代码
if(!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()){
                int innerturn = requestInterQueue.peek().getFloor() - nowFloor > 0 ? 1 : 2;
                int outturn = requestOutQueue.peek().getTurn();
                if(innerturn == this.turn && outturn != this.turn){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(outturn == this.turn && innerturn != this.turn){
                    nowrequest = requestOutQueue.peek();
                    requestOutQueue.remove();
                }
                else {
                    if(Math.abs(requestInterQueue.peek().floor - this.nowFloor)
                            < Math.abs(requestOutQueue.peek().floor - this.nowFloor)){
                        nowrequest = requestInterQueue.peek();
                        requestInterQueue.remove();
                    }
                    else{
                        nowrequest = requestOutQueue.peek();
                        requestOutQueue.remove();
                    }
                }
            }
            else if(!requestInterQueue.isEmpty()){
                nowrequest = requestInterQueue.peek();
                requestInterQueue.remove();
            }
            else{
                nowrequest = requestOutQueue.peek();
                requestOutQueue.remove();
            }

改动后的代码,在判断方向的方法中,于内外部请求均存在的前提下,增加了8条判断语句确保能够覆盖所有情况。
涵盖所有情况的同时,由于采用了大量if-else语句,导致复杂度增加,抵消了一部分对于manager的优化。

然后,就当我以为代码能够通过测试点时,发现仍然是答案错误

第一个测试点未能通过,经过长达2天的思考,在一次尝试性注释代码块后,程序竟然通过了,注释掉的代码块的用途是处理顺路请求,OOP6 似乎不用处理顺路请求,被卡了3天的我在结束前两小时完成了题目集

IV.代码分析:

1.OOP6 源代码:
点击查看代码
import java.util.Scanner;

class Request{
    private int floor;
    private int turn;
    private boolean isOut;
    private int maxFloor;
    private int minFloor;

    public Request(){
        this.floor = 1;
        this.turn = 0;
        this.isOut = true;
        minFloor = 1;
        maxFloor = 1;
    }

    public Request(int floor,int turn,boolean isout,int minFloor,int maxFloor){
        this.floor = floor;
        this.turn = turn;
        this.isOut = isout;
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
    }

    public int getFloor(){
        return floor;
    }

    public int getTurn(){
        return turn;
    }

    public int getMinFloor() {
        return minFloor;
    }

    public int getMaxFloor() {
        return maxFloor;
    }

    public void setTurn(int turn){
        this.turn = turn;
    }

    public void setFloor(int floor){
        this.floor = floor;
    }

    public void setMinFloor(int minFloor) {
        this.minFloor = minFloor;
    }

    public void setMaxFloor(int maxFloor) {
        this.maxFloor = maxFloor;
    }

    public void setOut(boolean out) {
        isOut = out;
    }

    public boolean requestIsOut(){
        return this.isOut;
    }

    public boolean checkLegal(){
        if(this.floor > maxFloor || this.floor < minFloor) return false;
        return true;
    }

    public static Request createRequest(int floor,int turn,boolean isout,int minFloor,int maxFloor){
        return new Request(floor,turn,isout,minFloor,maxFloor);
    }

    public boolean isequals(Request other){
        return other.requestIsOut() == this.isOut
            && other.getTurn() == this.turn
            && other.getFloor() == this.floor
            && other.getMaxFloor() == this.maxFloor
            && other.getMinFloor() == this.minFloor;
    }
}

class myQue{
    private Request[] deque;
    private int size;
    private int l,r;
    private final int maxSize = 10000;

    public myQue(){
        deque = new Request[maxSize];
        size = 0;
        l = 0;
        r = 0;
    }

    public boolean isEmpty(){
        return size <= 0;
    }

    public boolean isFull(){
        return size >= maxSize;
    }

    public Request peek(){
        return deque[l];
    }

    public boolean push(Request request){
        if(isFull()) return false;
        deque[r++] = request;
        size++;
        return true;
    }

    public boolean remove(){
        if(isEmpty()) return false;
        l++;
        size--;
        return true;
    }


    public int getSize(){
        return size;
    }

    public void clear(){
        l = 0;
        r = 0;
        size = 0;
    }


}

class elevator{
    private int maxFloor;
    private int minFloor;
    private int nowFloor;
    private int turn; //1 上 2 下 0 止
    private int state;//0 停止 1 移动 2 开门 3 关门

    //l 装载上行  r 装载下行

    public elevator(){
        maxFloor = 1;
        minFloor = 1;
        nowFloor = 1;
        turn = 0;
        state = 0;
    }

    public elevator(int minFloor,int maxFloor){
        this.maxFloor = maxFloor;
        this.minFloor = minFloor;
        nowFloor = Math.max(1,minFloor);
        this.turn = 1;
        this.state = 0;
    }

    public int getNowFloor() {
        return nowFloor;
    }

    public int getState() {
        return state;
    }

    public int getTurn() {
        return turn;
    }

    public int getMaxFloor() {
        return maxFloor;
    }

    public int getMinFloor() {
        return minFloor;
    }

    public void setMaxFloor(int maxFloor) {
        this.maxFloor = maxFloor;
    }

    public void setMinFloor(int minFloor) {
        this.minFloor = minFloor;
    }

    public void setState(int state) {
        this.state = state;
    }

    public void reverseTurn(){
        this.turn = this.turn == 1 ? 2 : 1;
    }

    public void setTurn(int turn) {
        this.turn = turn;
    }

    public void setNowFloor(int nowFloor) {
        this.nowFloor = nowFloor;
    }
}

class Agent{
    private elevator Elevator;
    private myQue requestOutQueue = new myQue();
    private myQue requestInterQueue = new myQue();
    private Request lastRequestOut = null;
    private Request lastRequestInter = null;

    public Agent(){

    }

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

    private boolean waitRequest(){
        return requestInterQueue.isEmpty() && requestOutQueue.isEmpty();
    }

    private boolean collectRequest(Request request){
        if(request.checkLegal()){
            if(request.requestIsOut()){
                this.requestOutQueue.push(request);
            }
            else{
                this.requestInterQueue.push(request);
            }
            return true;
        }
        else return false;
    }

    private void showNowFloorStop(){
        System.out.printf("Open Door # Floor %d\n",Elevator.getNowFloor());
        Elevator.setState(2);
        if(!waitRequest()) System.out.print("Close Door\n");
        else System.out.print("Close Door");
        Elevator.setState(3);
    }

    private void showNowFloorUnstop(){
        String theTurn = Elevator.getTurn() == 1 ? "UP" : "DOWN";
        System.out.printf("Current Floor: %d Direction: %s\n",Elevator.getNowFloor(),theTurn);
    }

    private boolean elevtorMoveUp(){
        if(Elevator.getNowFloor() < Elevator.getMaxFloor()) Elevator.setNowFloor(Elevator.getNowFloor() + 1);
        else return false;
        return true;
    }

    private boolean elevtorMoveDown(){
        if(Elevator.getNowFloor() > Elevator.getMinFloor()) Elevator.setNowFloor(Elevator.getNowFloor() - 1);
        else return false;
        return true;
    }

    public boolean needToContinue(String input){
        if(input.equalsIgnoreCase("end") || input.isEmpty()) return false;
        else{
            Request newrequest;
            if(input.matches("<(-?\\d+)(,\\w{2,4})?>")){
                int index = input.indexOf(',');
                int nfloor = 0;
                if(index != -1) {
                    nfloor = Integer.parseInt(input.substring(1,index));
                    int nturn = input.substring(index + 1, input.length() - 1).equals("UP") ? 1 : 2;
                    newrequest = Request.createRequest(nfloor, nturn, true, Elevator.getMinFloor(), Elevator.getMaxFloor());
                }
                else{
                    nfloor = Integer.parseInt(input.substring(1,input.length()-1));
                    newrequest = Request.createRequest(nfloor,0,false, Elevator.getMinFloor(), Elevator.getMaxFloor());
                }
            }
            else{
                return true;
            }
            boolean t;
            boolean isout = newrequest.requestIsOut();
            if(isout){
                if(lastRequestOut == null || !lastRequestOut.isequals(newrequest)) collectRequest(newrequest);
                lastRequestOut = newrequest;
            }
            else{
                if(lastRequestInter == null || !lastRequestInter.isequals(newrequest)) collectRequest(newrequest);
                lastRequestInter = newrequest;
            }

            return true;
        }
    }

    private Request getNextRequest(){
        if(waitRequest()){
            Elevator.setState(0);
            Elevator.setTurn(0);
            return null;
        }
        Request nowrequest = null;
            if(!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()) {
                while (!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()) {
                    int innerturn = requestInterQueue.peek().getFloor() - Elevator.getNowFloor() >= 0 ? 1 : 2;
                    int outturn = requestOutQueue.peek().getTurn();
                    int trueturn = requestOutQueue.peek().getFloor() - Elevator.getNowFloor() >= 0 ? 1 : 2;

                         if(innerturn == Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn == Elevator.getTurn()){
                        if(Math.abs(requestInterQueue.peek().getFloor() - Elevator.getNowFloor())
                                < Math.abs(requestOutQueue.peek().getFloor() - Elevator.getNowFloor())){
                            nowrequest = requestInterQueue.peek();
                            requestInterQueue.remove();
                        }
                        else if(Math.abs(requestInterQueue.peek().getFloor() - Elevator.getNowFloor())
                                == Math.abs(requestOutQueue.peek().getFloor() - Elevator.getNowFloor())){
                            nowrequest = requestInterQueue.peek();
                            requestOutQueue.remove();
                            requestInterQueue.remove();
                        }
                        else{
                            nowrequest = requestOutQueue.peek();
                            requestOutQueue.remove();
                        }
                    }
                    else if(innerturn == Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn != Elevator.getTurn()){
                        nowrequest = requestInterQueue.peek();
                        requestInterQueue.remove();
                    }
                    else if(innerturn != Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn == Elevator.getTurn()){
                        nowrequest = requestOutQueue.peek();
                        requestOutQueue.remove();
                    }
                    else if(innerturn != Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn != Elevator.getTurn()){
                        Elevator.reverseTurn();
                        continue;
                    }
                    else if(innerturn == Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn == Elevator.getTurn()){
                        nowrequest = requestInterQueue.peek();
                        requestInterQueue.remove();
                    }
                    else if(innerturn == Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn != Elevator.getTurn()){
                        nowrequest = requestInterQueue.peek();
                        requestInterQueue.remove();
                    }
                    else if(innerturn != Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn == Elevator.getTurn()){
                        nowrequest = requestOutQueue.peek();
                        requestOutQueue.remove();
                    }
                    else if(innerturn != Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn != Elevator.getTurn()){
                        Elevator.reverseTurn();
                        continue;
                    }
                    break;
                }
            }
            else {
                if (!requestInterQueue.isEmpty()) {
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                } else {
                    nowrequest = requestOutQueue.peek();
                    requestOutQueue.remove();
                }
            }

            return nowrequest;
    }

    public void mannager(){
        if(waitRequest()){
            Elevator.setState(0);
            Elevator.setTurn(0);
            return;
        }
        Request nowrequest = new Request();
        while(!waitRequest()){
            nowrequest = getNextRequest();
            if(nowrequest == null) break;

            Elevator.setTurn(nowrequest.getFloor() - Elevator.getNowFloor() >= 0 ?  1 : 2);
            
            if(Elevator.getState() == 0) {
                if(nowrequest.getFloor() != Elevator.getNowFloor()) {
                    showNowFloorUnstop();
                    Elevator.setState(1);
                }
            }
            int n = -10;
            while(Elevator.getNowFloor() != nowrequest.getFloor()){

                boolean again = false;

                if(Elevator.getTurn() == 1) {
                    if (!elevtorMoveUp()) break;
                }
                else {
                    if (!elevtorMoveDown()) break;
                }

                showNowFloorUnstop();

                /*if(!requestOutQueue.isEmpty()
                        && requestOutQueue.peek().getFloor() == Elevator.getNowFloor()
                        && requestOutQueue.peek().getTurn() == Elevator.getTurn()
                ){
                    n = Elevator.getNowFloor();
                    again = true;
                    showNowFloorStop();
                    Elevator.setState(1);
                    requestOutQueue.remove();
                }
                if(!requestInterQueue.isEmpty()
                        && requestInterQueue.peek().getFloor() == Elevator.getNowFloor()
                ){
                    if(!again) showNowFloorStop();
                    Elevator.setState(1);
                    n = Elevator.getNowFloor();
                    requestInterQueue.remove();
                }*/
            }

            if(Elevator.getNowFloor() != n) showNowFloorStop();
            if(nowrequest.requestIsOut()) Elevator.setTurn(nowrequest.getTurn());
            if(waitRequest()) Elevator.setState(0);
        }
    }

}

public class Main {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        elevator one = new elevator(input.nextInt(),input.nextInt());

        input.nextLine();

        Agent elevatorMannager = new Agent(one);

        while(elevatorMannager.needToContinue(input.nextLine()));

        elevatorMannager.mannager();
    }
}
2.代码类图:

在本次的题目集中,应题目要求,我将elevator类分离成4个类:Request类,myQue类,Agent类,elevator类。
以下是类图:

3.SourceMonitor分析评估:

SM评估图片如下:

评估分析:

点击查看分析
Lines:代码行数 429 。
Statements:语句数 276 。
Percent Branch Statements:分支语句占比 19.2% 。
Method Call Statements:方法调用语句数 149 。
Percent Lines with Comments:注释行占比仅 0.5% ,说明代码注释较少。
结构相关
Classes and Interfaces:类和接口数量为 5 。
Methods per Class:平均每个类的方法数 9.60 。
Average Statements per Method:平均每个方法的语句数 4.25 。
复杂度相关
Line Number of Most Complex Method:最复杂方法在 298 行,方法是 Agent.getNextRequest() ,最大复杂度为 38 。
Line Number of Deepest Block:最深代码块在 314 行,最大块深度 6 。
Average Block Depth:平均块深度 2.43 。
Average Complexity:平均复杂度 2.69 。
  • 由本次的SM分析图片与OOP5 相对比,最大复杂度优化较少,最大深度仍为6,最复杂的方法从manager转为了getNextRequest,但是判断语句已优化,平均复杂度较大减少。
  • 代码的最大复杂都仍然较高,因此仍然需要不断优化。
  • 本次代码主要优化逻辑处理方法,相较于OOP5 已经能处理较为全面的情况。

V.题目集 NCHU_OOP6 总结:

在此次的题目集中,针对与OOP5 逻辑不够完善的问题,我进行了较大优化,同时也优化了方法的分工,减少了最大复杂度与平均复杂度,但代码仍然有较大的不足。

3、题目集NCHU_OOP7 (第三次迭代作业)

I.题目描述:

对之前电梯调度程序再次进行迭代性设计,加入乘客类(Passenger),取消乘客请求类,类设计要求遵循单一职责原则(SRP),要求必须包含但不限于设计电梯类、乘客类、队列类以及控制类
电梯运行规则与前阶段相同,但有如下变动情况:

乘客请求输入变动情况:外部请求由之前的<请求楼层数,请求方向>修改为<请求源楼层,请求目的楼层>
对于外部请求,当电梯处理该请求之后(该请求出队),要将<请求源楼层,请求目的楼层>中的请求目的楼层加入到请求内部队列(加到队尾)

II.问题分析:

  • 在本次的题目集中,取消了请求类,增加乘客类,并且修改了输入格式,然后又新增了处理完外部请求后,将外部请求的目标楼层装载进内部队列。
  • 本次题目集改动较大,逻辑新增,格式变化,作为最后一次迭代作业,难度相当。

III.初次尝试:

由于取消了Request类,我重新设计了Passenger类,相较于Request类,我改动了正则表达式部分以及获取方向等方法以适应题目要求。
Passenger代码如下:

点击查看代码
class Passenger{
    private int startFloor;
    private int targetFloor;

    public Passenger(){
        startFloor = 0;
        targetFloor = -1;
    }

    public  Passenger(int startFloor){
        this.startFloor = startFloor;
        this.targetFloor = -1;
    }

    public Passenger(int startFloor,int targetFloor){
        this.targetFloor = targetFloor;
        this.startFloor = startFloor;
    }

    public int getTargetFloor() {
        return targetFloor;
    }

    public int getStartFloor() {
        return startFloor;
    }

    public boolean requestIsOut(){
        return targetFloor != -1;
    }

    public boolean isEqual(Passenger other){
        return this.targetFloor == other.targetFloor
                && this.startFloor == other.startFloor;
    }

    public int getTurn(){
        return startFloor - targetFloor >= 0 ? 2 : 1;
    }
}

原Request代码如下:

点击查看代码
class Request{
    private int floor;
    private int turn;
    private boolean isOut;
    private int maxFloor;
    private int minFloor;

    public Request(){
        this.floor = 1;
        this.turn = 0;
        this.isOut = true;
        minFloor = 1;
        maxFloor = 1;
    }

    public Request(int floor,int turn,boolean isout,int minFloor,int maxFloor){
        this.floor = floor;
        this.turn = turn;
        this.isOut = isout;
        this.minFloor = minFloor;
        this.maxFloor = maxFloor;
    }

    public int getFloor(){
        return floor;
    }

    public int getTurn(){
        return turn;
    }

    public int getMinFloor() {
        return minFloor;
    }

    public int getMaxFloor() {
        return maxFloor;
    }

    public void setTurn(int turn){
        this.turn = turn;
    }

    public void setFloor(int floor){
        this.floor = floor;
    }

    public void setMinFloor(int minFloor) {
        this.minFloor = minFloor;
    }

    public void setMaxFloor(int maxFloor) {
        this.maxFloor = maxFloor;
    }

    public void setOut(boolean out) {
        isOut = out;
    }

    public boolean requestIsOut(){
        return this.isOut;
    }

    public boolean checkLegal(){
        if(this.floor > maxFloor || this.floor < minFloor) return false;
        return true;
    }

    public static Request createRequest(int floor,int turn,boolean isout,int minFloor,int maxFloor){
        return new Request(floor,turn,isout,minFloor,maxFloor);
    }

    public boolean isequals(Request other){
        return other.requestIsOut() == this.isOut
            && other.getTurn() == this.turn
            && other.getFloor() == this.floor
            && other.getMaxFloor() == this.maxFloor
            && other.getMinFloor() == this.minFloor;
    }
}

Passenger基于题目要求由Request类优化而来,代码相对简洁,删去了maxFloor与minFloor等无关紧要的属性,同时,在manager的到达楼层后新增将乘客对象压入内部乘客队列。

改动后相关代码:

点击查看代码
if(nowrequest.requestIsOut()){
                Elevator.setTurn(nowrequest.getTurn());
                collectPassenger(new Passenger(nowrequest.getTargetFloor()));
            }
            if(waitRequest()) Elevator.setState(0);

改动前相关代码:

点击查看代码
if(nowrequest.requestIsOut()) Elevator.setTurn(nowrequest.getTurn());
if(waitRequest()) Elevator.setState(0);

由于逻辑问题在OOP6 中已解决,因此我这次直接通过。

IV.代码分析:

1.OOP7 源代码:
点击查看代码
import java.util.Scanner;

class Passenger{
    private int startFloor;
    private int targetFloor;

    public Passenger(){
        startFloor = 0;
        targetFloor = -1;
    }

    public  Passenger(int startFloor){
        this.startFloor = startFloor;
        this.targetFloor = -1;
    }

    public Passenger(int startFloor,int targetFloor){
        this.targetFloor = targetFloor;
        this.startFloor = startFloor;
    }

    public int getTargetFloor() {
        return targetFloor;
    }

    public int getStartFloor() {
        return startFloor;
    }

    public boolean requestIsOut(){
        return targetFloor != -1;
    }

    public boolean isEqual(Passenger other){
        return this.targetFloor == other.targetFloor
                && this.startFloor == other.startFloor;
    }

    public int getTurn(){
        return startFloor - targetFloor >= 0 ? 2 : 1;
    }
}

class myQue{
    private Passenger[] deque;
    private int size;
    private int l,r;
    private final int maxSize = 10000;

    public myQue(){
        deque = new Passenger[maxSize];
        size = 0;
        l = 0;
        r = 0;
    }

    public boolean isEmpty(){
        return size <= 0;
    }

    public boolean isFull(){
        return size >= maxSize;
    }

    public Passenger peek(){
        return deque[l];
    }

    public boolean push(Passenger request){
        if(isFull()) return false;
        deque[r++] = request;
        size++;
        return true;
    }

    public boolean remove(){
        if(isEmpty()) return false;
        l++;
        size--;
        return true;
    }


    public int getSize(){
        return size;
    }

    public void clear(){
        l = 0;
        r = 0;
        size = 0;
    }


}

class elevator{
    private int maxFloor;
    private int minFloor;
    private int nowFloor;
    private int turn; //1 上 2 下 0 止
    private int state;//0 停止 1 移动 2 开门 3 关门

    //l 装载上行  r 装载下行

    public elevator(){
        maxFloor = 1;
        minFloor = 1;
        nowFloor = 1;
        turn = 1;
        state = 0;
    }

    public elevator(int minFloor,int maxFloor){
        this.maxFloor = maxFloor;
        this.minFloor = minFloor;
        nowFloor = Math.max(minFloor, 1);
        this.turn = 1;
        this.state = 0;
    }

    public int getNowFloor() {
        return nowFloor;
    }

    public int getState() {
        return state;
    }

    public int getTurn() {
        return turn;
    }

    public int getMaxFloor() {
        return maxFloor;
    }

    public int getMinFloor() {
        return minFloor;
    }

    public void setMaxFloor(int maxFloor) {
        this.maxFloor = maxFloor;
    }

    public void setMinFloor(int minFloor) {
        this.minFloor = minFloor;
    }

    public void setState(int state) {
        this.state = state;
    }

    public void reverseTurn(){
        this.turn = this.turn == 1 ? 2 : 1;
    }

    public void setTurn(int turn) {
        this.turn = turn;
    }

    public void setNowFloor(int nowFloor) {
        this.nowFloor = nowFloor;
    }

    public boolean checkLegal(Passenger passenger){
        return passenger.getStartFloor() >= this.minFloor
                || passenger.getStartFloor() <= this.maxFloor
                || (passenger.getTargetFloor() == -1 || (passenger.getTargetFloor() >= this.minFloor
                || passenger.getTargetFloor() <= this.maxFloor
        ));
    }
}

class Agent{
    private elevator Elevator;
    private myQue requestOutQueue = new myQue();
    private myQue requestInterQueue = new myQue();
    private Passenger lastRequestOut = null;
    private Passenger lastRequestInter = null;

    public Agent(){

    }

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

    private boolean waitRequest(){
        return requestInterQueue.isEmpty() && requestOutQueue.isEmpty();
    }

    private boolean collectPassenger(Passenger request){
        if(this.Elevator.checkLegal(request)){
            if(request.requestIsOut()){
                this.requestOutQueue.push(request);
            }
            else{
                this.requestInterQueue.push(request);
            }
            return true;
        }
        else return false;
    }

    private void showNowFloorStop(){
        System.out.printf("Open Door # Floor %d\n",Elevator.getNowFloor());
        System.out.print("Close Door\n");
        Elevator.setState(3);
    }

    private void showNowFloorUnstop(){
        String theTurn = Elevator.getTurn() == 1 ? "UP" : "DOWN";
        System.out.printf("Current Floor: %d Direction: %s\n",Elevator.getNowFloor(),theTurn);
    }

    private boolean elevtorMoveUp(){
        if(Elevator.getNowFloor() < Elevator.getMaxFloor()) Elevator.setNowFloor(Elevator.getNowFloor() + 1);
        else return false;
        return true;
    }

    private boolean elevtorMoveDown(){
        if(Elevator.getNowFloor() > Elevator.getMinFloor()) Elevator.setNowFloor(Elevator.getNowFloor() - 1);
        else return false;
        return true;
    }

    public boolean needToContinue(String input){
        if(input.equalsIgnoreCase("end") || input.isEmpty()) return false;
        else{
            Passenger newrequest;
            if(input.matches("<(-?\\d+)(,\\d+)?>")){
                int index = input.indexOf(',');
                int nfloor = 0;
                if(index != -1) {
                    nfloor = Integer.parseInt(input.substring(1,index));
                    int targetFlooor = Integer.parseInt(input.substring(index + 1, input.length() - 1));
                    int nturn = nfloor - targetFlooor > 0 ? 1 : 2;
                    newrequest = new Passenger(nfloor,targetFlooor);
                }
                else{
                    nfloor = Integer.parseInt(input.substring(1,input.length()-1));
                    newrequest = new Passenger(nfloor);
                }
            }
            else{
                return true;
            }
            boolean t;
            boolean isout = newrequest.requestIsOut();
            if(isout){
                if(lastRequestOut == null || !lastRequestOut.isEqual(newrequest)) collectPassenger(newrequest);
                lastRequestOut = newrequest;
            }
            else{
                if(lastRequestInter == null || !lastRequestInter.isEqual(newrequest)) collectPassenger(newrequest);
                lastRequestInter = newrequest;
            }

            return true;
        }
    }

    private Passenger getNextPassenger(){
        if(waitRequest()){
            Elevator.setState(0);
            Elevator.setTurn(0);
            return null;
        }
        Passenger nowrequest = null;
        if(!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()) {
            while (!requestOutQueue.isEmpty() && !requestInterQueue.isEmpty()) {
                int innerturn = requestInterQueue.peek().getStartFloor() - Elevator.getNowFloor() >= 0 ? 1 : 2;
                int outturn = requestOutQueue.peek().getTurn();
                int trueturn = requestOutQueue.peek().getStartFloor() - Elevator.getNowFloor() >= 0 ? 1 : 2;

                if(innerturn == Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    if(Math.abs(requestInterQueue.peek().getStartFloor() - Elevator.getNowFloor())
                            < Math.abs(requestOutQueue.peek().getStartFloor() - Elevator.getNowFloor())){
                        nowrequest = requestInterQueue.peek();
                        requestInterQueue.remove();
                    }
                    else if(Math.abs(requestInterQueue.peek().getStartFloor() - Elevator.getNowFloor())
                            == Math.abs(requestOutQueue.peek().getStartFloor() - Elevator.getNowFloor())){
                        nowrequest = requestInterQueue.peek();
                        requestOutQueue.remove();
                        requestInterQueue.remove();
                    }
                    else{
                        nowrequest = requestOutQueue.peek();
                        requestOutQueue.remove();
                    }
                }
                else if(innerturn == Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    nowrequest = requestOutQueue.peek();
                    requestOutQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn == Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    Elevator.reverseTurn();
                    continue;
                }
                else if(innerturn == Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(innerturn == Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    nowrequest = requestInterQueue.peek();
                    requestInterQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn == Elevator.getTurn()){
                    nowrequest = requestOutQueue.peek();
                    requestOutQueue.remove();
                }
                else if(innerturn != Elevator.getTurn() && outturn != Elevator.getTurn() && trueturn != Elevator.getTurn()){
                    Elevator.reverseTurn();
                    continue;
                }
                break;
            }
        }
        else {
            if (!requestInterQueue.isEmpty()) {
                nowrequest = requestInterQueue.peek();
                requestInterQueue.remove();
            }
            else {
                nowrequest = requestOutQueue.peek();
                requestOutQueue.remove();
            }
        }

        return nowrequest;
    }

    public void mannager(){
        if(waitRequest()){
            Elevator.setState(0);
            Elevator.setTurn(0);
            return;
        }
        Passenger nowrequest;
        while(!waitRequest()){
            nowrequest = getNextPassenger();
            if(nowrequest == null) break;

            Elevator.setTurn(nowrequest.getStartFloor() - Elevator.getNowFloor() >= 0 ?  1 : 2);

            if(Elevator.getState() == 0) {
                if(nowrequest.getStartFloor() != Elevator.getNowFloor()) {
                    showNowFloorUnstop();
                    Elevator.setState(1);
                }
            }
            while(Elevator.getNowFloor() != nowrequest.getStartFloor()){

                boolean again = false;

                if(Elevator.getTurn() == 1) {
                    if (!elevtorMoveUp()) break;
                }
                else {
                    if (!elevtorMoveDown()) break;
                }

                showNowFloorUnstop();
            }

            showNowFloorStop();
            if(nowrequest.requestIsOut()){
                Elevator.setTurn(nowrequest.getTurn());
                collectPassenger(new Passenger(nowrequest.getTargetFloor()));
            }
            if(waitRequest()) Elevator.setState(0);
        }
    }

}

public class Main {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        elevator one = new elevator(input.nextInt(),input.nextInt());

        input.nextLine();

        Agent elevatorMannager = new Agent(one);

        while(elevatorMannager.needToContinue(input.nextLine()));

        elevatorMannager.mannager();
    }
}
2.代码类图:

本次题目集,取消了Request类,增加Passenger类。

3.SourceMonitor分析评估:

SM评估图片如下:

分析评估:

点击查看分析
Lines:代码行数 398 。
Statements:语句数 250 。
Percent Branch Statements:分支语句占比 19.6% 。
Method Call Statements:方法调用语句数 146 。
Percent Lines with Comments:注释行占比仅 0.5% ,说明代码注释严重不足。
结构相关
Classes and Interfaces:类和接口数量为 5 。
Methods per Class:平均每个类的方法数 8.40 。
Average Statements per Method:平均每个方法的语句数 4.45 。
复杂度相关
Line Number of Most Complex Method:最复杂方法在 265 行,方法为 Agent.getNextPassenger() ,最大复杂度达 38 。
Line Number of Deepest Block:最深代码块在 281 行,最大块深度为 6 。
Average Block Depth:平均块深度 2.53 。
Average Complexity:平均复杂度 2.83 。
  • 本次代码优化了类的设计,取消了Request类,Passenger类的增加使得代码更简洁,也符合实际情况。
  • 本次代码的平均块深度与复杂度稍有增加,因为输入格式改动。
  • 代码的最大复杂度仍然较高,未能优化。
V.题目集NCHU_OOP7 总结

在本次题目集中,应题目要求,我取消了Request类,新增Passenger类,使得代码设计更符合实际情况,代码相较与OOP6 更简洁,但我并未对代码性能进行相关优化,导致复杂度上升。

三、踩坑心得

  • 在第一次的题目集中,我由于没有看到对电梯运行逻辑详细阐述的pdf文档,完全自己摸索,导致浪费了许多时间,同时也时初次写这种类型的题目,方法的设计与分工不清晰,导致代码的复杂度大幅度提升,所以一定要了解题目的要求,搞清楚方法与类的分工与职责。同时,在选择数据结构时,第一次采用了优先队列,后更换成普通队列

  • 在第二次的题目集中,由于第一次题目集的判断请求的逻辑简陋,以及与manager方法杂糅在一起,导致我查明错误时花费了大量时间,以至于赶在题目集结束前2小时才完成,所以在设计方法时一定要综合考虑所有情况,完善自己的逻辑。

  • 在第三次的题目集中,由于沿袭前两次的代码,且未能对代码性能进行优化,导致代码的复杂度较高,仍然是失败的代码,所以设计方法时,要不断比较思考,采用最优的算法。

四、改进建议

  • 代码中最好要有注释,以增加代码的可读性
  • 优化乘客判断算法,降低最大复杂度
  • 尽可能遵循单一职责原则,让自己的类设计更加合理,减少耦合度
  • 减少if-else 语句的嵌套,降低代码的深度,提高运行效率
  • 在处理较大的数据量时,静态数组不占优势,且由于队列的特性,不需要随机访问,故可以考虑采用双向链表进行模拟或采用提供的Queue来处理较大的数据量

五、总结

学习总结

经过这几次的迭代的题目集,我在C语言中的面向过程思维,正在逐渐转变为面向对象思维,设计的类之间的关系更加合理,在设计类前,我懂得使用类图来分析类的需求,设计类的方法与属性,从而合理的设计类与类之间的关系,尽可能的朝“高内聚,低耦合”的方向来设计。
与此同时,我也学会了处理较为复杂的问题,能够细分问题,理清核心逻辑,并能够优化代码,使其更加精简。我对Java的正则表达式部分也有了一部分的了解,能够基本使用正则表达式来简化语句,提升效率。

对课程组的建议

  • 希望课程组在题目集的测试点中能够加入相关提示信息,以快速帮助学生定位错误。
  • 希望课程组能够在题目中详细阐述关于题目的具体判断要求,以节省学生的时间来更好地完成题目,设计逻辑,省去不必要的判断逻辑,简化代码。
posted @ 2025-04-19 20:10  一个屑屑  阅读(62)  评论(0)    收藏  举报