OO第一次总结

0.写在最前面的废话

  度量分析的工具真的好难搞!到如今个人metrics也没法正常使用,能够建立它的透视图,可是不能再工程的属性里找到它......得,我如今只能展现类关系图谱(逃)。正则表达式

  OO给个人感受就像是雨夜爬山通常,“爬山”本已举步维艰,大晚上的还漆黑一片,得“边爬边摸索”,要是走了面向过程的“歪路”,也不免重头再来。加之各类条条框框如大雨般倾盆而下,一不当心就弄个“泥泞不堪”,若是不慎落了“无效做业”的大坑,也只能叫苦连天但无力回天。编程

  嗨,这么一写还忽然以为,OO有点意思。数组

1.第一次做业

  第一次做业是要写多项式的加减,个人程序的大致结构以下:多线程

其中,Main是主类,负责调用其余的类,并运行程序;框架

Check类是用来检测输入的字符串是否合法的,在这里主要使用了正则表达式来判断;函数

Operation类是用来实现多项式加减的,主要是一个大循环,一个字符一个字符向后读。工具

 

  第一次做业的公测错了两个点,互测没出问题,第一个是爆栈,缘由是个人正则表达式就是一个长串来匹配整个的输入,致使在最大长度的输入状况下程序出了问题。把输入的几十个多项式按花括号拆开,再进行正则匹配便可解决。测试

  第二个点是没有考虑-0仍是什么关于正负号的一个小点,后来仔细阅读指导书后,大呼之遂心服口服,这很好的提醒了我在之后的做业中要仔细考虑各类状况以及仔细阅读指导书,勤于思考各类非法的状况。spa

  

  个人第一次做业的代码量比较少,可能勉强算是一个有点,但第一次写面向对象的程序,老是有些四不像的感受,不会使用构造函数,把全部的功能都放在了类的方法中,形似面向过程。线程

 

2.第二次做业

  第二次做业是写一个服从“傻瓜调度”的电梯,即根据指令的时间顺序来控制电梯的运动,个人程序的大致结构以下:

 

其中,Request类是用来处理单条需求的,经过正则表达式判断指令是否合法,进而判断指令是哪一种类型(FR+UP,FR+DOWN,ER),而后将指令分解,分别去判断时间和楼层是否越界。由于考虑到时间可能超过int型的范围而且会有不少的前导零,我用了一个循环来算时间...

for(int i=0; i<s.length; i++ ) {
            if(s[i]!= '+') {
                NowTime *= 10;
                NowTime += (s[i] - '0');
            }
        }

 

Queue类是用来循环读入指令的,调用了Request类,对单条指令进行处理,并把它们分别存在对应的数组中。

Elevator类是用来记录电梯的运行状态的,包括电梯如今所处的楼层,下一个楼层,当前时间,下一个时间,电梯运行时间,运行状态等。

Floor类是用来记录楼层信息的,但其实实际操做中我几乎没用到它,由于Elevator类里的东西就够用了。

Scheduler类是用来执行电梯调度的,实例化了Queue类的对象来读入指令,也实例化了Elevator类的对象来记录电梯的运行状态,并设置了一些其余的属性来模拟电梯的运行。

    private double[] ERButton = new double[20];
    private double[] FRUPButton = new double[20];
    private double[] FRDOWNButton = new double[20];

上面三个按钮数组用来模拟电梯里面和楼层上的按钮。开始时我想用boolean型的数组,可是发现那样只能记录按钮的状态,不能记录按钮状态改变的时间,因此我后来改用double型,记录每一个按钮被释放的时间,即这个按钮在哪个时刻能够被再次使用,在这个时刻以前,若是有人发出了须要这个按钮的指令,则被视为同质指令。

        if(queue.RequestTypeArray[valid] == 1) {
                    if(queue.TimeArray[valid] <= FRUPButton[queue.FloorArray[valid]]) {
                        System.out.println("#This input is similar:"+(queue.InputArray[i]));
                        IfSimilar = true;
                    }
                }

拿一段代码来讲明,好比一条指令的类型为1(FR+UP),那么比较读入指令的发出时刻与该指令的对应按钮的释放时间,就能够判断这条指令是否是同质(在这以前先判断是否合法)。这样就不须要预先知道后面的指令是什么,简化了代码的复杂度。

若是它不一样质,那么就能够产生一个对应的输出,并改变某个按钮的释放时间,部分代码以下:

            if(queue.RequestTypeArray[valid] == 1) {
                        FRUPButton[queue.FloorArray[valid]] = elevator.NextTime;
                    }

好比这条指令的类型是1,那么就将FRButton中对应按钮的时间设置为elevator.NextTime(即通过计算后的电梯达到下一个楼层的时间),这样就可让程序不断的循环运做了~

 

  第二次做业的公测我没有错测试点,互测错了一个,是:输出若是超过了int范围而且是小数,那么个人输出就会把它的小数部分给省略掉,后来我寻找缘由,发如今这个地方:

System.out.print(BigDecimal.valueOf(elevator.NextTime));

  我为了使输出不是科学记数法的形式,我用了BigDecimal,但不知为啥这里会出这样的幺蛾子......

  

  第二次做业我花了好久的时间去思考,主要在想如何去判断各类同质的情况,后来通过不断的摸索,而且有意识地去模拟真实电梯的属性和方法(在我理解里的面向对象吧),我选择用按钮这个概念来记录电梯的被触发不一样状态后的终止时刻,想明白了这个以后再去写代码就顺畅了许多。有了此次的经验,我在写第三次做业以前花了更多的时间去思考。

 

3.第三次做业

  第三次做业的电梯是在第二次做业的基础上考虑“捎带”这一规则,我本觉得只须要小改一下就成,后来在实际操做中我才发现本身错的离谱......先展现一下程序的大致结构:

 

其中,除了SubScheduler类之外,其余几个类与第二次做业基本相同,不赘述;

SubScheduler是继承了Scheduler父类的子类,说来惭愧,我此次做业几乎只干了一件事儿:重写了Scheduler父类的Run函数......

由于电梯要捎带,那么电梯的运行就不能只是发生在相邻的两条指令之间了,由于后面的指令或者时刻靠后的指令彻底有可能要先执行,判断哪些指令要先执行就是最大的难点所在。我先很天然地想到咱们使用的电梯是什么样的,在运动到某一楼层前,若是接收到这个楼层发出的信号,若是方向相同即可以停靠,那么关键点有两个,一个是位置,一个是时间。我最初想到的是以时间为主线,直接以0.5s为最小的度量,每过0.5秒记录电梯的位置和运行状态,而后去队列中搜索有没有这个时刻或以前发出的同层的指令,后来由于各类考虑放弃之。

因而便选择了先遍历一下读入指令后面的指令,若是这条指令知足可捎带的条件,执行之,而后把它从请求队列中剔除,并改变一些按钮被释放的时间以及楼层、到达时刻等属性,其中一部分大概像下面这样:

else if(elevator.Condition.equals("UP")) {
                            if(queue.RequestTypeArray[j] == 1) {
                                if((queue.FloorArray[j] <= MaxFloor) && (queue.FloorArray[j] > elevator.NowFloor)) {
                                    ExtraTime = (queue.FloorArray[j] - elevator.NowFloor)*0.5;
                                    for(int k=(elevator.NowFloor); k<(queue.FloorArray[j]); k++) {
                                        ExtraTime += ExtraFloorArray[k];
                                    }
                                    if(queue.TimeArray[j] < (elevator.NowTime + ExtraTime)) {
                                        if(queue.TimeArray[j] <= FRUPButton[queue.FloorArray[j]] ) {
                                            //同质
                                            UsedArray[j] = true;
                                            System.out.println("#SAME["+(queue.ValidArray[j])+"]");
                                        }
                                        else {
                                            FRUPButton[queue.FloorArray[j]] = (elevator.NowTime + ExtraTime);
                                            ExtraFloorArray[queue.FloorArray[j]] = 1.0;
                                            //加入捎带的额外数组
                                            UsedArray[j] = true;
                                            ExtraConditionArray[queue.FloorArray[j]] = "UP";
                                            ExtraOrderArray[queue.FloorArray[j]][ExtraSameNumberArray[queue.FloorArray[j]]] = j;
                                            ExtraSameNumberArray[queue.FloorArray[j]]++;
                                        }
                                    }
                                }
                            }

很繁琐,分了电梯运行的各类状态以及指令的各类类型来分类讨论,这里把主指令以后的指令存入一个新的数组中,而不是直接输出,由于它后面还可能有比它还要提早执行的指令,因此输出也变得很繁琐了......

                    if(elevator.Condition.equals("UP")) {
                        for(int m=elevator.NowFloor; m<=MaxFloor; m++) {
                            if(ExtraFloorArray[m] == 1.0) {
                                for(int n=0; n<ExtraSameNumberArray[m]; n++) {
                                    if(queue.RequestTypeArray[ExtraOrderArray[m][n]] == 1) {
                                        System.out.print("[FR,");
                                        System.out.print(queue.FloorArray[ExtraOrderArray[m][n]]);
                                        System.out.print(",UP,");
                                        System.out.print(queue.TimeArray[ExtraOrderArray[m][n]]);
                                        System.out.print("]/(");
                                        System.out.print(m);
                                        System.out.print(",");
                                        System.out.print(ExtraConditionArray[m]);
                                        System.out.print(",");
                                        System.out.print(BigDecimal.valueOf(RunTime));
                                        System.out.println(")");
                                    }

我在主请求结束后进行这个输出的循环,大致思路是上面的程序段记录了每一个楼层的停靠状态,以后遍历楼层,把有标记的楼层按要求输出。这是一种以位置为主轴的方法吧。由于一层楼中可能会开若干次门,因此只能创建一个二维数组ExtraOrderArray来记录某层楼的可能出现的若干次开门的请求。

 

  很幸运,第三次做业的公测和互测都没有出BUG,能够说是很振奋人心了。但想到以后要写多线程的电梯,感受程序不免仍是要修改,仍是很使人头大。

  此次做业虽然重点只是放在了重写Run函数上,但周六日两天刚好有事情不能写OO,结果致使个人周一二三过的至关艰难,通宵数宿,苦不堪言,不堪回首,触目惊心......想不想得清楚是一方面,更重要的是一些小的细节的改动会牵一发而动全身,原本想要微调结果不得不大刀阔斧的改一通,其中折磨可想而知。这也让我吸收到了很宝贵的经验:1、拖延症害死人,能早点解决的事儿别把它养肥了;2、磨刀不误砍柴工,在头脑清醒时先把问题想清楚,方法想完善,必要时能够手写一下流程框架图什么的,这样说不定就能事半功倍。

 

  总的来讲,OO仍是让人收获颇丰的,别的不说,就是之后得去“搬砖”,基本的编程能力仍是要有的,毋庸置疑,OO锻炼了个人编程能力;其次,在思考和对问题的分析上,我能够有意识地用面向对象的思路去思考问题(或许我还并不能正确认识什么是面向对象),这是一种有趣的思考过程,我总感受这样幻想出来的对象还有点可爱......

  最后祝你们永不被判无效做业!实在太痛了,也但愿之后的OO能升级一下无效做业的判断机制吧。

相关文章
相关标签/搜索