这次的作业和以往不同,按照老师的要求,我们要进行结对编程的练习。所谓结对编程相信各位都不会陌生,这里不在赘述。

  首先介绍下我的小伙伴,很幸运的是我的队友也是我的室友---樊西江,这为我们合作提供了很大的便利。

  其次说下项目的描述与实现的办法,问题如下

  

电梯调度

现有一新建办公大厦,共有21层,共有四部电梯,所有电梯基本参数如下表所示:

电梯编号

可服务楼层

最大乘客数量

最大载重量

1

全部楼层

10

800 kg

2

单层

10

800 kg

3

双层

20

1600 kg

4

全部楼层

20

2000 kg

其使用规定如下:

1、楼层号为0~20,其中0号为地下一层;

2、有楼层限制的电梯不在响应楼层停靠,如单双层;

3、所有电梯采用统一按钮控制

  对于这个项目,我俩决定采用java语言编写,原因如下:我们对C/C++的掌握程度不够精深,和现学现卖的JAVA差不了太多,而且我们想要做出一个拥有图形化界面的程序,仅靠我们所有的C以及C++是无法满足的,时间所限现学其他的语言变得很困难。

  接下来简单介绍下软件开发中遇到的问题以及整体思路实现。

  有了C++面向对象的基础,使我们在面对java语言的面向对象用的更加得心应手,当然,问题也是大大的有。首先是类的设计,类的属性和方法随着需求一点点变化越加越多,代码也一度出过问题,我俩经过多次分析才最终化繁为简,将代码优化到可以容易看懂的地步。面对这个电梯调度问题,电梯类必不可少,其次是控制类,以及主函数,当然还有我们最想实现的,图形化界面。

  首先说下界面的布置,这里我们将界面布置的和现实中的电梯类似,一个输入框用来键入人所在楼层,以及用来获取目标楼层的输入框,两个按钮,分别向上和向下,四个显示框用来输出电梯的信息。整体布局如下:

  

  实现代码如下:

 1 // 定义图形化界面引用
 2     private Frame f;
 3     private Button butUp;//上升按钮
 4     private Button butDown;//下降按钮
 5     private Label lab1;//当前楼层说明
 6     private Label lab2;//目的楼层说明
 7     private TextField personFloor;//人所在楼层
 8     private TextField personToFloor; //人的目标楼层
 9     private TextArea screen1;//显示信息
10     private TextArea screen2;//显示信息
11     private TextArea screen3;//显示信息
12     private TextArea screen4;//显示信息

界面声明部分

 1 public void init()//图形界面初始化
 2     {
 3         f = new Frame("Elevator dispatching");
 4         f.setSize(400,400);
 5         f.setLayout(new FlowLayout());
 6         f.setResizable(false);//窗体固定
 7         f.setLocationRelativeTo(null);//窗体居中
 8
 9         lab1 = new Label("当前楼层");
10         lab2 = new Label("目的楼层");
11
12         personFloor = new TextField("",10);
13         personToFloor = new TextField("",10);
14
15         butUp = new Button("↑");
16         butDown = new Button("↓");
17
18
19         screen1 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);
20         screen2 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);
21         screen3 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);
22         screen4 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);
23
24         screen1.setEditable(false);
25         screen2.setEditable(false);
26         screen3.setEditable(false);
27         screen4.setEditable(false);
28
29         f.add(lab1);
30         f.add(personFloor);
31         f.add(butUp);
32         f.add(butDown);
33         f.add(lab2);
34         f.add(personToFloor);
35         f.add(screen1);
36         f.add(screen2);
37         f.add(screen3);
38         f.add(screen4);
39
40         myEvent();//添加事件
41
42         f.setVisible(true);
43     }

图形界面初始化

  其次是类的设计与实现

  1、Elevator类

    电梯类用以描述电梯的属性以及方法,用以实体化电梯以供使用。

    电梯的主要属性:编号、种类(单双层)、所在楼层、目标楼层等等。

    电梯类的方法:

      构造函数对属性值进行初始化

      void add()方法,根据指令将人所在的楼层和人要去的楼层加入Elevator的目标队列中。其中Elevator类的toFloors[]为数组,用来存储电梯的目的楼层,start和end为其指针。判断逻辑如下:如当前目标楼层数目为1或者0时,无需判断,直接将二者加入电梯目标队列中;否则,判断人和电梯的方向异同,若相同,则判断具体方向,最后判断人与电梯目标段的位置,在目标段之外(之上或之下)以及在目标段之内,根据判断将人所在的楼层和人要去的楼层加入Evelator类toFloors[]中的相应位置,并移动指针end。如果电梯和人的方向不同,无需判断,直接将二者顺序加入Elevator类toFloors[]中即可;

      void run()方法,电梯动起来的方法,判断目标队列的元素数,如果start!=end 表明电梯仍需运行,这时根据目标队列的start楼层和电梯当前楼层,将电梯的运行状态改变,并将电梯的当前楼层++或者--,当电梯的当前楼层 == 电梯的start楼层时,输出提醒,将电梯运行状态置为0,并将start后移。

      int countDistance() 方法,后加入的方法,主要用来计算电梯相应按钮指令所需要的时间(这里用距离来表示),返回值为距离的具体值,首先判断特殊情况,即单层电梯响应双层按钮或双层电梯相应单层按钮的距离,无需判断,返回一个最大值(100)即可。否则的话根据具体情况判断,首先电梯的情况有三,目标楼层为空,电梯静止。目标楼层数为大于2,这时根据最后的情况判断距离,这种情况和目标楼层数为1时相同。判断距离的判断方法和电梯的run方法雷同,将情况分为可见的几种情况,逐步实现,这里刚开始为难了我俩好久。后来我们逐步分析,将情况分为了可以解决的小情况。

      void show()方法,展示函数,将电梯的信息输出,输出电梯的当前楼层和运行状态,直接将电梯类的属性值输出即可。

  1 class Elevator
  2 {
  3     private int id;//电梯编号
  4     private int maxLoadWeight;//最大载重
  5     private int loadWeight;//当前重量
  6     private int state;//0:全层 1:单层 2:双层
  7     private int floor; //电梯当前楼层
  8     private int runState;//电梯运行状态 0--不动       1--向上    -1--向下
  9     private int[] toFloors;//电梯目标楼层
 10     private int start,end;
 11     private String info;//电梯信息
 12
 13     Elevator(int id, int maxLoadWeight, int state){
 14         this.id = id;
 15         this.maxLoadWeight = maxLoadWeight;
 16         this.loadWeight = 0;
 17         this.state = state;
 18         this.setFloor(1);
 19         this.setRunState(0);
 20         toFloors = new int[20];
 21         this.start = 0;
 22         this.end = 0;
 23     }
 24
 25     public int countDistance(int personFloor, int runDirection)//判断电梯->人的距离
 26     {
 27         if(state ==1 && (personFloor%2)==0)
 28             return 100;
 29         if(state ==2 && (personFloor%2)==1)
 30             return 100;
 31         if(end == start)
 32             return Math.abs(personFloor - floor);
 33         else if(end-start ==1){//电梯目标值为1个
 34             if(toFloors[end-1] > floor){//电梯上升
 35                 if(1 == runDirection){//人上升    三种情况
 36                     if(personFloor < floor){
 37                         return (toFloors[end-1]-floor)*2+(floor-personFloor);
 38                     }else{
 39                         return personFloor-floor;
 40                     }
 41                 }else{//人下降  三种情况
 42                     if(personFloor>toFloors[end-1]){
 43                         return personFloor-floor;
 44                     }else if(personFloor < floor){
 45                         return (toFloors[end-1]-floor)*2+(floor-personFloor);
 46                     }else{
 47                         return (toFloors[end-1]-floor)+(personFloor-floor);
 48                     }
 49                 }
 50             }else{//电梯下降
 51                 if(1 == runDirection){//人上升
 52                     if(personFloor>floor){
 53                         return (floor-toFloors[end-1])*2+(personFloor-floor);
 54                     }else if(personFloor < toFloors[end-1]){
 55                         return floor-personFloor;
 56                     }else{
 57                         return (floor-toFloors[end-1])+(personFloor-toFloors[end-1]);
 58                     }
 59                 }else{//人下降
 60                     if(personFloor>floor){
 61                         return (floor-toFloors[end-1])*2+(personFloor-floor);
 62                     }else if(personFloor < toFloors[end-1]){
 63                         return floor-personFloor;
 64                     }
 65                 }
 66             }
 67         }else{//电梯目标值为两个以上
 68             if(toFloors[end-1] >toFloors[end-2]){//电梯最终状态为上升
 69                 if(1 == runDirection){//人上升    三种情况
 70                     if(personFloor < toFloors[end-2]){
 71                         return (toFloors[end-1]-toFloors[end-2])*2+(toFloors[end-2]-personFloor);
 72                     }else{
 73                         return personFloor-toFloors[end-2];
 74                     }
 75                 }else{//人下降  三种情况
 76                     if(personFloor>toFloors[end-1]){
 77                         return personFloor-toFloors[end-2];
 78                     }else if(personFloor < toFloors[end-2]){
 79                         return (toFloors[end-1]-toFloors[end-2])*2+(toFloors[end-2]-personFloor);
 80                     }else{
 81                         return (toFloors[end-1]-toFloors[end-2])+(personFloor-toFloors[end-2]);
 82                     }
 83                 }
 84             }else{//电梯最终状态为下降
 85                 if(1 == runDirection){//人上升
 86                     if(personFloor>toFloors[end-2]){
 87                         return (toFloors[end-2]-toFloors[end-1])*2+(personFloor-toFloors[end-2]);
 88                     }else if(personFloor < toFloors[end-1]){
 89                         return toFloors[end-2]-personFloor;
 90                     }else{
 91                         return (toFloors[end-2]-toFloors[end-1])+(personFloor-toFloors[end-1]);
 92                     }
 93                 }else{//人下降
 94                     if(personFloor>toFloors[end-2]){
 95                         return (floor-toFloors[end-1])*2+(personFloor-toFloors[end-2]);
 96                     }else if(personFloor < toFloors[end-1]){
 97                         return toFloors[end-2]-personFloor;
 98                     }
 99                 }
100             }
101         }
102         return -100;//防止出错判断
103     }
104
105
106     public void add(int personFloor, int runDirection,int toFloor)
107     {
108         if (end - start > 0)//电梯目标楼层大于0个
109         {
110             if ((toFloors[end-1] - toFloors[end - 2])*runDirection > 0) {//人和电梯同方向
111                 if (1 == runDirection)//同向上
112                 {
113                     if (personFloor > toFloors[end - 1])//人所在楼层 高于 电梯去的最高楼层
114                     {
115                         toFloors[(end++) % 20] = personFloor;
116                         toFloors[(end++) % 20] = toFloor;
117                     }else {//人所在楼层 低于 电梯去的最高楼层
118                         toFloors[end] = toFloors[(end++)%20 -1];
119                         toFloors[end - 2] = personFloor;
120                         if (toFloor > toFloors[end - 1])//人要去楼层高于电梯所在楼层
121                             toFloors[(end++) % 20] = toFloor;
122                         else{    //人要去楼层低于电梯所在楼层
123                             toFloors[end] = toFloors[end - 1];
124                             toFloors[end - 1] = toFloor;
125                             end = (end++) % 20;
126                         }
127
128                     }
129                 }
130                 else {//同向下
131                     if (personFloor < toFloors[end - 1])//人所在楼层 低于 电梯去的最高楼层
132                     {
133                         toFloors[(end++) % 20] = personFloor;
134                         toFloors[(end++) % 20] = toFloor;
135                     }
136                     else {//人所在楼层 高于 电梯去的最低楼层
137                         toFloors[end] = toFloors[end - 1];
138                         toFloors[end - 1] = personFloor;
139                         end = (end++)%20;
140                         if (toFloor < toFloors[end - 1])//人要去楼层低于电梯所在楼层
141                             toFloors[(end++) % 20] = toFloor;
142                         else {    //人要去楼层高于电梯所在楼层
143                             toFloors[end] = toFloors[end - 1];
144                             toFloors[end - 1] = toFloor;
145                             end = (end++) % 20;
146                         }
147                     }
148                 }
149
150             }
151             else {//反方向
152                 toFloors[(end++) % 20] = personFloor;
153                 toFloors[(end++) % 20] = toFloor;
154             }
155         }
156         else//电梯目标楼层数量为1或者0
157         {
158             toFloors[(end++) % 20] = personFloor;
159             toFloors[(end++) % 20] = toFloor;
160         }
161     }
162
163
164     public void run()throws Exception//电梯运行
165     {
166         if (start != end)//需要运行
167         {
168             if (floor < toFloors[start])//向上
169             {
170                 runState = 1;
171                 floor++;
172             }
173             else if (floor > toFloors[start])//向下
174             {
175                 runState = -1;
176                 floor--;
177             }
178             else//floor = toFloors[start] 到目的地
179             {
180                 System.out.println("电梯"+id+" 已到达到达目的地:"+floor);
181
182                 runState = 0;
183                 start = (start+1)%20;
184             }
185         }
186     }
187
188     public String show(){
189         info = id+"'s Elevator \non "+floor+"'s floor\nis ";
190         if(1 == runState)
191             return info+" ↑";
192         if(-1 == runState)
193             return info+" ↓";
194         return info+" -- ";
195
196     }
197
198     public int getRunState() {
199         return runState;
200     }
201
202     public void setRunState(int runState) {
203         this.runState = runState;
204     }
205
206     public int getFloor() {
207         return floor;
208     }
209
210     public void setFloor(int floor) {
211         this.floor = floor;
212     }
213 }

Elevator类

  2、Controller类

    控制器类,用以开启多线程,以及控制电梯的运行。

    控制器属性,电梯类的指针以及用以接收电梯类输出信息的字符串。

    控制器方法:

       不多说,开启多线成的两种方法,继承Thread和实现Runnable接口,无论哪种都需要覆盖的run方法。这个方法里调用电梯类的run方法后,用info接收电梯类的输出信息,以供主函数用来更新界面显示。

 1 class Controller implements Runnable
 2 {
 3     Elevator Elevator = null;
 4     String info = null;
 5     Controller(Elevator e)
 6     {
 7         this.Elevator = e;
 8     }
 9
10     public String getInfo(){
11         return info;
12     }
13     public void run()//控制器执行,调度电梯
14     {
15         while(true)//里面保持每个电梯的运行
16         {
17             try {
18                 Elevator.run();
19                 info = Elevator.show();
20             } catch (Exception e1) {
21                 // TODO 自动生成的 catch 块
22                 e1.printStackTrace();
23             }
24             try {
25                 Thread.sleep(3000);
26             } catch (InterruptedException e) {
27                 // TODO 自动生成的 catch 块
28                 e.printStackTrace();
29             }
30         }
31     }
32 }

Controller类

  3、主函数

    属性:界面控件,以及用来判断按钮的静态量 order

    方法:

      构造方法:执行界面的初始化、order的置零以及自定义的执行方法myRun();

      init() 图形界面初始化函数

      boolean isBetween20()用来判断输入数据的合法性所用到的小函数,当值不在0-20之间时返回false

      boolean isCorrect() 判断输入数据的合法性,例如向上时,人要去的楼层应该比人所在的楼层高,等等常识性问题的判断。

      int whoIsRun()  用来判断最优电梯方案,调用四个电梯的计算函数,计算距离,参数传入,封装成数组,找到最小距离后返回下标,利用返回值调用相应电梯做相应的调度。

      myEvent() 方法,用来为界面控件添加事件监听,当两个输入框输入非法字符时(非数字和删除键),控制台打印警告,不予录入。当两个按钮按下时,用isCorrect函数判断输入的合法性,如果合法,将order分别置为1或者-1,否则置零,视为此次输入无效。

  接下来说一下遇到的问题以及解决方案

    1、首先就是主函数的问题,由于主函数是静态的,无法访问非静态的变量和方法,所以我们采取了在主函数的构造函数中调用自己构建好的一个方法,主函数中创建这个自己的类即可实现。

    2、命令的传递问题,最初打算在按钮事件中直接调用电梯类的方法将目标楼层直接录入,后来发现以我们的水准无法实现,于是采用折中的办法,在主函数(myRun())d 循环中检察order的状态,并在按钮时间中更改order状态,以此来判断按钮以及调用电梯的方法,执行最优方案将目标楼层加入电梯的目标序列中。

    3、最优电梯方案,这个我们想了最久,也是最后实现的并且实现的不彻底,最优的方案应该是最令用户满意的方案,也就是说按了按钮以后电梯可以最快到达的方案。于是我们采用计算距离的方式,用距离最短的电梯去接人。

    4、由于采取了数组的方式存储电梯的目标序列,导致很难判断哪个楼层为上、哪个楼层为下,所以上多少人以及判断体重的功能我们还没彻底实现,由于时间关系我们只好写到这里,后续过程一定会实现它。

总结:

  首先感谢老师给的这次机会,让我对队友有了更深的理解,相信其他人应该也是如此。在这不短的时间里,两个人合作做成一件事情,虽然它不是多么难,多么的累,但仍然是一件让人感到满足感的事情。

  在这里简单评价下我的队友,虽然经验可能稍微缺少些,但是学习的精神很足,使用他所不擅长的语言他也没放弃过,一直为这个项目努力着并在其中扮演着重要的角色。代码的编写并没有按照时间轮转,而是根据我俩谁更想写哪里,我想写的我擅长写的我去写,他擅长写的他去写,期间我们的讨论对于解决问题发挥了很大作用。对于代码复审,在我编程期间他没有表现出一点的不耐,这令我非常佩服。我相信我写代码的过程比他听一篇没有意义的演讲更令人困倦,他的坚持令我汗颜,希望他不仅局限于这次结对编程,在以后的学习生活中还可以如同现在一般投入。

  最后说说我的感受,通过软件工程这门课,我们可以学习到很多课本上无法学习到的东西,软件的实际开发流程、软件开发团队的类型等等,这次的课程通过老师的讲解以及课下的作业练习,让我们的编程能力得以锻炼,通过解决遇到的问题,也使得我们在今后面对问题时有了可以战胜的信心,相信这对我们以后的发展是很有利的。这次的软件工程作业也令我对所学的知识运用的更加得心用手,再次让我明白,实践出真知,谢谢老师~

  附录:
    工作照:

    

    程序运行图:

    

    

    

    源码:

      

  1 package cn.sau.homework;2 3 import java.awt.*;4 import java.awt.event.*;5 6 public class Main {7     // 定义图形化界面引用8     private Frame f;9     private Button butUp;//上升按钮10     private Button butDown;//下降按钮11     private Label lab1;//当前楼层说明12     private Label lab2;//目的楼层说明13     private TextField personFloor;//人所在楼层14     private TextField personToFloor; //人的目标楼层15     private TextArea screen1;//显示信息16     private TextArea screen2;//显示信息17     private TextArea screen3;//显示信息18     private TextArea screen4;//显示信息19     20     private static int order; //有无按钮提示  0:无  1:↑ -1:↓21 22     23     24     Main()25     {26         order = 0;27         init();    28         myRun();29     }30     31     public void init()//图形界面初始化32     {33         f = new Frame("Elevator dispatching");34         f.setSize(400,400);35         f.setLayout(new FlowLayout());36         f.setResizable(false);//窗体固定37         f.setLocationRelativeTo(null);//窗体居中38         39         lab1 = new Label("当前楼层");40         lab2 = new Label("目的楼层");41         42         personFloor = new TextField("",10);43         personToFloor = new TextField("",10);44         45         butUp = new Button("↑");46         butDown = new Button("↓");47 48         49         screen1 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);50         screen2 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);51         screen3 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);52         screen4 = new TextArea("显示屏",5,10,TextArea.SCROLLBARS_NONE);53         54         screen1.setEditable(false);55         screen2.setEditable(false);56         screen3.setEditable(false);57         screen4.setEditable(false);58         59         f.add(lab1);60         f.add(personFloor);61         f.add(butUp);62         f.add(butDown);63         f.add(lab2);64         f.add(personToFloor);65         f.add(screen1);66         f.add(screen2);67         f.add(screen3);68         f.add(screen4);69         70         myEvent();//添加事件71         72         f.setVisible(true);73     }74     75     public boolean isBetween20(int floor){76         if(floor>=0 && floor <=20)77             return true;78         return false;79     }80     81     public boolean isCorrect(int order,int floor,int toFloor)//判断输入是否合法82     {83         if(1 == order){//电梯向上84             if(!isBetween20(floor))85             {86                 System.out.println("你在这??      "+floor+"");87                 return false;88             }89             if(!isBetween20(toFloor))90             {91                 System.out.println("你要去这??   "+floor);92                 return false;93             }94             if(toFloor <= floor){95                 System.out.println("你确定是要上楼? 从  "+floor+"-> "+toFloor);96                 return false;97             }98             return true;99         }else{//电梯向下
100             if(!isBetween20(floor))
101             {
102                 System.out.println("你在这??      "+floor+"");
103                 return false;
104             }
105             if(!isBetween20(toFloor))
106             {
107                 System.out.println("你要去这?  "+floor);
108                 return false;
109             }
110             if(toFloor >= floor){
111                 System.out.println("你确定是要下楼? from  "+floor+" to "+toFloor);
112                 return false;
113             }
114             return true;
115         }
116     }
117
118     public int whoIsRun(int e1Distance,int e2Distance,int e3Distance,int e4Distance){//根据传入参数判断哪个电梯最优
119         int[] arr = new int[]{e1Distance,e2Distance,e3Distance,e4Distance};
120         int index=0;
121         for(int i=1;i<4;i++){
122             if(arr[index]>arr[i])
123                 index = i;
124         }
125         return index+1;
126     }
127
128     private void myEvent(){//创建事件监听
129         f.addWindowListener(new WindowAdapter(){
130             public void windowClosing(WindowEvent e){
131                 System.exit(0);
132             }
133         });
134
135         personFloor.addKeyListener(new KeyAdapter(){
136             public void keyPressed(KeyEvent e){
137
138                 int code = e.getKeyCode();
139                 if(!(code>=KeyEvent.VK_0 && code <= KeyEvent.VK_9 || code==8))
140                 {
141                     System.out.println(code+"... 是非法的");
142                     e.consume();
143                 }
144             }
145         });
146
147         personToFloor.addKeyListener(new KeyAdapter(){
148             public void keyPressed(KeyEvent e){
149                 int code = e.getKeyCode();
150                 if(!(code>=KeyEvent.VK_0 && code <= KeyEvent.VK_9 || code==8))
151                 {
152                     System.out.println(code+"... 是非法的");
153                     e.consume();
154                 }
155             }
156         });
157
158         butUp.addActionListener(new ActionListener(){//上升按钮
159             public void actionPerformed(ActionEvent e){
160                 int personF = new Integer(personFloor.getText());
161                 int personTF = new Integer(personToFloor.getText());
162                 if(isCorrect(1,personF,personTF))
163                 {
164                     order = 1;
165                 }
166                 else
167                     order = 0;
168                 System.out.println("上升按钮按下");
169             }
170         });
171
172         butDown.addActionListener(new ActionListener(){//下降按钮
173             public void actionPerformed(ActionEvent e){
174                 int personF = new Integer(personFloor.getText());
175                 int personTF = new Integer(personToFloor.getText());
176                 if(isCorrect(-1,personF,personTF))
177                 {
178                     order = -1;
179                 }
180                 else
181                     order = 0;
182                 System.out.println("下降按钮按下");
183             }
184         });
185     }
186
187
188     public void myRun()//为了调用非静态方法自创的主函数~
189     {
190
191         Elevator e1 = new Elevator(1,800,0);
192         Elevator e2 = new Elevator(2,800,1);
193         Elevator e3 = new Elevator(3,1600,2);
194         Elevator e4 = new Elevator(4,2000,0);
195         Controller controller1 = new Controller(e1);
196         Controller controller2 = new Controller(e2);
197         Controller controller3 = new Controller(e3);
198         Controller controller4 = new Controller(e4);
199
200         Thread t1 = new Thread(controller1);
201         Thread t2 = new Thread(controller2);
202         Thread t3 = new Thread(controller3);
203         Thread t4 = new Thread(controller4);
204
205         //开启电梯控制器
206         t1.start();
207         t2.start();
208         t3.start();
209         t4.start();
210
211         while(true)//接收命令
212         {
213             try {
214                 Thread.sleep(2000);
215             } catch (InterruptedException e) {
216                 // TODO 自动生成的 catch块
217                 e.printStackTrace();
218             }
219
220             //逻辑判断,哪个电梯拥有最短路径哪个电梯去接人
221             if(1 == order){//上升按钮
222                 int personF = new Integer(personFloor.getText());
223                 int personTF = new Integer(personToFloor.getText());
224
225                 //逻辑判断 电梯最优方案
226                 int e1Distance = e1.countDistance(personF, order);
227                 int e2Distance = e2.countDistance(personF, order);
228                 int e3Distance = e3.countDistance(personF, order);
229                 int e4Distance = e4.countDistance(personF, order);
230                 int result = whoIsRun(e1Distance,e2Distance,e3Distance,e4Distance);
231                 switch(result){
232                     case 1:
233                         e1.add(personF, order, personTF);
234                         break;
235                     case 2:
236                         e2.add(personF, order, personTF);
237                         break;
238                     case 3:
239                         e3.add(personF, order, personTF);
240                         break;
241                     case 4:
242                         e4.add(personF, order, personTF);
243                         break;
244
245                 }
246
247                 order = 0;
248             }
249             else if(-1 == order)//下降按钮
250             {
251                 int personF = new Integer(personFloor.getText());
252                 int personTF = new Integer(personToFloor.getText());
253
254
255                 //逻辑判断 电梯最优方案
256                 int e1Distance = e1.countDistance(personF, order);
257                 int e2Distance = e2.countDistance(personF, order);
258                 int e3Distance = e3.countDistance(personF, order);
259                 int e4Distance = e4.countDistance(personF, order);
260                 int result = whoIsRun(e1Distance,e2Distance,e3Distance,e4Distance);
261                 switch(result){
262                     case 1:
263                         e1.add(personF, order, personTF);
264                         break;
265                     case 2:
266                         e2.add(personF, order, personTF);
267                         break;
268                     case 3:
269                         e3.add(personF, order, personTF);
270                         break;
271                     case 4:
272                         e4.add(personF, order, personTF);
273                         break;
274
275                 }
276
277                 order = 0;
278             }
279             //清理屏幕
280             screen1.setText(controller1.getInfo());
281             screen2.setText(controller2.getInfo());
282             screen3.setText(controller3.getInfo());
283             screen4.setText(controller4.getInfo());
284         }
285     }
286
287
288     public static void main(String[] args) {
289         new Main();
290     }
291 }
292
293 class Controller implements Runnable
294 {
295     Elevator Elevator = null;
296     String info = null;
297     Controller(Elevator e)
298     {
299         this.Elevator = e;
300     }
301
302     public String getInfo(){
303         return info;
304     }
305     public void run()//控制器执行,调度电梯
306     {
307         while(true)//里面保持每个电梯的运行
308         {
309             try {
310                 Elevator.run();
311                 info = Elevator.show();
312             } catch (Exception e1) {
313                 // TODO 自动生成的 catch 块
314                 e1.printStackTrace();
315             }
316             try {
317                 Thread.sleep(3000);
318             } catch (InterruptedException e) {
319                 // TODO 自动生成的 catch 块
320                 e.printStackTrace();
321             }
322         }
323     }
324 }
325
326 class Elevator
327 {
328     private int id;//电梯编号
329     private int maxLoadWeight;//最大载重
330     private int loadWeight;//当前重量
331     private int state;//0:全层 1:单层 2:双层
332     private int floor; //电梯当前楼层
333     private int runState;//电梯运行状态 0--不动       1--向上    -1--向下
334     private int[] toFloors;//电梯目标楼层
335     private int start,end;
336     private String info;//电梯信息
337
338     Elevator(int id, int maxLoadWeight, int state){
339         this.id = id;
340         this.maxLoadWeight = maxLoadWeight;
341         this.loadWeight = 0;
342         this.state = state;
343         this.setFloor(1);
344         this.setRunState(0);
345         toFloors = new int[20];
346         this.start = 0;
347         this.end = 0;
348     }
349
350     public int countDistance(int personFloor, int runDirection)
351     {
352         if(state ==1 && (personFloor%2)==0)
353             return 100;
354         if(state ==2 && (personFloor%2)==1)
355             return 100;
356         if(end == start)
357             return Math.abs(personFloor - floor);
358         else if(end-start ==1){//电梯目标值为1个
359             if(toFloors[end-1] > floor){//电梯上升
360                 if(1 == runDirection){//人上升    三种情况
361                     if(personFloor < floor){
362                         return (toFloors[end-1]-floor)*2+(floor-personFloor);
363                     }else{
364                         return personFloor-floor;
365                     }
366                 }else{//人下降  三种情况
367                     if(personFloor>toFloors[end-1]){
368                         return personFloor-floor;
369                     }else if(personFloor < floor){
370                         return (toFloors[end-1]-floor)*2+(floor-personFloor);
371                     }else{
372                         return (toFloors[end-1]-floor)+(personFloor-floor);
373                     }
374                 }
375             }else{//电梯下降
376                 if(1 == runDirection){//人上升
377                     if(personFloor>floor){
378                         return (floor-toFloors[end-1])*2+(personFloor-floor);
379                     }else if(personFloor < toFloors[end-1]){
380                         return floor-personFloor;
381                     }else{
382                         return (floor-toFloors[end-1])+(personFloor-toFloors[end-1]);
383                     }
384                 }else{//人下降
385                     if(personFloor>floor){
386                         return (floor-toFloors[end-1])*2+(personFloor-floor);
387                     }else if(personFloor < toFloors[end-1]){
388                         return floor-personFloor;
389                     }
390                 }
391             }
392         }else{//电梯目标值为两个以上
393             if(toFloors[end-1] >toFloors[end-2]){//电梯最终状态为上升
394                 if(1 == runDirection){//人上升    三种情况
395                     if(personFloor < toFloors[end-2]){
396                         return (toFloors[end-1]-toFloors[end-2])*2+(toFloors[end-2]-personFloor);
397                     }else{
398                         return personFloor-toFloors[end-2];
399                     }
400                 }else{//人下降  三种情况
401                     if(personFloor>toFloors[end-1]){
402                         return personFloor-toFloors[end-2];
403                     }else if(personFloor < toFloors[end-2]){
404                         return (toFloors[end-1]-toFloors[end-2])*2+(toFloors[end-2]-personFloor);
405                     }else{
406                         return (toFloors[end-1]-toFloors[end-2])+(personFloor-toFloors[end-2]);
407                     }
408                 }
409             }else{//电梯最终状态为下降
410                 if(1 == runDirection){//人上升
411                     if(personFloor>toFloors[end-2]){
412                         return (toFloors[end-2]-toFloors[end-1])*2+(personFloor-toFloors[end-2]);
413                     }else if(personFloor < toFloors[end-1]){
414                         return toFloors[end-2]-personFloor;
415                     }else{
416                         return (toFloors[end-2]-toFloors[end-1])+(personFloor-toFloors[end-1]);
417                     }
418                 }else{//人下降
419                     if(personFloor>toFloors[end-2]){
420                         return (floor-toFloors[end-1])*2+(personFloor-toFloors[end-2]);
421                     }else if(personFloor < toFloors[end-1]){
422                         return toFloors[end-2]-personFloor;
423                     }
424                 }
425             }
426         }
427         return -100;//防止出错判断
428     }
429
430
431     public void add(int personFloor, int runDirection,int toFloor)
432     {
433         if (end - start > 0)//电梯目标楼层大于0个
434         {
435             if ((toFloors[end-1] - toFloors[end - 2])*runDirection > 0) {//人和电梯同方向
436                 if (1 == runDirection)//同向上
437                 {
438                     if (personFloor > toFloors[end - 1])//人所在楼层 高于 电梯去的最高楼层
439                     {
440                         toFloors[(end++) % 20] = personFloor;
441                         toFloors[(end++) % 20] = toFloor;
442                     }else {//人所在楼层 低于 电梯去的最高楼层
443                         toFloors[end] = toFloors[(end++)%20 -1];
444                         toFloors[end - 2] = personFloor;
445                         if (toFloor > toFloors[end - 1])//人要去楼层高于电梯所在楼层
446                             toFloors[(end++) % 20] = toFloor;
447                         else{    //人要去楼层低于电梯所在楼层
448                             toFloors[end] = toFloors[end - 1];
449                             toFloors[end - 1] = toFloor;
450                             end = (end++) % 20;
451                         }
452
453                     }
454                 }
455                 else {//同向下
456                     if (personFloor < toFloors[end - 1])//人所在楼层 低于 电梯去的最高楼层
457                     {
458                         toFloors[(end++) % 20] = personFloor;
459                         toFloors[(end++) % 20] = toFloor;
460                     }
461                     else {//人所在楼层 高于 电梯去的最低楼层
462                         toFloors[end] = toFloors[end - 1];
463                         toFloors[end - 1] = personFloor;
464                         end = (end++)%20;
465                         if (toFloor < toFloors[end - 1])//人要去楼层低于电梯所在楼层
466                             toFloors[(end++) % 20] = toFloor;
467                         else {    //人要去楼层高于电梯所在楼层
468                             toFloors[end] = toFloors[end - 1];
469                             toFloors[end - 1] = toFloor;
470                             end = (end++) % 20;
471                         }
472                     }
473                 }
474
475             }
476             else {//反方向
477                 toFloors[(end++) % 20] = personFloor;
478                 toFloors[(end++) % 20] = toFloor;
479             }
480         }
481         else//电梯目标楼层数量为1或者0
482         {
483             toFloors[(end++) % 20] = personFloor;
484             toFloors[(end++) % 20] = toFloor;
485         }
486     }
487
488
489     public void run()throws Exception//电梯运行
490     {
491         if (start != end)//需要运行
492         {
493             if (floor < toFloors[start])//向上
494             {
495                 runState = 1;
496                 floor++;
497             }
498             else if (floor > toFloors[start])//向下
499             {
500                 runState = -1;
501                 floor--;
502             }
503             else//floor = toFloors[start] 到目的地
504             {
505                 System.out.println("电梯"+id+" 已到达到达目的地:"+floor);
506
507                 runState = 0;
508                 start = (start+1)%20;
509             }
510         }
511     }
512
513     public String show(){
514         info = id+"'s Elevator \non "+floor+"'s floor\nis ";
515         if(1 == runState)
516             return info+" ↑";
517         if(-1 == runState)
518             return info+" ↓";
519         return info+" -- ";
520
521     }
522
523     public int getRunState() {
524         return runState;
525     }
526
527     public void setRunState(int runState) {
528         this.runState = runState;
529     }
530
531     public int getFloor() {
532         return floor;
533     }
534
535     public void setFloor(int floor) {
536         this.floor = floor;
537     }
538 }

源码

转载于:https://www.cnblogs.com/lishida/p/5366029.html

结对编程作业---电梯调度程序相关推荐

  1. 现代软件工程系列 结对编程 (II) 电梯调度程序

    [很多同学完成了上一个结对编程项目后,  很想知道下一个项目是什么, 我们这次要练习如何设计 接口, 测试框架,  和算法] 现代软件工程系列 结对编程 (II) 电梯调度程序 ------- Pai ...

  2. 现代软件工程系列 结对编程 (II) 电梯调度程序新需求

    原来布置的作业在这里: http://www.cnblogs.com/xinz/archive/2010/11/28/1890300.html 正如在现实生活中一样, 软件项目的需求也会经常发生变化. ...

  3. 现代软件工程 结对编程 (II) 电梯调度 算法和测试框架

    [很多同学完成了上一个结对编程项目后,  很想知道下一个项目是什么, 我们这次要练习如何设计 接口, 测试框架,  和算法. ] [博客园的朋友们也可以试一试怎么高效地解决这个问题] 现代软件工程系列 ...

  4. 现代软件工程 结对编程 (II) 电梯调度

    现代软件工程 结对编程 (II) 电梯调度 Pair Project II: Elevator Scheduler <现代软件工程> 的结对编程作业,  作者: 邹欣 怎样设计API?  ...

  5. 软件工程网络15结对编程作业

    软件工程网络15结对编程作业 1.项目成员 学号:201521123014 博客地址:http://www.cnblogs.com/huangsh/ 学号: 201521123102 博客地址:htt ...

  6. 结对编程作业——毕设导师智能匹配

    结对编程作业--毕设导师智能匹配 031402317 李佳恺 031402511 黄家俊 问题描述及要求 输入30个老师(包含带学生数的要求的上限,单个数值,在[0,8]内),100个学生(包含绩点信 ...

  7. 2022秋软工实践 第一次结对编程作业

    2022秋软工实践 第一次结对编程作业 需求分析 (1)Need,需求 (2)Approach,做法 (3)Benfit,好处 (4)Competitors,竞争 (5)Delivery,推广 UML ...

  8. 2021秋软工实践第一次结对编程作业

    这个作业属于哪个课程 构建之法-2021秋-福州大学软件工程 这个作业要求在哪里 2021秋软工实践第一次结对编程作业 这个作业的目标 实现博饼软件原型并进行博客写作 学号 031902139 队友学 ...

  9. 2022软工K班结对编程作业

    逍遥骰GitHub链接 哔哩哔哩功能展示 学号 姓名 作业博客链接 具体分工 032002621 林灿彬 待填写 JavaScript编程.AI设计 032002623 林达锴 待填写 原型制作.ht ...

最新文章

  1. 32位so库兼容64位使用
  2. Android Jetpack - Emoji表情符号初探
  3. 【qduoj - 纳新题】小明的dp(快速幂 + 乘法原理)(简单组合数学)
  4. leetcode619. 只出现一次的最大数字(SQL)
  5. 计算机多媒体发展2018,2018秋季学期计算机多媒体项目圆满结课
  6. mysql查看重复数据结构_mysql 数据库重复数据结构
  7. SVN commit failed: 'xxx' is not under version control
  8. 【日本软件外包】设计书中常用到的文型
  9. Google Breakpad的使用
  10. NORDIC nRF52840 输入引脚初始化及中断操作
  11. JAVA 16进制转字符串问题
  12. 最新MTK刷机工具资料(SP_Flash_Tool_exe_Windows_v5.1844.00.000)
  13. 金鹰卡通java面试_两则电视栏目招募通告,来试试?!
  14. 公钥私钥的使用和数字签名原理
  15. 数据过多/DOM操作导致页面卡顿和请求突增导致页面崩溃
  16. 原谅我,无法刻骨铭心地记住你
  17. java判断访问设备类型
  18. 如何用matlab解异或方程,Matlab-6:解非线性方程组newton迭代法
  19. Excel表格怎么转PDF?这两种途径都可以
  20. 在百里峡内的拍照技巧

热门文章

  1. acl 允许同网段访问_ENSP模拟交换环境中调用高级ACL限制不同网段之间互访
  2. linux创建网络ntfs接点,Linux系统下挂接ntfs盘时总提示module fuse not found如何解决?...
  3. wps多人协作后怎么保存_白酒开瓶后怎么保存?
  4. 我php第一个页面,您的第一个 PHP 页面
  5. 监控摄像头接入流媒体服务器的几种方式
  6. python记录(5)- find() 与 rfind()
  7. 毕设日志——tensorboardX无法连接的问题
  8. 如何查看google chrome 插件源码
  9. 轻量级数据交换格式JSON
  10. 学习 服务器部署 hello world