一、系统介绍
1. 功能描述
本电梯系统用来控制一台运行于一个具有16层的大楼电梯,它具有上升、下降、开门、关门、载客的基本功能。
大楼的每一层都有:
(1) 两个指示灯: 这两个指示灯分别用于指示当前所在的层数和电梯的当前状态(上行、下行或停止);
(2)按钮: 除了第一层和顶层,每一层都有两个按钮(上行、下行),乘客可以呼叫上楼或下楼,顶楼只有一个下楼按钮,而第一层只有一个上楼按钮。
2. 电梯里面具有: 标示从“1”到“16”的16个楼层按钮,用于让乘客选择所要的层数;
注:1-8层不停
二、关键实现方法描述
用两个队列来实现电梯的调度,电梯根据这两个队列发送来的楼层号作为目的地进行运行。在上行队列中保存了所有的上行请求的楼层号(包括楼层的呼叫和电梯里的楼层按钮请求),即保存电梯上行时需要停的楼层号。
队列排列规则是:高于或等于电梯当前所地楼层的上行请求的楼层号从小到大排在队列的前部分,低于电梯当前所地楼层的上行请求的楼层号从小到大排在队列后部分。如果新请求的楼层号被插在队列头时同时将这个楼层号发送给电梯作为它的目的地。在下行队列中保存了所有的下行请求的楼层号(包括楼层的呼叫和电梯里楼层按钮请求),即保存电梯下行时需要停的楼层号。
三、电梯具体设计
本次设计用的语言是.net,用的环境是VS 2010开发工具,
该系统用了3个.cs文件,一个主类class ElevatorController,主要定义了函数用来调度电梯。一个class Elevator,标明电梯状态;一个class Form1,设计布局,线程控制;
1. 电梯设置: 电梯分为三种状态:静止,上升,下降。
2 乘客分析: 乘客的需求分为“上”和“下”两种。
3 电梯需要初始化,其中状态为静止state=0,层数floor_lift设置为1。目标层数数组需要初始化。
程序源代码:
1.Elevator.CS
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ElevatorManager 7 { 8 class Elevator 9 {10 public int floor;11 public bool[] panel;//电梯内面板状态12 public int direction;//up,down13 public int gatestatus;//open,close14 public bool isrun;15 16 17 const int UP = 0;18 const int DOWN = 1;19 20 const int CLOSE = 0;21 const int OPEN = 1;22 23 public Elevator()24 {25 floor = 0;26 panel = new bool[10];27 for (int i = 0; i < 10; ++i)28 {29 panel[i] = false;30 }31 direction = UP;32 gatestatus = CLOSE;33 isrun = false;34 }35 36 public void setPanel(int i)37 {38 panel[i] = true;39 }40 41 }42 }
2.ElevatorManager.CS
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace ElevatorManager 8 { 9 class ElevatorController 10 { 11 public Elevator ele_1; 12 public Elevator ele_2; 13 public bool[] uppanel; 14 public bool[] downpanel; 15 16 #region 状态常量定义 17 //电梯内 18 const int UP = 0; 19 const int DOWN = 1; 20 21 const int CLOSE = 0; 22 const int OPEN = 1; 23 const int WAIT = 2; 24 25 //电梯外 26 const int EXTERIOR = 0; 27 const int INTERIOR = 1; 28 29 //任务 30 const int MOVEUP = 0; 31 const int MOVEDOWN = 1; 32 const int NONE = -1; 33 34 //type判断 35 const int ELE1 = 0; 36 const int ELE2 = 1; 37 38 39 #endregion 40 41 public ElevatorController() 42 { 43 ele_1 = new Elevator(); 44 ele_2 = new Elevator(); 45 uppanel = new bool[10];//电梯外 上按钮状态 46 downpanel = new bool[10];//电梯外 下按钮状态 47 for (int i = 0; i < 10; ++i) 48 { 49 uppanel[i] = false; 50 } 51 for (int i = 0; i < 10; ++i) 52 { 53 downpanel[i] = false; 54 } 55 } 56 57 public void operate(int IorE, int type, int select)//操作 58 { 59 //操作判断 60 if (IorE == INTERIOR)//外层IorE判断 61 { 62 if (type == ELE1)//内层type判断 63 { 64 ele_1.setPanel(select); 65 } 66 else if (type == ELE2) 67 { 68 ele_2.setPanel(select); 69 } 70 else 71 { 72 Exception ex = new Exception("INTERIOR type 错误"); 73 throw ex; 74 } 75 } 76 else if (IorE == EXTERIOR) 77 { 78 if (type == UP) 79 { 80 uppanel[select] = true; 81 } 82 else if (type == DOWN) 83 { 84 downpanel[select] = true; 85 } 86 else 87 { 88 Exception ex = new Exception("EXTERIOR type 错误"); 89 throw ex; 90 } 91 } 92 else 93 { 94 Exception ex=new Exception("IorE错误"); 95 throw ex; 96 } 97 98 //电梯是否在执行任务 99 if (!ele_1.isrun)100 {101 ele_1.isrun = true;102 Thread th1 = new Thread(new ThreadStart(run_ele1));103 th1.IsBackground = true;104 th1.Start();105 }106 if (!ele_2.isrun)107 {108 ele_2.isrun = true;109 Thread th2 = new Thread(new ThreadStart(run_ele2));110 th2.IsBackground = true;111 th2.Start();112 }113 }114 115 public void run_ele1()116 {117 try118 {119 run(ele_1);120 }121 catch (Exception ex)122 {123 throw ex;124 }125 }126 127 public void run_ele2()128 {129 try130 {131 run(ele_2);132 }133 catch (Exception ex)134 {135 throw ex;136 }137 }138 139 public void run(Elevator ele)//运行140 {141 for (; isGoOn(ele); )142 {143 for (operaGate(ele); ele.gatestatus == OPEN; operaGate(ele))144 {145 Thread.Sleep(5000);146 ele.gatestatus = CLOSE;147 }148 int task = NONE;149 task = gettask(ele);150 if (task == MOVEUP)151 {152 ele.floor += 1;153 if (!floorJudge(ele))154 {155 Exception ex = new Exception("楼层错误");156 throw ex;157 }158 Thread.Sleep(1000);159 }160 else if (task == MOVEDOWN)161 {162 ele.floor -= 1;163 if (!floorJudge(ele))164 {165 Exception ex = new Exception("楼层错误");166 throw ex;167 }168 Thread.Sleep(1000);169 }170 else if (task == NONE)171 {172 //不操作173 if (!floorJudge(ele))174 {175 Exception ex = new Exception("楼层错误");176 throw ex;177 }178 }179 else 180 {181 Exception ex = new Exception("获取的任务出错");182 throw ex;183 }184 }185 ele.isrun = false;186 }187 188 public void operaGate(Elevator ele)//是否开门操作189 {190 if (ele.direction == UP)191 {192 if(ele.panel[ele.floor]||uppanel[ele.floor])193 {194 ele.gatestatus = OPEN;195 //ele.direction = UP;196 ele.panel[ele.floor] = false;197 uppanel[ele.floor] = false;198 return;199 }200 if (!upAsk(ele))201 {202 if (downpanel[ele.floor])203 {204 ele.gatestatus = OPEN;205 ele.direction = DOWN;206 downpanel[ele.floor] = false;207 return;208 }209 }210 }211 else if (ele.direction == DOWN)212 {213 if (ele.panel[ele.floor] || downpanel[ele.floor])214 {215 ele.gatestatus = OPEN;216 //ele.direction = DOWN;217 ele.panel[ele.floor] = false;218 downpanel[ele.floor] = false;219 return;220 }221 if (!downAsk(ele))222 {223 if (uppanel[ele.floor])224 {225 ele.gatestatus = OPEN;226 ele.direction = UP;227 uppanel[ele.floor] = false;228 return;229 }230 }231 }232 else233 {234 Exception ex = new Exception("电梯状态出错");235 throw ex;236 }237 }238 239 public bool isGoOn(Elevator ele)//是否有任务判断240 {241 for (int i=0;i<10;++i)242 {243 if (ele.panel[i])244 {245 return true;246 }247 if (uppanel[i])248 {249 return true;250 }251 if (downpanel[i])252 {253 return true; 254 }255 }256 return false;257 }258 259 public int gettask(Elevator ele)//任务获取260 {261 if(ele.direction==UP)//方向上任务获取顺序262 {263 if (upAsk(ele))264 {265 return MOVEUP;266 }267 if (downAsk(ele))268 {269 return MOVEDOWN;270 }271 }272 else if(ele.direction==DOWN)//方向下任务获取顺序273 {274 if (downAsk(ele))275 {276 return MOVEDOWN;277 }278 if (upAsk(ele))279 {280 return MOVEUP;281 }282 }283 else284 {285 Exception ex = new Exception("电梯状态出错");286 throw ex;287 }288 return NONE;289 }290 291 public bool upAsk(Elevator ele)//上方查询292 {293 for (int i = ele.floor + 1; i < 10; ++i)294 {295 if (ele.panel[i])296 {297 return true;298 }299 if (uppanel[i])300 {301 return true;302 }303 if (downpanel[i])304 {305 return true;306 }307 }308 return false;309 }310 311 public bool downAsk(Elevator ele)//下方查询312 {313 for (int i = ele.floor - 1; i >= 0; --i)314 {315 if (ele.panel[i])316 {317 return true;318 }319 if (uppanel[i])320 {321 return true;322 }323 if (downpanel[i])324 {325 return true;326 }327 }328 return false;329 }330 331 public bool floorJudge(Elevator ele)332 {333 if (ele.floor>=0&&ele.floor<10)334 { 335 return true;336 }337 return false;338 }339 340 }341 }
3.Form1.CS
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Threading; 10 11 namespace ElevatorManager 12 { 13 public partial class Form1 : Form 14 { 15 const int UP = 0; 16 const int DOWN = 1; 17 const int EXTERIOR = 0; 18 const int INTERIOR = 1; 19 const int ELE1 = 0; 20 const int ELE2 = 1; 21 22 const int CLOSE = 0; 23 const int OPEN = 1; 24 25 List
四、测试结果
结过几周的不断编写和调试,最后程序得已成功运行,期间查看了不少的资料和信息,特别 是对于画布的设计效果,还有就是对于电梯开关时的音效.
下面是测试效果:
1.开始界面,初使是默认在第一层:
2.进入乘客,分别对两台电梯进行操作:
3.15层要下行,两个电梯同时出发,当电梯2到达后,响应,电梯1不再调度。
4. 这是在进入电梯后,电梯1点击了13;电梯2中点击了8,9,10楼后的效果,分别在8,9,10楼电梯都停止,电梯门打开,等待一段时间后继续响应。
五、心得体会
回首本次实验历程,最初这个关于电梯调度的大工程,我们很是头疼,由于涉及到了图形界面,一开始我和雪青我们准备用java来实现,但是由于在图形界面这方面遇到的困难颇多,又因为上学期刚学了.net,最终选择了较为熟悉的.net开发;后来就是在电梯调度算法的选择上面出现了问题,虽然有小小的分歧,但是最终我们选择了一种容易实现并且易懂的算法,不得不说,在这个问题上,没少让我们学习有关操作系统各种调度算法的知识。这个电梯调度有个特点就是涉及到两个电梯,所以就更要求要有一个好的调度方法,来实现资源的利用最大化,涉及到并行,线程控制显得略为重要。
通过我们两个人精诚合作,最终实现了作为电梯调度的基本功能,虽然依旧没有完美的解决电梯调度中出现的问题,但是过程是十分重要的,我们学习到了许多知识,涉及多个学科,巩固了基础,提高了能力,也提高了结对开发的乐趣和效率,收获颇丰。