这次的作业和以往不同,按照老师的要求,我们要进行结对编程的练习。所谓结对编程相信各位都不会陌生,这里不在赘述。
首先介绍下我的小伙伴,很幸运的是我的队友也是我的室友---樊西江,这为我们合作提供了很大的便利。
其次说下项目的描述与实现的办法,问题如下
电梯调度
现有一新建办公大厦,共有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 on "+floor+"'s floor is "; 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 }
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 }
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 on "+floor+"'s floor is "; 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 }