结对项目开发电梯调度 - 整体设计
一、系统介绍
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
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ElevatorManager { class Elevator { public int floor; public bool[] panel;//电梯内面板状态 public int direction;//up,down public int gatestatus;//open,close public bool isrun; const int UP = 0; const int DOWN = 1; const int CLOSE = 0; const int OPEN = 1; public Elevator() { floor = 0; panel = new bool[10]; for (int i = 0; i < 10; ++i) { panel[i] = false; } direction = UP; gatestatus = CLOSE; isrun = false; } public void setPanel(int i) { panel[i] = true; } } }
2.ElevatorManager.CS
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ElevatorManager { class ElevatorController { public Elevator ele_1; public Elevator ele_2; public bool[] uppanel; public bool[] downpanel; #region 状态常量定义 //电梯内 const int UP = 0; const int DOWN = 1; const int CLOSE = 0; const int OPEN = 1; const int WAIT = 2; //电梯外 const int EXTERIOR = 0; const int INTERIOR = 1; //任务 const int MOVEUP = 0; const int MOVEDOWN = 1; const int NONE = -1; //type判断 const int ELE1 = 0; const int ELE2 = 1; #endregion public ElevatorController() { ele_1 = new Elevator(); ele_2 = new Elevator(); uppanel = new bool[10];//电梯外 上按钮状态 downpanel = new bool[10];//电梯外 下按钮状态 for (int i = 0; i < 10; ++i) { uppanel[i] = false; } for (int i = 0; i < 10; ++i) { downpanel[i] = false; } } public void operate(int IorE, int type, int select)//操作 { //操作判断 if (IorE == INTERIOR)//外层IorE判断 { if (type == ELE1)//内层type判断 { ele_1.setPanel(select); } else if (type == ELE2) { ele_2.setPanel(select); } else { Exception ex = new Exception("INTERIOR type 错误"); throw ex; } } else if (IorE == EXTERIOR) { if (type == UP) { uppanel[select] = true; } else if (type == DOWN) { downpanel[select] = true; } else { Exception ex = new Exception("EXTERIOR type 错误"); throw ex; } } else { Exception ex=new Exception("IorE错误"); throw ex; } //电梯是否在执行任务 if (!ele_1.isrun) { ele_1.isrun = true; Thread th1 = new Thread(new ThreadStart(run_ele1)); th1.IsBackground = true; th1.Start(); } if (!ele_2.isrun) { ele_2.isrun = true; Thread th2 = new Thread(new ThreadStart(run_ele2)); th2.IsBackground = true; th2.Start(); } } public void run_ele1() { try { run(ele_1); } catch (Exception ex) { throw ex; } } public void run_ele2() { try { run(ele_2); } catch (Exception ex) { throw ex; } } public void run(Elevator ele)//运行 { for (; isGoOn(ele); ) { for (operaGate(ele); ele.gatestatus == OPEN; operaGate(ele)) { Thread.Sleep(5000); ele.gatestatus = CLOSE; } int task = NONE; task = gettask(ele); if (task == MOVEUP) { ele.floor += 1; if (!floorJudge(ele)) { Exception ex = new Exception("楼层错误"); throw ex; } Thread.Sleep(1000); } else if (task == MOVEDOWN) { ele.floor -= 1; if (!floorJudge(ele)) { Exception ex = new Exception("楼层错误"); throw ex; } Thread.Sleep(1000); } else if (task == NONE) { //不操作 if (!floorJudge(ele)) { Exception ex = new Exception("楼层错误"); throw ex; } } else { Exception ex = new Exception("获取的任务出错"); throw ex; } } ele.isrun = false; } public void operaGate(Elevator ele)//是否开门操作 { if (ele.direction == UP) { if(ele.panel[ele.floor]||uppanel[ele.floor]) { ele.gatestatus = OPEN; //ele.direction = UP; ele.panel[ele.floor] = false; uppanel[ele.floor] = false; return; } if (!upAsk(ele)) { if (downpanel[ele.floor]) { ele.gatestatus = OPEN; ele.direction = DOWN; downpanel[ele.floor] = false; return; } } } else if (ele.direction == DOWN) { if (ele.panel[ele.floor] || downpanel[ele.floor]) { ele.gatestatus = OPEN; //ele.direction = DOWN; ele.panel[ele.floor] = false; downpanel[ele.floor] = false; return; } if (!downAsk(ele)) { if (uppanel[ele.floor]) { ele.gatestatus = OPEN; ele.direction = UP; uppanel[ele.floor] = false; return; } } } else { Exception ex = new Exception("电梯状态出错"); throw ex; } } public bool isGoOn(Elevator ele)//是否有任务判断 { for (int i=0;i<10;++i) { if (ele.panel[i]) { return true; } if (uppanel[i]) { return true; } if (downpanel[i]) { return true; } } return false; } public int gettask(Elevator ele)//任务获取 { if(ele.direction==UP)//方向上任务获取顺序 { if (upAsk(ele)) { return MOVEUP; } if (downAsk(ele)) { return MOVEDOWN; } } else if(ele.direction==DOWN)//方向下任务获取顺序 { if (downAsk(ele)) { return MOVEDOWN; } if (upAsk(ele)) { return MOVEUP; } } else { Exception ex = new Exception("电梯状态出错"); throw ex; } return NONE; } public bool upAsk(Elevator ele)//上方查询 { for (int i = ele.floor + 1; i < 10; ++i) { if (ele.panel[i]) { return true; } if (uppanel[i]) { return true; } if (downpanel[i]) { return true; } } return false; } public bool downAsk(Elevator ele)//下方查询 { for (int i = ele.floor - 1; i >= 0; --i) { if (ele.panel[i]) { return true; } if (uppanel[i]) { return true; } if (downpanel[i]) { return true; } } return false; } public bool floorJudge(Elevator ele) { if (ele.floor>=0&&ele.floor<10) { return true; } return false; } } }
3.Form1.CS
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace ElevatorManager { public partial class Form1 : Form { const int UP = 0; const int DOWN = 1; const int EXTERIOR = 0; const int INTERIOR = 1; const int ELE1 = 0; const int ELE2 = 1; const int CLOSE = 0; const int OPEN = 1; List<Button> btnUpPanel; List<Button> btnDownPanel; List<Button> btnEle1; List<Button> btnEle2; Thread th_ui; ElevatorController myElevator; Image imgEleOpen; Image imgEleClose; public Form1() { InitializeComponent(); System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; } private void Form1_Load(object sender, EventArgs e) { try { btnUpPanel = new List<Button>(); btnDownPanel = new List<Button>(); btnEle1 = new List<Button>(); btnEle2 = new List<Button>(); #region 控件获取 btnUpPanel.Add(btn_1_up); btnUpPanel.Add(btn_2_up); btnUpPanel.Add(btn_3_up); btnUpPanel.Add(btn_4_up); btnUpPanel.Add(btn_5_up); btnUpPanel.Add(btn_6_up); btnUpPanel.Add(btn_7_up); btnUpPanel.Add(btn_8_up); btnUpPanel.Add(btn_9_up); btnUpPanel.Add(new Button()); btnDownPanel.Add(new Button()); btnDownPanel.Add(btn_2_down); btnDownPanel.Add(btn_3_down); btnDownPanel.Add(btn_4_down); btnDownPanel.Add(btn_5_down); btnDownPanel.Add(btn_6_down); btnDownPanel.Add(btn_7_down); btnDownPanel.Add(btn_8_down); btnDownPanel.Add(btn_9_down); btnDownPanel.Add(btn_10_down); btnEle1.Add(btn_e1_f1); btnEle1.Add(btn_e1_f2); btnEle1.Add(btn_e1_f3); btnEle1.Add(btn_e1_f4); btnEle1.Add(btn_e1_f5); btnEle1.Add(btn_e1_f6); btnEle1.Add(btn_e1_f7); btnEle1.Add(btn_e1_f8); btnEle1.Add(btn_e1_f9); btnEle1.Add(btn_e1_f10); btnEle2.Add(btn_e2_f1); btnEle2.Add(btn_e2_f2); btnEle2.Add(btn_e2_f3); btnEle2.Add(btn_e2_f4); btnEle2.Add(btn_e2_f5); btnEle2.Add(btn_e2_f6); btnEle2.Add(btn_e2_f7); btnEle2.Add(btn_e2_f8); btnEle2.Add(btn_e2_f9); btnEle2.Add(btn_e2_f10); #endregion imgEleOpen=new Bitmap(@".\elevator_open.jpg"); imgEleClose=new Bitmap(@".\elevator_close.jpg"); myElevator=new ElevatorController(); MessageBox.Show("初始化成功!!!"); } catch(Exception ex) { MessageBox.Show(ex.Message); } th_ui = new Thread(new ThreadStart(UIController)); th_ui.IsBackground=true; th_ui.Start(); } public void UIController()//UI控制线程 { try { for (; true; ) { #region 面板灯 for (int i = 0; i < 10; ++i) { if (myElevator.uppanel[i]) { btnUpPanel[i].BackColor = Color.Yellow; } if (!myElevator.uppanel[i]) { btnUpPanel[i].BackColor = Color.White; } // if (myElevator.downpanel[i]) { btnDownPanel[i].BackColor = Color.Yellow; } if (!myElevator.downpanel[i]) { btnDownPanel[i].BackColor = Color.White; } // if (myElevator.ele_1.panel[i]) { btnEle1[i].BackColor = Color.Yellow; } if (!myElevator.ele_1.panel[i]) { btnEle1[i].BackColor = Color.White; } // if (myElevator.ele_2.panel[i]) { btnEle2[i].BackColor = Color.Yellow; } if (!myElevator.ele_2.panel[i]) { btnEle2[i].BackColor = Color.White; } } #endregion label_ele1.Text = "Ele1.floor:" + (myElevator.ele_1.floor + 1).ToString(); label_ele2.Text = "Ele2.floor:" + (myElevator.ele_2.floor + 1).ToString(); picture_ele1.Location = new Point(picture_ele1.Location.X, 500 - (50 * myElevator.ele_1.floor)); picture_ele2.Location = new Point(picture_ele2.Location.X, 500 - (50 * myElevator.ele_2.floor)); if (myElevator.ele_1.gatestatus == CLOSE) { picture_ele1.Image = imgEleClose; } if (myElevator.ele_1.gatestatus == OPEN) { picture_ele1.Image = imgEleOpen; } if (myElevator.ele_2.gatestatus == CLOSE) { picture_ele2.Image = imgEleClose; } if (myElevator.ele_2.gatestatus == OPEN) { picture_ele2.Image = imgEleOpen; } Thread.Sleep(100); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_1_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 0); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_2_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 1); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_2_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 1); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_3_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 2); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_3_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 2); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_4_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 3); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_4_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 3); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_5_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 4); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_5_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 4); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_6_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 5); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_6_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 5); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_7_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 6); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_7_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 6); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_8_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 7); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_8_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 7); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_9_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 8); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_9_up_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, UP, 8); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_10_down_Click(object sender, EventArgs e) { try { myElevator.operate(EXTERIOR, DOWN, 9); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f1_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 0); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f2_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 1); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f3_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 2); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f4_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 3); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f5_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 4); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f6_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 5); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f7_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 6); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f8_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 7); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f9_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 8); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e1_f10_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE1, 9); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f1_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 0); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f2_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 1); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f3_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 2); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f4_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 3); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f5_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 4); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f6_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 5); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f7_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 6); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f8_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 7); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f9_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 8); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btn_e2_f10_Click(object sender, EventArgs e) { try { myElevator.operate(INTERIOR, ELE2, 9); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } }
四、测试结果
结过几周的不断编写和调试,最后程序得已成功运行,期间查看了不少的资料和信息,特别 是对于画布的设计效果,还有就是对于电梯开关时的音效.
下面是测试效果:
1开始界面,初使是默认在第一层:
2.进入乘客,分别对两台电梯进行操作:
3.15层要下行,两个电梯同时出发,当电梯2到达后,响应,电梯1不再调度。
4. 这是在进入电梯后,电梯1点击了13;电梯2中点击了8,9,10楼后的效果,分别在8,9,10楼电梯都停止,电梯门打开,等待一段时间后继续响应。
五、心得体会
回首本次实验历程,最初这个关于电梯调度的大工程,我们很是头疼,由于涉及到了图形界面,一开始我和雪青我们准备用java来实现,但是由于在图形界面这方面遇到的困难颇多,又因为上学期刚学了.net,最终选择了较为熟悉的.net开发;后来就是在电梯调度算法的选择上面出现了问题,虽然有小小的分歧,但是最终我们选择了一种容易实现并且易懂的算法,不得不说,在这个问题上,没少让我们学习有关操作系统各种调度算法的知识。这个电梯调度有个特点就是涉及到两个电梯,所以就更要求要有一个好的调度方法,来实现资源的利用最大化,涉及到并行,线程控制显得略为重要。
通过我们两个人精诚合作,最终实现了作为电梯调度的基本功能,虽然依旧没有完美的解决电梯调度中出现的问题,但是过程是十分重要的,我们学习到了许多知识,涉及多个学科,巩固了基础,提高了能力,也提高了结对开发的乐趣和效率,收获颇丰。