lmdi

导航

结对编程项目--电梯调度

      从本次开始,我们改变了作业模式,由起初的个人编程到结对编程的过渡,很好的让我们了解和认识别人的编程方法和习惯,同时也避开了以往个人编程中所遇到的诸多问题,让我想起了一句话,“一个人或许可以走的很快,但一定走的不远。”。

      接下来我们来回顾一下本次作业的内容及要求:

  电梯调度

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

电梯编号

可服务楼层

最大乘客数量

 

最大载重量

 1

全部楼层

10

800 kg

2

单层

10

800 kg

3

双层

20

1600 kg

4

全部楼层

20

2000 kg

      其使用规定如下:

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

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

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

     关于本次作业,刚看到的时候觉得各种问题好复杂,但是仔细分析之后思路便明了了,我和我的队友最终决定把问题条形化,分成一个个子问题逐一分析进而用一个个子函数来实现,这样复杂的问题就简单化了。当然这次的编程语言我们选了自我感觉最能解决也是我们比较熟悉的C++,感觉C语言好像不能完全实现诶>.<...

 

  我和我的小伙伴首先简单分析了一下实现的过程。

  一、电梯类,电梯类要能实现单双层的判断以及对所要去的电梯进行存储,最初我们打算默认让哪几个电梯跑单层,哪几个电梯跑双层,后来决定采用属性值来标识的做法,其次是电梯的存储,最开始我们用一个int型的数来存储目标楼层,但是测试过程中发现,如果只用一个int型变量的话,当电梯的目标楼层为多个或者需要中途改变的时候电梯会无法实现既定的目标,于是我提出用数组来直接存储多个目标,这样可以满足当多个用户使用电梯的需求。随之改变的是电梯的运行,以前的电梯运行只要判断当前楼层和目标楼层就可以做相应的执行,改变的电梯想要运行需要判断数组是否为空,当数组不为空时判断电梯的运行。电梯类中最难实现的方法应该是将目标楼层添加进数组了,因为情况很多,当时也没有分析明白,导致开发的进度一度毫无进展,经过伙伴的四方求助以及分析,我们最终将各种情况分化,化为一个一个小的情况,接下来的就简单多了,针对每一个小的情况,将目标楼层加入电梯的数组,接下来只要让电梯运行就可以。

  

  1 class Elevator{
  2 private:
  3     int id;//电梯号
  4     int floor;//电梯当前楼层
  5     int max;//最大人数
  6     int Pnum;//当前人数
  7     int state;//0:全部 1:单层 2:双层
  8     int RunState;//0:不动  1:向上  2:向下
  9     int Queue[21];
 10     int start = 0, end = 0;
 11     int pState, toP;//pState 奇数时进人 偶数时出人
 12 public:
 13     Elevator(int Enum, int floor, int Pnum, int state,int max);//构造函数
 14     int getId(){ return id; }//获取电梯号
 15     int getfloor(){ return floor; }//获取当前楼层数
 16     int getPnum(){ return Pnum; }//获取人数
 17     void Run();//电梯上下行
 18     void show();//显示函数
 19     void Add(int Pfloor, int Runstate, int tofloor, int Pnum);//根据方向添加进数组
 20     int countDistance(int pFloor, int runDirection);//计算电梯与人的距离
 21 };
 22 Elevator::Elevator(int id, int floor, int Pnum, int state,int max) :id(id), floor(floor), Pnum(Pnum),state(state),max(max){
 23     RunState = 0;
 24     pState = 1;
 25     toP = 0;
 26 }
 27 void Elevator::Run(){
 28     if (end != start)//需要电梯运行的情况
 29     {
 30         if (floor > Queue[start])//向下
 31         {
 32             RunState = 2;
 33             floor--;
 34             
 35         }
 36         if (floor < Queue[start])//向上
 37         {
 38             
 39             RunState = 1;
 40             floor++;
 41         }
 42         if (floor == Queue[start])//到达目的地
 43         {
 44             RunState = 0;
 45             start = (start++) % 21;//start指针向后移
 46             if (pState % 2 == 0){//出人
 47                 if (start == end)
 48                     Pnum = 0;
 49                 else
 50                     Pnum = Pnum - abs(rand() % Pnum);
 51                 pState++;
 52             }
 53             else{//进人
 54                 Pnum += toP;
 55                 if (Pnum > max)
 56                 {
 57                     cout << "超重了,需要下" << Pnum - max << "";
 58                     Pnum = max;
 59                 }
 60                 pState++;
 61             }
 62         }
 63     }
 64     else{
 65         RunState = 0;
 66     }
 67     
 68 }
 69 void Elevator::Add(int Pfloor, int runDirection, int tofloor,int person){
 70     toP = person;
 71     if (end - start < 1)//end指向下一个地址
 72     {
 73         Queue[(end++) % 21] = Pfloor;
 74         Queue[(end++) % 21] = tofloor;
 75         
 76     }
 77     else
 78     {
 79         if (runDirection == 1)//人向上
 80         {
 81             if (Queue[end - 1]>Queue[end - 2])//电梯向上
 82             {
 83                 if (Queue[end - 1] > Pfloor)//电梯的目标楼层大于人当前的楼层
 84                 {
 85                     Queue[end] = Queue[end - 1];
 86                     Queue[end - 1] = Pfloor;
 87                     end = (end++) % 21;
 88                 }
 89                 else//小于
 90                 {
 91                     Queue[end] = Pfloor;
 92                     end = (end++) % 21;
 93                 }
 94                 if (Queue[end - 1] > tofloor)//队列中的最后一个数大于人的目标楼层时
 95                 {
 96                     Queue[end] = Queue[end - 1];
 97                     Queue[end - 1] = tofloor;
 98                     end = (end++) % 21;
 99                 }
100                 else
101                 {
102                     Queue[end] = tofloor;
103                     end = (end++) % 21;
104                 }
105             }
106             if (Queue[end - 1]<Queue[end - 2])//电梯向下
107             {
108                 if (Queue[end - 1] > Pfloor)//电梯的目标楼层大于人当前的楼层
109                 {
110                     Queue[end] = Pfloor;
111                     end = (end++) % 21;
112                     Queue[end] = tofloor;
113                     end = (end++) % 21;
114                 }
115             }
116         }
117         if (runDirection == 2)//人向下
118         {
119             if (Queue[end - 1]>Queue[end - 2])//电梯向上
120             {
121                 if (Queue[end - 1] < Pfloor)//电梯的目标楼层小于人当前的楼层
122                 {
123                     Queue[end] = Pfloor;
124                     end = (end++) % 21;
125                     Queue[end] = tofloor;
126                     end = (end++) % 21;
127                 }
128             }
129             else//电梯向下
130             {
131                 if (Queue[end - 1]<Pfloor)//电梯的目标楼层小于人当前的楼层
132                 {
133                     Queue[end] = Queue[end - 1];
134                     Queue[end - 1] = Pfloor;
135                     end = (end++) % 21;
136                 }
137                 else
138                 {
139                     Queue[end] = Pfloor;
140                     end = (end++) % 21;
141                 }
142                 if (Queue[end - 1] < tofloor)//队列中的最后一个数小于人的目标楼层时
143                 {
144                     Queue[end] = Queue[end - 1];
145                     Queue[end - 1] = tofloor;
146                     end = (end++) % 21;
147                 }
148                 else
149                 {
150                     Queue[end] = tofloor;
151                     end = (end++) % 21;
152                 }
153             }
154         }
155     }
156 }
157 void Elevator::show(){
158     cout << "id:" << id;
159     cout << "电梯,在" << floor << "";
160     cout << " 运行方向:";
161     if (0 == RunState)//不动
162     {
163         cout << "  -";
164     }
165     if (1 == RunState)//向上
166     {
167         cout << "";
168     }
169     if (2 == RunState)//向下
170     {
171         cout << "";
172     }
173     cout << "人:" << Pnum << endl;
174     cout << endl;
175 }
176 int Elevator::countDistance(int pFloor, int runDirection){
177     if (state == 1&&pFloor%2==0)//电梯单层 人在双层
178     {
179         return 100;
180     }
181     if (state==2&&pFloor%2!=0)//电梯双层 人在单层
182     {
183         return 100;
184     }
185     if (end == start)//电梯静止时
186     {
187         return abs(floor-pFloor);
188     }
189     if (end - start == 1)//电梯只有一个目标楼层时
190     {
191         if (floor<Queue[start])//电梯上行
192         {
193             if (runDirection == 1)//人上行
194             {
195                 if (pFloor<floor)//人在当前楼层下方
196                 {
197                     return (2 * (Queue[start] - floor) + (floor - pFloor));
198                 }
199                 if (pFloor>=floor)//人在当前楼层上方
200                 {
201                     return (pFloor - floor);
202                 }
203             }
204             if (runDirection == 2)//人下行
205             {
206                 if (pFloor<floor)//人在当前楼层下方
207                 {
208                     return (2 * (Queue[start] - floor) + (floor - pFloor));
209                 }
210                 if (pFloor >Queue[start])//人在当前楼层上方
211                 {
212                     return (pFloor - floor);
213                 }
214                 if (pFloor >= floor&&pFloor <= Queue[start])//人在当前楼层和目标楼层之间
215                 {
216                     return (Queue[start] - floor + Queue[start] - pFloor);
217                 }
218             }
219         }
220         else//电梯下行
221         {
222             if (runDirection == 1)//人上行
223             {
224                 if (pFloor < floor)//人在当前楼层下方
225                 {
226                     return (floor-Queue[start]+pFloor-Queue[start]);
227                 }
228                 if (pFloor >= floor)//人在当前楼层上方
229                 {
230                     return (2*(floor-Queue[start])+pFloor-floor);
231                 }
232                 if (pFloor >= floor&&pFloor <= Queue[start])//人在当前楼层和目标楼层之间
233                 {
234                     return (floor-Queue[start]+pFloor-Queue[start]);
235                 }
236             }
237             if (runDirection == 2)//人下行
238             {
239                 if (pFloor<floor)//人在当前楼层下方
240                 {
241                     return (floor-pFloor);
242                 }
243                 if (pFloor >Queue[start])//人在当前楼层上方
244                 {
245                     return (2*(floor-Queue[start])+pFloor-floor);
246                 }
247             }
248         }
249     }
250     if (end-start>1)//电梯有两个或两个以上目标楼层时
251     {
252         if (Queue[end-2]<Queue[end-1])//电梯上行
253         {
254             if (runDirection == 1)//人上行
255             {
256                 if (pFloor>=Queue[end-2])//人在目标楼层1上方
257                 {
258                     return (pFloor-Queue[end-2]);
259                 }
260                 if (pFloor<Queue[end-2])//人在目标楼层1下方
261                 {
262                     return (2*(Queue[end-1]-Queue[end-2])+Queue[end-2]-pFloor);
263                 }
264             }
265                 if (runDirection == 2)//人下行
266                 {
267                     if (pFloor<Queue[end - 2])//人在目标楼层1下方
268                     {
269                         return (2 * (Queue[end - 1] - Queue[end - 2]) + (Queue[end - 2] - pFloor));
270                     }
271                     if (pFloor >Queue[end - 1])//人在目标楼层2上方
272                     {
273                         return (pFloor - Queue[end - 2]);
274                     }
275                     if (pFloor >= Queue[end - 2] && pFloor <= Queue[end - 1])//人在目标楼层1和目标楼层2之间
276                     {
277                         return (Queue[end - 1] - Queue[end - 2] + Queue[end - 1] - pFloor);
278                     }
279                 }
280         }
281         else//电梯下行
282         {
283             if (runDirection == 1)//人上行
284             {
285                 if (pFloor<Queue[end-1])//人在目标楼层2下方
286                 {
287                     return (Queue[end-2]-pFloor);
288                 }
289                 if (pFloor>Queue[end-2])//人在目标楼层1上方
290                 {
291                     return (2*(Queue[end-2]-Queue[end-1])+pFloor-Queue[end-2]);
292                 }
293                 if (pFloor>=Queue[end-1]&&pFloor<=Queue[end-2])//人在目标楼层1和2之间
294                 {
295                     return (Queue[end-2]-Queue[end-1]+pFloor-Queue[end-1]);
296                 }
297             }
298             if (runDirection == 2)//人下行
299             {
300                 if (pFloor>Queue[end-2])//人在目标楼层1上方
301                 {
302                     return (2*(Queue[end-2]-Queue[end-1])+pFloor-Queue[end-2]);
303                 }
304                 if (pFloor<=Queue[end-2])//人在目标楼层1下方
305                 {
306                     return (Queue[end - 2] - pFloor);
307                 }
308             }
309         }    
310     }
311 }
class Elevator

  电梯类中主要有id 电梯号 floor 电梯当前楼层 Pnum当前人数等属性,方法有add方法,run方法 show方法以及countDistance方法

  二、电梯的运行,起初我们以为电梯的运行是一件很简单的事情,只要让它上上下下就可以,但后来我发现的我们大错特错了,电梯本身的运行很简单,但是当电梯的数目增加时,电梯的运行变得很难实现,首先是如何判断多个电梯中的哪个电梯去响应对应楼层的按钮,其次是判断后怎么让相应的电梯去到按钮所在的楼层,响应按钮后如何将人所在的楼层和人要去的楼层合理的添加进数组的相应位置,在这里我们给电梯类添加了一个新的方法,通过判断电梯与人之间所隔的楼层数来判断哪个电梯去响应按钮,最后是电梯的状态判断,在电梯的run方法中,当电梯的运行状态改变时,更改电梯当前的运动状态。

 1 //    cout << e1.countDistance(pFloor, runDirection);
 2     //    cout << e2.countDistance(pFloor, runDirection);
 3     //    cout << e3.countDistance(pFloor, runDirection);
 4     //    cout << e4.countDistance(pFloor, runDirection);
 5         //电梯最优解
 6         int num;
 7         num = compareDistance(e1.countDistance(pFloor, runDirection), e2.countDistance(pFloor, runDirection), e3.countDistance(pFloor, runDirection), e4.countDistance(pFloor, runDirection));
 8         if (num==1)//e1最近
 9         {
10             e1.Add(pFloor, runDirection, toFloor,person);
11         }
12         if (num==2)//e2最近
13         {
14             e2.Add(pFloor, runDirection, toFloor, person);
15         }
16         if (num==3)//e3最近
17         {
18             e3.Add(pFloor, runDirection, toFloor, person);
19         }
20         if (num==4)//e4最近
21         {
22             e4.Add(pFloor, runDirection, toFloor, person);
23         }
电梯运行

  三、人数的判断,最初的电梯人数的限制很简单,因为电梯目标只有一个,所以只要判断响应按钮时进入的人少于最大人数就可以,更改后的电梯则不行,因为存在电梯有多个目标中途下人的情况,所以我们又为电梯添加了两个新的属性,用以判断电梯是应该上人还是应该下人,以及电梯上人的时候有多少人,下人时则采取随机数方式。人数的增减则增加在电梯的运行方法中,并且改变时予以判断,如果应该下人是否为目标楼层,是的话将人数清零;如果上人超限的话则输出应下电梯多少人,以及将电梯人数设置成最大值(依据现实情况)。

 1 void Elevator::Run(){
 2     if (end != start)//需要电梯运行的情况
 3     {
 4         if (floor > Queue[start])//向下
 5         {
 6             RunState = 2;
 7             floor--;
 8             
 9         }
10         if (floor < Queue[start])//向上
11         {
12             
13             RunState = 1;
14             floor++;
15         }
16         if (floor == Queue[start])//到达目的地
17         {
18             RunState = 0;
19             start = (start++) % 21;//start指针向后移
20             if (pState % 2 == 0){//出人
21                 if (start == end)
22                     Pnum = 0;
23                 else
24                     Pnum = Pnum - abs(rand() % Pnum);
25                 pState++;
26             }
27             else{//进人
28                 Pnum += toP;
29                 if (Pnum > max)
30                 {
31                     cout << "超重了,需要下" << Pnum - max << "";
32                     Pnum = max;
33                 }
34                 pState++;
35             }
36         }
37     }
38     else{
39         RunState = 0;
40     }
41     
42 }
人数判断

 

  四、数据的输入,由于设计的不断改变,输入的数据也不断变化,因为界面的不到位,这里采用纯手工输入的方式,输入人所在的楼层,按的按钮的方向,人要去的楼层以及要上电梯的人数。由于采用循环的方式,应该有输入数据无效的情况,这时应让电梯自行运行。

 1  int Pnum, pFloor, toFloor, runDirection ,person,t=0;//  pFloor:人当前所在楼层  toFloor:人的目标楼层 runDirection:1向上 2向下  person:进电梯的人数
 2     cout << "请输入指令,\n格式为: 人所在楼层  按钮方向 人的目标楼层  人数"<<endl;
 3     while (true)
 4     {
 5         cin >> pFloor >> runDirection >> toFloor>>person;
 6         if (pFloor == -1)
 7         {
 8             //无效操作
 9             e1.show();
10             e2.show();
11             e3.show();
12             e4.show();
13             e1.Run();
14             e2.Run();
15             e3.Run();
16             e4.Run();
17             continue;
18         }
输入数据

  五、界面的实现,电梯类的实现耗费了多天的时间,本来兴致满满的打算写一个界面,然而当我们去实现时,才发现时间所剩不多,现学现做一个图形化界面已经来不及,所以草草的写了个输出函数,在控制台中输出电梯的运行情况

  

 1 void Elevator::show(){
 2     cout << "id:" << id;
 3     cout << "电梯,在" << floor << "";
 4     cout << " 运行方向:";
 5     if (0 == RunState)//不动
 6     {
 7         cout << "  -";
 8     }
 9     if (1 == RunState)//向上
10     {
11         cout << "";
12     }
13     if (2 == RunState)//向下
14     {
15         cout << "";
16     }
17     cout << "人:" << Pnum << endl;
18     cout << endl;
19 }
显示

     六、代码运行结果如下:

  

 

总结:

       结对编程对于我们来讲,是一次全新的编程作业模式,作业过程中有与队友思想的冲突,也有共同改进完善的欣喜,一点点的进步直到整个编程作业的完成,让我体验到了结对编程的益处,也使自己的编程习惯得到了很大的改善和提高。另外,逐步分析使问题化繁为简也是我们这次编程作业的关键点,拿到一个问题,刚开始也许会一头雾水,但是把一个复杂的问题拆分为若干个子问题,这样整个思路就十分清晰了,希望自己以后对待任何问题也能如此解决,沉着冷静。

 

工作照:

 

  

      

 

posted on 2016-04-09 09:24  lmdi  阅读(309)  评论(4编辑  收藏  举报