• 电梯模拟C++


    源码在文章结尾,需要者自取(有问题欢迎评论批评指教)

    1、问题描述与要求

    模拟某校九层教学楼的电梯系统。该楼有一个自动电梯,能在每层停留,其中第一层是大楼的进出层,即是电梯的“本垒层”,电梯“空闲”时,将来到该层候命。

    电梯一共有七个状态,即正在开门(Opening)、已开门(Opened)、正在关门(Closing)、已关门(Closed)、等待(Waiting)、移动(Moving)、减速(Decelerate)。

    乘客可随机地进出于任何层。对每个人来说,他有一个能容忍的最长等待时间,一旦等候电梯时间过长,他将放弃。

    模拟时钟从0开始,时间单位为0.1秒。人和电梯的各种动作均要消耗一定的时间单位(简记为t),比如:

    有人进出时,电梯每隔40t测试一次,若无人进出,则关门

    关门和开门各需要20t;

    每个人进出电梯均需要25t;

    电梯加速需要15t;

    上升时,每一层需要51t,减速需要14t

    下降时,每一层需要61t,减速需要23t

    如果电梯在某层静止时间超过300t,则驶回1层候命。

    电梯调度规则:

    1)就近原则:电梯的主要调度策略是首先响应沿当前行进方向上最近端的请求直到满足最远端请求。若该方向上无请求时,就改变移动方向

    2)在就近原则无法满足的情况下,首先满足更高层的请求

    3)电梯的最大承载人数为13人,电梯人数达到13人后,在有人出电梯之前,不接受进入电梯的请求

    4)乘客上下电梯时先出后进。进电梯时乘客是按发出乘坐请求的顺序依次进入,每次只能进入一人且每个人花费的时间都为25t

    5)电梯在关门期间(电梯离开之前)所在层提出请求的乘客同样允许进入。

    要求:

    按时序显示系统状态的变化过程,即发生的全部人和电梯的动作序列。

    扩展要求:

    实现电梯模拟的可视化界面。用动画显示电梯的升降,人进出电梯。设计有下列对象:电梯、人、电梯控制板及其上各种按钮、定时器等。

    2、设计

    2.1 设计思想

    数据由用户自定义输入,也可以进行改变使得通过用伪随机数方式来产生相关数据。此程序采用用户自定义输入,这种输入方式可以更加自由化的决定相关数据,但是同样有弊端,不适合中途随意更改数据。操作的功能如下:添加乘客、是否有乘客请求、判断电梯方向、开关门的判断设计、乘客进出设计、电梯移动的判断设计、改变电梯状态、判断是否有人放弃来改变电梯的最远请求。主要的操作必须每次都遍历,所以时间会有点耗费过大,并且存储结构设计不大合理,导致每次都需要遍历所有数据,从而浪费时间。

    存储结构采用电梯外的等待队列是单链表,电梯内部采用数组存储。等待队列的单链表设计为存储乘客类数据的结点,这样可以更加方便的访问乘客的相关信息,但是放弃了链表内部的排序,因为等待队列每次都需要遍历,所以排序会浪费更多的时间,因此抛弃该项功能。电梯内部的数组是开辟了10个大小,因为数组的下标是由0开始,所以为了更好地储存乘客前往的楼层,选择开辟10个大小的数组,每个下标里存储的数字代表着在该楼层下电梯的人数为多少人,选取数组存储的原因是一旦乘客进入电梯,有用的信息就仅仅只是下电梯的楼层,因此数组是一个较优解。

    该程序中涉及最多的算法是穷举搜索法,该算法设计是为了每次都能够遍历所有的数据,但是该算法存在缺陷,无法应对很多数据的操作,因此限制了该程序的数据量。该算法使用for循环和while循环对数据进行遍历,并且在循环中插入判断语句,使得能够在得到需要的数据后进行一系列的操作。

    2.2 设计表示

    2.3 详细设计

    链表结构体node

    成员有:(1)乘客类数据data:存储乘客的相关信息,以便于在电梯模块中使用。

    2struct node*类型的next,用于链接下一个节点。

     函数有:(1append(形参为乘客类数据):因为有头尾指针和头节点,只要把形参链接到尾部即可。

    2empty:只要头指针指向的next为空就返回true,否则就返回false

    3Remove(形参为乘客的ID):if当前节点是否就是所要删除的节点,如果是就根据是否是仅此一个节点或者是多个节点来分开处理;else当前节点不是要删除的节点,那么遍历整个链表去寻找所要删除的节点。

    乘客类passenger

    成员有:(1ID:用于设置乘客的编号。

    2nowfloor:用于记录乘客当前楼层。

    3gofloor:用于记录乘客需要去的楼层。

    4whenwait:用于记录乘客多久进入等待队列。

    函数有:(1)默认构造函数以及接口函数。

    2setdata(参数为乘客ID):对该ID下的乘客进行赋值,并且限制乘客的当前楼层和所要前往的楼层为1-9,一旦超出范围则提示需要重新输入数据。

    电梯类elevator

    成员有:(1State:用于记录电梯的状态。

    2floor:用于记录电梯所处楼层。

    3Wait:指向等待队列头节点的指针。

    4DiantiLI[10]:电梯里的人员数组,下标用于记录该层是否有人下电梯。

    5All:记录电梯里的人数。

    6Dir:用于判断电梯处于UpDown以外时之前所处的状态,以便于下一步的状态判断,-1为初始状态,0为下降,1为上升。

    函数有:(1setnowState(参数为需要设定的电梯状态):用于更改电梯状态。

    2setAll(参数为需要修改的乘客数量,有符号的整型):将参数与All参数进行加减。

    (3)setDir(参数为想要把Dir改变的值):将Dir改变为参数值。

    4JudgeGiveUp(参数为当前时间):用于判定当前是否有人放弃

    如果(指针不为空){

    如果(当前访问的节点的等待时间+忍耐时间==当前时间)

    删除该节点并提示  }

    (5)NoPassenger:主要是用于电梯处于闲置时的一些操作

    如果电梯是Waiting状态{

              如果holdtime(一个全局变量,用来检测是否达到300t==300并且floor不等于1{

              改变电梯状态为下降,并且把holdtime重新置0,进入MoveDown函数,返回true

              }

       如果holdtim==300并且floor等于1{

       输出“电梯空闲无人”并把holdtime置为0,返回true

              }

       如果电梯里外都没有人{

       输出“电梯空闲无人”,并且holdtime自加,返回true

             }

       其他情况就调用JudgeDirction函数,并且返回false

    }

              如果电梯不处于Waiting状态,调用JudgeDirction函数,并且返回false

    (6)JudgeDirction:得出不同情况下的最远请求,传递给MoveDirction用于改变状态

    如果状态为Closed{

         如果电梯里外都没有人{

             改变电梯状态并且返回空

         }

         如果floor1{     //因为此时是电梯里外肯定至少有一种情况不为空

        改变电梯状态为Up并且把Dir置为1

          }

         如果floor9{

        改变电梯状态为Down并且把Dir置为0

          }

          如果电梯里有人{

                遍历数组DiantiLi得到下标i,并通过i来改变电梯状态

          }

          如果电梯外不为空{

          //此时根据电梯关门前的Dir来进行判定是否前往接乘客,此时分4种情况,2种上行,2种下行

        如果Dir1{

          如果乘客楼层在当前楼层之上,才有可能前往接乘客{

                    如果该乘客是上行则将最远请求与该乘客的前往楼层对比,并进行更改

                    否则如果乘客是下行,就将最远请求与该乘客的当前楼层对比,并进行对比

                     }

                     对最远请求进行对比和更改

                 }

        如果Dir0{

                     如果乘客楼层在当前楼层之下,才有可能前往接乘客{

                     如果该乘客是下行则将最远请求与该乘客的前往楼层对比,并进行更改

                     否则如果乘客是上行,就将最远请求与该乘客的当前楼层对比,并进行对比

                     }

                     对最远请求进行对比和更改

                }

           }

    }

    如果状态为Waiting{

               循环遍历等待队列,找出最先按键的人,去响应该请求

               如果ptemp(指向头节点)不为空{

          如果便利到进入队列时间最早的乘客{

                           如果是电梯需要上行

                                则记录上行的最远请求

                           如果是电梯需要下行

                                则记录下行的最远请求

                           如果两者皆有

                                 则满足先上后下的原则来改变电梯的状态

                    }

               }

    }

    如果电梯状态为Up{

            如果电梯里有人{

         遍历DiantiLi数组得到电梯里的乘客的最远请求

             }

       如果等待队列有人{

                    遍历整个等待队列

                    如果有乘客要去的楼层或者当前楼层比最远请求大

                            则改变最远请求

              }

    }

    如果电梯状态为Down{

            如果电梯里有人{

          遍历DiantiLi数组得到电梯里的乘客的最远请求

             }

       如果等待队列有人{

                     遍历整个等待队列

                     如果有乘客要去的楼层或者当前楼层比最远请求小

                            则改变最远请求

               }

    }

    最后调用MoveDirction函数,并把最远请求传入

    7MoveDirction(参数为最远请求):通过最远请求和目前的状态来调用不同的函数

        如果最远请求小于当前楼层

               调用MoveDown并返回空

        如果最远请求大于当前楼层

               调用MoveUp并返回空

        如果电梯状态目前为Opening

               调用Open函数并返回空

        如果电梯状态目前为In

               调用IN函数,并且调用JudgeClose函数进行判定此时是否还有人要进入,并返回空

        如果电梯状态目前为Out

               调用OUT函数,并且调用JudgeClose函数进行判定此时是否还有人要进入,返回空

       如果电梯状态目前为Opened

               JudgeClose判定是否关门

               调用JudgeOut判定是否有人要出门,如果有人出去,调用OUT;调用JudgeIn判定是否有      人要进入,如果有人进入,调用IN,然后返回空

       如果电梯状态目前为Closing

              调用Close并返回空    

       如果最远请求等于当前楼层并且电梯里外都无人

              将电梯置为Waiting,并且进入NoPassenger输出电梯是空闲状态

       如果最远请求等于当前楼层且电梯里外是有人的

               此时将电梯置为Opening,并且进入Open   

    8MoveDown:输出电梯下楼每一t的状态

         如果record(全局变量,用于输出电梯每一t的状态)小于枚举的值

                record自加,输出“电梯正在下楼”并返回空

         如果等于枚举的值时

                 电梯的楼层自减1,并且record0

      如果JudgeOpenfalse则继续调用MoveDown显示下楼的状态

                 如果JudgeOpentrue则将电梯的状态置为Opening

    (9)MoveUp:输出电梯上楼每一t的状态

        如果record(全局变量,用于输出电梯每一t的状态)小于枚举的值

               record自加,输出“电梯正在上楼”并返回空

        如果等于枚举的值时

               电梯的楼层自加1,并且record0

     如果JudgeOpenfalse则继续调用MoveUp显示上楼的状态

                如果JudgeOpentrue则将电梯的状态置为Opening

    10Open:显示电梯开门状态每一t的状态

          如果当前状态不为Opening

                设置当前状态为Opening,把record置为0,然后返回空

          如果record小于枚举的值

                 record自加,输出“电梯开门中”,返回空

          如果是其他情况{

                 record置为0,输出“开门完成”,将当前状态置为Opened

                 如果JudgeOuttrue就调用OUT

                 如果JudgeIntrue就调用IN

                 JudgeClose判断是否关门

           }

    11IN:显示哪些乘客进入电梯以及判定语句

    如果电梯里人少于13{

                 如果record小于枚举值{

                        如果当前状态为Opened{

                                 record自加,遍历等待队列,并且加入判断乘客当前楼层必须是等于floor才能             进入电梯

                         }

            如果当前状态为In{

                          record自加,输出“乘客正在进入电梯”,返回空

                         }

                 }

         如果是等于枚举值{

                         record置为0,并且将当前状态置为Opened

                  }

    }

    如果电梯里的人数大于13{

       输出“电梯内人数已经达到最大值”,将当前状态置为Closing

    }

    (12)JudgeClose:判断当前电梯是否可以关门

    如果当前状态为Opened{

       如果record小于枚举值{

                    record自加,输出“正在关门检测”,然后返回空

              }

       如果等于枚举值{

          输出“关门检测结束”

          如果当前状态为Opened{

                            record置为0,调用Close函数

                     }

          否则 record置为0,并且返回空

                }

    }

    其他情况返回空

    13Close:显示电梯关门时每一t的状态

    如果record小于枚举值{

            record自加,设置当前状态为Closing,输出“电梯正在关门中”

    }

    其他情况{

             record置为0,输出“电梯已经关门”,设置当前状态为Closed

             如果最大请求为floor{

                     如果电梯里外有人{

                             遍历整个等待队列

                             如果此时等待队列有人发出请求

                             如果停止前电梯是向上走的

                则判断是否在当前楼层之上或者就是当前楼层,如果满足就设置当前状态为Opening

                            如果停止前电梯是向下走的

                                    则判断是否在当前楼层之下或者就是当前楼层,如果满足就设置当前状态为Opening

                      }

                       如果电梯里外都没人

                             设置当前状态为Waiting,把Dir置为-1

                }

        如果最大请求不是当前楼层{

                      保持停止前电梯的状态不变

                }

    }

    调用NoPassenger

    14OUT:记录乘客下电梯的每一t的状态

    如果record小于枚举值{

       如果当前状态为Opened{

                     record自加

                     如果电梯里有人要下电梯{

             根据数组DiantiLi来判定下去多少个乘客并且输出下去时每一t状态,并且设置当前状态为Out,返回空

                      }

              }

              如果当前状态为Out{

                      record自加,输出“乘客正在下电梯”,返回空

               }

              其他情况则输出“需要下的乘客都已下去”,record置为0,并且把当前状态置为Opened

    }

    15JudgeIn:判断是否可以进乘客

     如果All不为13{

              如果等待队列不为空{

                       如果乘客是向上走的并且当前楼层在该层并且电梯之前的方向为向上

                                则允许进入,返回true

                       如果乘客是向下走的并且当前楼层在该层并且电梯之前的方向为向下

                               则允许进入,返回true

                  }

      }

    遍历完若没有返回true则此时返回false

    16JudgeOut:判断乘客是否可以出去

    如果电梯里有人{

            数组DiantiLi中的该层楼的下标值中的数据不为0,则返回true

    }

    否则返回false

    3、源程序清单

    passenger.h     //乘客类头文件,存放乘客的相关信息以及更改值的接口函数

    elevator.h      //电梯类头文件,存放枚举信息以及电梯的属性和相关判断函数

    Node.h        //节点类头文件,用于创建链表以及链表相关的操作函数

    main.cpp       //主函数,主要调用乘客类的设置属性函数,电梯类的JudgeGiveUp函数,以及电梯类的addpassenger函数,并且显示现在是多少t

    4、源代码

    passenger.h     //乘客类头文件,存放乘客的相关信息以及更改值的接口函数

     1 #ifndef PASSENGER_H
     2 #define PASSENGER_H
     3 #include<iostream>
     4 using namespace std;
     5 
     6 class passenger {
     7 private:
     8     int ID;
     9     int nowfloor;
    10     int gofloor;
    11     int whenwait;
    12 public:
    13     passenger();
    14     void setdata(int ID1);
    15     void setnowfloor(int nowfloor1);
    16     void setgofloor(int gofloor1);
    17     void setwhenwait(int whenwait1);
    18     int getnowfloor()const;
    19     int getgofloor()const;
    20     int getID()const;
    21     int getwhenwait()const;
    22 };
    23 
    24 passenger::passenger() {
    25     ID = 0;
    26     nowfloor = 0;
    27     gofloor = 0;
    28     whenwait = 0;
    29 }
    30 
    31 void passenger::setdata(int ID1) {
    32     ID = ID1; int i = 1;
    33     while (i) {
    34         cout << "请输入第" << ID << "位乘客的信息" << endl;
    35         cout << "该乘客目前在哪一层:"; cin >> nowfloor;
    36         cout << "该乘客去哪一层:"; cin >> gofloor;
    37         cout << "该乘客何时上电梯:"; cin >> whenwait;
    38         if (nowfloor > 9 || nowfloor < 0) {
    39             cout << "乘客目前的楼层有误,请重输入!" << endl;
    40         }
    41         if (gofloor > 9 || gofloor < 0) {
    42             cout << "乘客要去的楼层有误,请重输入!" << endl;
    43         }
    44         else i = 0;
    45     }
    46 }
    47 
    48 void passenger::setnowfloor(int nowfloor1) {
    49     nowfloor = nowfloor1;
    50 }
    51 
    52 void passenger::setgofloor(int gofloor1) {
    53     gofloor = gofloor1;
    54 }
    55 
    56 void passenger::setwhenwait(int whenwait1) {
    57     whenwait = whenwait1;
    58 }
    59 
    60 int passenger::getnowfloor()const {
    61     return nowfloor;
    62 }
    63 
    64 int passenger::getgofloor()const {
    65     return gofloor;
    66 }
    67 
    68 int passenger::getID()const {
    69     return ID;
    70 }
    71 
    72 int passenger::getwhenwait()const {
    73     return whenwait;
    74 }
    75 
    76 #endif // !PASSENGER_H
    77 #pragma once
    passenger.h

    elevator.h      //电梯类头文件,存放枚举信息以及电梯的属性和相关判断函数

      1 #ifndef ELEVATOR_H
      2 #define ELEVATOR_H
      3 #include"Node.h"
      4 #include"passenger.h"
      5 
      6 enum state {
      7     Opening,
      8     Opened,
      9     Closing,
     10     Closed,
     11     Waiting,
     12     Up,
     13     Down,
     14     In,
     15     Out,
     16     Decelerate
     17 };
     18 
     19 int holdtime = 0,record=0,near=0;
     20 enum timeX
     21 {
     22     test = 40,
     23     open = 20,
     24     close = 20,
     25     in = 25,
     26     out = 25,
     27     quick = 15,
     28     up = 51,
     29     updecelerate = 14,
     30     down = 61,
     31     downdecelerate = 23,
     32     peoplewait = 500,
     33     wait = 300
     34 };
     35 
     36 class elevator {
     37 private:
     38     state State=Waiting;
     39     int floor = 1;
     40     PNODE Wait=p_head;    
     41     int DiantiLi[10] = {0};
     42     int All = 0;
     43     int Dir=-1;//判断上下的情况
     44 public:
     45     state getnowState()const;
     46     void setnowState(state t);
     47     int getfloor()const;
     48     void setfloor(int floor1);
     49     int getAll()const;
     50     void setAll(int num);//num为外部上电梯的人数
     51     int getDir()const;
     52     void setDir(int x);
     53     void addpassenger(const passenger &x);//添加乘客
     54     bool NoPassenger();//判断是否有乘客请求
     55     void JudgeDirction();//判断电梯行走方向
     56     bool JudgeOpen();//判断是否开门
     57     void Open();//电梯门打开
     58     bool JudgeOut();//判断乘客出去
     59     void OUT();//乘客出去
     60     bool JudgeIn();//判断乘客进入
     61     void IN();//乘客进入
     62     void Close();//关门
     63     void MoveUp();//向上移动
     64     void MoveDown();//向下移动
     65     void JudgeClose();//40t时间来判断是否关门
     66     void MoveDirction(const int floor1);//用来改变电梯的状态
     67     void JudgeGiveUp(int waittime);//判断是否有人放弃,用在函数最开始
     68 };
     69 
     70 state elevator::getnowState()const {
     71     return State;
     72 }
     73 void elevator::setnowState(state t) {
     74     State = t;
     75 }
     76 int elevator::getfloor()const {
     77     return floor;
     78 }
     79 void elevator::setfloor(int floor1) {
     80     floor = floor1;
     81 }
     82 int elevator::getAll()const {
     83     return All;
     84 }
     85 void elevator::setAll(int num) {
     86        All += num;
     87 }
     88 int elevator::getDir()const {
     89     return Dir;
     90 }
     91 void elevator::setDir(int num) {
     92     Dir = num;
     93 }
     94 void elevator::addpassenger(const passenger &x) {
     95     append(x);
     96     cout << "" << x.getID() << "名乘客进入等待队列 " ;
     97 }
     98 bool elevator::NoPassenger() {
     99     //用于判断电梯是否接收乘客的请求
    100     if (getnowState() == Waiting) {
    101         if (holdtime == 300 &&floor!=1 ) {
    102             //如果等够了300t并且不在1楼的话,开始下行
    103             setnowState(Down);
    104             setDir(0);
    105             holdtime = 0;
    106             MoveDown();
    107             return true;
    108         }
    109         else if (holdtime== 300 && floor == 1) {
    110             //如果电梯本身在一楼则不需要进行操作
    111             cout<< "电梯空闲无人,正在等待";
    112             holdtime = 0;
    113             return true;
    114         }
    115         else if (All == 0 && empty()==true) {
    116             cout << "电梯空闲无人,正在等待";
    117             holdtime++;
    118             return true;
    119         }
    120         else {
    121             JudgeDirction();
    122             return false;
    123         }
    124     }
    125     else {
    126         JudgeDirction();
    127         return false;
    128     }
    129 }
    130 
    131 void elevator::JudgeDirction() {
    132     //使用该函数进行判断电梯的走向
    133     near = floor;//初始化near的值,为防止不满足条件的情况出现时依旧可以使用MoveDirction函数
    134     int upoutfar = 0, downoutfar = 10;//定义2个记录上下出去最远请求的变量
    135     int upinfar = 0, downinfar = 10;//定义2个记录上下进来最远请求的变量
    136     if (State == Closed) {
    137         if (getAll() == 0 && empty()==true) {
    138             setnowState(Waiting);
    139             return;
    140         }
    141         if (floor == 1) {
    142             setnowState(Up); setDir(1);
    143         }
    144         if (floor == 9) {
    145             setnowState(Down); setDir(0);
    146         }
    147         if (getAll() != 0) {//电梯里依旧有人
    148             //此时需要区分电梯的运行方向,分两种情况来处理(目前还未处理)
    149                 for (int i = 1; i < 10; i++) {
    150                     if (DiantiLi[i] != 0) {
    151                         near = i;
    152                         if (i > floor) {
    153                             upinfar = i;
    154                             setnowState(Up);
    155                             setDir(1);
    156                             break;
    157                         }
    158                         else if (i < floor) {
    159                             downinfar = i;
    160                             setnowState(Down);
    161                             setDir(0);
    162                             break;
    163                         }
    164                     }
    165                 }
    166             }
    167         if (empty() == false) {//电梯外等待的人不为空
    168                 PNODE ptemp=p_head->next;
    169                 while (ptemp!=NULL) {
    170                     if (getDir() == 1) {//只接上行乘客
    171                         if (ptemp->data.getnowfloor() > floor) {//乘客所处楼层在电梯楼层上,这样才有可能电梯前往接人
    172                             //开始检索在链表中的乘客,并且进行判断是否有要上行的
    173                             if (ptemp->data.getgofloor() > ptemp->data.getnowfloor()) {
    174                                 //代表此人是上行,并且是在电梯运行方向的楼上,需要前往接人
    175                                 if (ptemp->data.getgofloor() > upoutfar)upoutfar = ptemp->data.getgofloor();
    176                             }
    177                             if (ptemp->data.getgofloor() < ptemp->data.getnowfloor()) {
    178                                 if (ptemp->data.getnowfloor() > upoutfar)upoutfar = ptemp->data.getnowfloor();
    179                             }
    180                         }
    181                         if (upinfar == 0 && upoutfar == 0) { setnowState(Down); setDir(0); }
    182                         if (upinfar <= upoutfar)near = upoutfar;
    183                         else near = upinfar;
    184                     }
    185 
    186                     else if (getDir() == 0) {//只接下行乘客
    187                         if (ptemp->data.getnowfloor() < floor) {//乘客所处楼层在电梯楼层下,这样才有可能电梯前往接人
    188                                     //开始检索在链表中的乘客,并且进行判断是否有要下行的
    189                             if (ptemp->data.getgofloor() < ptemp->data.getnowfloor()) {
    190                                 //代表此人是下行,并且是在电梯运行方向的楼下,需要前往接人
    191                                 if (ptemp->data.getgofloor() < downoutfar)downoutfar = ptemp->data.getgofloor();
    192                             }
    193                             if (ptemp->data.getgofloor() > ptemp->data.getnowfloor()) {
    194                                 if (ptemp->data.getnowfloor() < downoutfar)downoutfar = ptemp->data.getnowfloor();
    195                             }
    196                         }
    197                         if (downinfar == 10 && downoutfar == 10) { setnowState(Up); setDir(1); }
    198                         if (downinfar <= downoutfar)near = downinfar;
    199                         else near = downoutfar;
    200                     }
    201                     ptemp = ptemp->next;
    202                 }
    203             }
    204         
    205     }
    206     if (State == Waiting) {
    207         PNODE ptemp = p_head->next;
    208         int time_now = 0;
    209         while (ptemp!=NULL) {
    210             int Time_now = ptemp->data.getwhenwait();//用于记录最先按的人
    211             time_now = Time_now;
    212             if(ptemp->data.getwhenwait()<time_now){//挑选出最先按键的人,然后进行改变电梯的方向
    213                 time_now = ptemp->data.getwhenwait();
    214             }
    215             ptemp = ptemp->next;
    216         }
    217         ptemp = p_head->next;
    218         while (ptemp != NULL) {
    219             int up(floor), down(floor);
    220             if (ptemp->data.getwhenwait() == time_now) {
    221                 int x = ptemp->data.getgofloor() - ptemp->data.getnowfloor();
    222                 //此时会出现4种情况,并且只会有2种是电梯上行,2种是电梯下行
    223                 if ((x > 0&& (ptemp->data.getnowfloor()>floor))||(x<0&& (ptemp->data.getnowfloor()>floor))) {
    224                     setnowState(Up); 
    225                     setDir(1);
    226                     upinfar = ptemp->data.getnowfloor();
    227                     if (up < upinfar) {
    228                         up = upinfar;
    229                     }
    230                 }
    231                 else if ((x > 0 && (ptemp->data.getnowfloor()<floor)) || (x<0 && (ptemp->data.getnowfloor()<floor))) {
    232                     setnowState(Down); 
    233                     setDir(0);
    234                     downinfar = ptemp->data.getnowfloor();
    235                     if (down > downinfar) {
    236                         down = downinfar;
    237                     }
    238                 }
    239                 if (down != floor&&up != floor) {//当上下同时有人请求时,满足先上的原则
    240                     setnowState(Up); near = upinfar; setDir(1);
    241                 }
    242                 else if (up != floor) {//只有上行的请求
    243                     setnowState(Up); near = upinfar; setDir(1);
    244                 }
    245                 else if (down != floor) {//只有下行的请求
    246                     setnowState(Down); near = downinfar; setDir(0);
    247                 }
    248                 if (floor == 1) { setnowState(Up); setDir(1); }
    249             }
    250             ptemp = ptemp->next;
    251         }
    252         if (near == floor)  Open();
    253     }
    254     if (State == Up) {
    255         if (getAll()!=0) {//电梯里有人
    256             for (int i = 1; i < 10; i++) {
    257                 if (DiantiLi[i] != 0) {
    258                     if (i >= near) {
    259                         upinfar = i;
    260                     }
    261                 }
    262             }
    263         }
    264         if (empty() == false) {
    265             PNODE ptemp = p_head->next;
    266             while (ptemp != NULL) {
    267                 if (ptemp->data.getnowfloor() >= near) {
    268                     if (ptemp->data.getgofloor() >= upoutfar) {
    269                         upoutfar = ptemp->data.getgofloor();
    270                     }
    271                     if (ptemp->data.getnowfloor() >= upoutfar) {
    272                         upoutfar = ptemp->data.getnowfloor();
    273                     }
    274                 }
    275                 ptemp = ptemp->next;
    276             }            
    277         }
    278         if (upinfar >= upoutfar)near = upinfar;
    279         else near = upoutfar;
    280     }
    281     if (State == Down) {
    282         //downinfar = 10, downoutfar = 10;
    283         if (getAll() != 0) {//电梯里有人
    284             for (int i = 1; i < 10; i++) {
    285                 if (DiantiLi[i] != 0) {
    286                     if (i <= near) {
    287                         downinfar = i;
    288                         break;
    289                     }
    290                 }
    291             }
    292         }
    293         if (empty() == false) {
    294             PNODE ptemp = p_head->next;
    295             while (ptemp != NULL) {
    296                 if (ptemp->data.getnowfloor() <= near) {
    297                     if (ptemp->data.getnowfloor() <= downoutfar) {
    298                         downoutfar = ptemp->data.getnowfloor();
    299                     }
    300                     if (ptemp->data.getgofloor() <= downoutfar) {
    301                         downoutfar = ptemp->data.getgofloor();
    302                     }
    303                 }
    304                 ptemp = ptemp->next;
    305             }
    306         }
    307         if (getAll() == 0 && empty() == true)near = 1;
    308         else if (downinfar >= downoutfar)near = downoutfar;
    309         else near = downinfar;
    310     }
    311     MoveDirction(near);
    312 }
    313 
    314 bool elevator::JudgeOpen() {//判断此楼层是否有人需要进出
    315     if (JudgeIn() || JudgeOut()) {
    316         Open();
    317         return true;
    318     }
    319     else return false;
    320 }
    321 
    322 void elevator::Open() {
    323     if (getnowState() != Opening) {
    324         setnowState(Opening);
    325         record = 0;
    326         return ;
    327     }
    328     if (record < open) {
    329         record++;
    330         cout << "电梯开门中";
    331         return;
    332     }
    333     else {//开门完成后
    334         record = 0;
    335         cout << "开门完成";
    336         setnowState(Opened);
    337         if (JudgeOut())OUT();
    338         if (JudgeIn())IN();
    339         JudgeClose();
    340     }
    341 }
    342 
    343 bool elevator::JudgeOut() {
    344     if (getAll() != 0) {
    345         int j = floor;
    346         if (DiantiLi[j] != 0)return true;
    347     }
    348     return false;
    349 }
    350 
    351 void elevator::OUT() {
    352     if (record < out) {
    353         if (getnowState() == Opened) {
    354             record++;
    355             cout << "乘客正在下电梯";
    356             if (DiantiLi[floor] != 0) {
    357                 cout << "在该层一共下去" << DiantiLi[floor] << "个人";
    358                 setAll(-DiantiLi[floor]);
    359                 DiantiLi[floor] = 0;
    360             }
    361             setnowState(Out);
    362             return;
    363         }
    364         if (getnowState() == Out) {
    365             record++;
    366             cout<< "乘客正在下电梯";
    367             return;
    368         }
    369     }
    370     else {
    371         cout << "电梯里需要下的乘客都已下去";
    372         record = 0;
    373         setnowState(Opened);
    374     }
    375 }
    376 
    377 bool elevator::JudgeIn() {//如果电梯未满,则返回true,可以继续进人
    378     //目前需要完善,因为是先把人删除输入进数组,所以需要进行有个判断
    379     if (getAll() != 13) {
    380         if (!empty()) {//不为空则执行if语句
    381             PNODE ptemp = p_head->next; int upnum1=0,downnum1=0;
    382             while (ptemp != NULL) {
    383                 if (ptemp->data.getnowfloor() == floor) {
    384                         if ((ptemp->data.getnowfloor() < ptemp->data.getgofloor()) && (getDir() > 0)) {
    385                             //乘客是往上走的
    386                             return true;
    387                         }
    388                         if ((ptemp->data.getnowfloor() > ptemp->data.getgofloor()) && (getDir() == 0)) {
    389                             //乘客下行
    390                             return true;
    391                         }
    392                         if (near == ptemp->data.getnowfloor()) {
    393                         //达到了最大请求楼层,如果是与电梯方向同向,则不改变方向,并且允许进入
    394                         //如果不与电梯同向,则改变方向,如果两个情况都有,就优先满足同方向的
    395                             if (getDir() == 1) {
    396                                 if (ptemp->data.getnowfloor() < ptemp->data.getgofloor()) {
    397                                     setDir(1); upnum1++;
    398                                 }
    399                                 if (ptemp->data.getnowfloor() > ptemp->data.getgofloor()) {
    400                                     setDir(0); downnum1++;
    401                                 }
    402                                 if (upnum1 != 0 && downnum1 != 0)setDir(1);
    403                             }
    404                             else if (getDir()==0) {
    405                                 if (ptemp->data.getnowfloor() < ptemp->data.getgofloor()) {
    406                                     setDir(1); upnum1++;
    407                                 }
    408                                 if (ptemp->data.getnowfloor() > ptemp->data.getgofloor()) {
    409                                     setDir(0);  downnum1++;
    410                                 }
    411                                 if (upnum1 != 0 && downnum1 != 0)setDir(0);
    412                             }
    413                             return true;
    414                         }
    415                 }
    416                 ptemp = ptemp->next;
    417             }
    418         }
    419     }
    420     return false;
    421 }
    422 
    423 void elevator::IN() {
    424     if (getAll() < 13) {
    425         if (record < in)
    426         {
    427             if (getnowState() == Opened) {
    428                 record++;
    429                 PNODE ptemp = p_head->next;
    430                 while (ptemp != NULL) {
    431                     if(ptemp->data.getnowfloor()==floor){//首先人得在电梯楼层,这才能进行判定
    432                     if ((ptemp->data.getnowfloor() < ptemp->data.getgofloor()) && (getDir() > 0)) {
    433                         //乘客是往上走的
    434                         cout << "" << ptemp->data.getID() << "个乘客正在进入电梯";
    435                         DiantiLi[ptemp->data.getgofloor()] += 1;
    436                         setAll(1);
    437                         Remove(ptemp->data.getID());
    438                         setnowState(In);
    439                         return;
    440                     }
    441                     if ((ptemp->data.getnowfloor() > ptemp->data.getgofloor()) && (getDir() == 0)) {
    442                         //乘客下行
    443                         cout << "" << ptemp->data.getID() << "个乘客正在进入电梯";
    444                         DiantiLi[ptemp->data.getgofloor()] += 1;
    445                         setAll(1);
    446                         Remove(ptemp->data.getID());
    447                         setnowState(In);
    448                         return;
    449                     }
    450                     }
    451                     ptemp = ptemp->next;
    452                 }
    453             }
    454             if (getnowState() == In) {
    455                 record++;
    456                 cout << "乘客正在进入电梯";
    457                 return;
    458             }
    459         }
    460         else {
    461             cout << "乘客已经进入电梯";
    462             record = 0;
    463             setnowState(Opened);
    464         }
    465     }
    466     else {
    467         cout << "电梯内人数已经达到最大值";
    468         setnowState(Closing);
    469     }
    470 }
    471 
    472 void elevator::Close() {
    473     if (record < close) {
    474         record++;
    475         setnowState(Closing);
    476         cout << "电梯正在关门中";
    477     }
    478     else {
    479         record = 0;
    480         cout << "电梯已经关门";
    481         setnowState(Closed);
    482         if (near == floor) {//电梯已经到达最大请求楼层,可能会出现4种情况
    483             if (empty() == false||getAll()!=0) {//等待队列有人或电梯里也有人
    484             PNODE ptemp = p_head->next; int OutPeople = 0;
    485             while (ptemp != NULL) {
    486                 if (ptemp->data.getnowfloor() == floor)OutPeople += 1;
    487                 if (getAll() != 0 && OutPeople!=0) {//电梯里有人,外面有人       判断去的方向
    488                     if (getDir() == 1 && (ptemp->data.getgofloor() > floor)) {//电梯上行,乘客上行,开门
    489                         setnowState(Opening);
    490                     }
    491                     else if (getDir() == 0 && (ptemp->data.getgofloor() < floor)) {//电梯下行,乘客下行,开门
    492                         setnowState(Opening);
    493                     }
    494                 }
    495                 if (getAll() == 0 && OutPeople != 0) {//电梯没人,外面有人
    496                     if (getDir() == 1 ) {//电梯上行
    497                         if (ptemp->data.getgofloor() > floor)
    498                         setnowState(Opening);
    499                         else if (ptemp->data.getgofloor() < floor) {
    500                             setDir(0); setnowState(Opening);
    501                         }
    502                     }
    503                     if (getDir() == 0) {//电梯下行
    504                         if (ptemp->data.getgofloor() < floor)
    505                             setnowState(Opening);
    506                         else if (ptemp->data.getgofloor() > floor) {
    507                             setDir(1); setnowState(Opening);
    508                         }
    509                     }
    510                 }
    511                 if (getAll() != 0 && OutPeople==0) {
    512                     //电梯里有人,外面没人,此时应该分是否继续送乘客上行或者下行,首先遍历数组得到乘客要去几层
    513                     for (int i = 1; i < 10; i++) {
    514                         if (DiantiLi[i] != 0) {
    515                             if (i < floor) { setnowState(Down); setDir(0); }
    516                             if (i > floor) { setnowState(Up); setDir(1); }
    517                         }
    518                     }
    519 
    520                 }
    521                 ptemp = ptemp->next;
    522             }
    523             }
    524             else if(empty() == true && getAll() == 0){//等待队列没人,电梯也没人
    525                 setnowState(Waiting); setDir(-1);
    526             }
    527         }
    528         else if (near != floor) {
    529             if (getDir() == 1) {
    530                 setDir(1); setnowState(Up);
    531             }
    532             if (getDir() == 0) {
    533                 setDir(0); setnowState(Down);
    534             }
    535         }
    536         NoPassenger();
    537     }
    538 }
    539 
    540 void elevator::MoveUp() {
    541     if (record<up) {
    542         record++;
    543         cout << "电梯正在上楼";
    544         return;
    545     }
    546     else {
    547         floor++;
    548         record = 0;
    549         if (JudgeOpen() == false)
    550             MoveUp();
    551         else {
    552             cout << "电梯正在上楼";
    553             setnowState(Opening);
    554         }
    555     }
    556 
    557 }
    558 
    559 void elevator::MoveDown() {
    560     if (record<down) {
    561         record++;
    562         cout << "电梯正在下楼";
    563         return;
    564     }
    565     else {
    566         floor--;
    567         record = 0;
    568         if (JudgeOpen() == false)MoveDown();
    569         else {
    570             cout << "电梯正在下楼";
    571             setnowState(Opening);
    572         }
    573     }
    574 }
    575 
    576 void elevator::JudgeClose() {
    577     if (getnowState() == Opened){
    578         if (record < test) {
    579             record++;
    580             cout << "正在关门检测";
    581             return;
    582         }
    583         else {
    584             cout << "关门检测结束";
    585             if (getnowState() == Opened) {
    586                 record = 0;
    587                 Close();
    588                 return;
    589             }
    590             else {//疑似可以删除    
    591                 record = 0;
    592                 return;
    593             }
    594         }
    595      }
    596     else return;
    597 }
    598 
    599 void elevator::MoveDirction(const int near) {
    600     //near为乘客的请求最远的楼层
    601     if (near<floor) {
    602         setnowState(Down);
    603         setDir(0);
    604         MoveDown();
    605         return;
    606     }
    607     if (near>floor) {
    608         setnowState(Up);
    609         setDir(1);
    610         MoveUp();
    611         return;
    612     }
    613     if (getnowState()==Opening) {
    614         Open();
    615         return;
    616     }
    617     if (getnowState() == In) {
    618         IN();
    619         JudgeClose();
    620         return;
    621     }
    622     if (getnowState() == Out) {
    623         OUT();
    624         JudgeClose();
    625         return;
    626     }
    627     if (getnowState()== Opened) {
    628         JudgeClose();
    629         if (JudgeOut())OUT();
    630         if (JudgeIn())IN();
    631         return;
    632     }
    633     if (getnowState() == Closing) {
    634         Close();
    635         return;
    636     }
    637     if (near == floor&&empty()==true&&getAll()==0) {
    638         setnowState(Waiting);
    639         NoPassenger();
    640         return;
    641     }
    642     if (near == floor) {
    643         setnowState(Opening);
    644         Open();
    645         return;
    646     }
    647 }
    648 
    649 void elevator::JudgeGiveUp(int waittime) {
    650     //一进入系统则先判断该时刻是否有人放弃
    651     //waittime为现在的时间,用于和乘客等待的时间+wait来进行判断乘客是否放弃
    652     PNODE ptemp=p_head->next;
    653     while (ptemp != NULL) {
    654         if ((ptemp->data.getwhenwait() + peoplewait) <= waittime) {
    655             cout << "" << ptemp->data.getID() << "名乘客已放弃等待  ";
    656             Remove(ptemp->data.getID());
    657         }
    658         ptemp = ptemp->next;
    659     }
    660     NoPassenger();
    661 }
    662 
    663 #endif // ELEVATOR_H
    664 #pragma once
    elevator.h

    Node.h        //节点类头文件,用于创建链表以及链表相关的操作函数

     1 #ifndef NODE_H
     2 #define NODE_H
     3 #include<iostream>
     4 #include"passenger.h"
     5 using namespace std;
     6 
     7 typedef struct node {
     8     passenger data;
     9     struct node* next;
    10 }NODE, *PNODE;
    11 
    12 NODE head;//头节点
    13 
    14 PNODE p_head = &head;//头指针
    15 PNODE p_tail = &head;//尾指针
    16 
    17 void append(passenger data) {
    18     PNODE pnew = (PNODE)malloc(sizeof(NODE));
    19     pnew->data = data; pnew->next = NULL;
    20     if (p_head == NULL) {
    21         p_head = pnew;
    22         p_tail = pnew;
    23     }
    24     else {
    25         p_tail->next = pnew;
    26         p_tail = pnew;
    27     }
    28 }
    29 
    30 bool empty() {
    31     if (p_head->next == NULL)return true;
    32     else return false;
    33 }
    34 
    35 void Remove(int ID) {//data为节点所存储的数据,查到就删除
    36     int pnew = ID;
    37     PNODE ptemp = p_head->next;
    38     if (ptemp->data.getID() == pnew) {
    39         if (ptemp == p_tail) {//如果就一个节点
    40             p_head->next = ptemp->next;
    41             p_tail = p_head;
    42             ptemp = NULL;
    43         }
    44         else { //如果是多个节点
    45             p_head->next = ptemp->next;
    46             ptemp = NULL;
    47         }
    48     }
    49     while (ptemp !=NULL) {
    50         if (ptemp->next->data.getID() == pnew) {
    51             if (ptemp->next == p_tail) {
    52                 ptemp->next = NULL;
    53                 p_tail = ptemp;
    54             }
    55             else ptemp->next = ptemp->next->next;
    56         }
    57         ptemp = ptemp->next;        
    58     }
    59 }
    60 
    61 #endif // !NODE_H
    62 #pragma once
    Node.h

    main.cpp       //主函数,主要调用乘客类的设置属性函数,电梯类的JudgeGiveUp函数,以及电梯类的addpassenger函数,并且显示现在是多少t

     1 #include"elevator.h"
     2 
     3 int main() {
     4     long int time = 0;
     5     int a = 0,j=1;
     6     cout << "请输入共有几位乘客使用电梯:";
     7     cin >> a;
     8     passenger *people = new passenger[a+1];
     9     for (int i = 1; i < a+1; i++) {
    10         people[i].setdata(i);
    11         cout << endl;
    12     }
    13     elevator x;
    14     long int Time = 0;
    15     for (int b = 1; b < a + 1; b++) {
    16         if (people[b].getwhenwait() > Time)Time = people[b].getwhenwait();
    17     }
    18     Time = a*1000;//此处的设置并不是最优解,目前还没有找到一个比较合适的值代替
    19     for (; time < Time; time++) {
    20         cout << time << "t时刻  ";
    21         for (int i = 1; i < a + 1; i++) {
    22             if (people[i].getwhenwait() == time)x.addpassenger(people[i]);
    23         }
    24         cout << "电梯在" << x.getfloor() << "";
    25         x.JudgeGiveUp(time);
    26         cout << endl;
    27     }
    28     delete[]people;
    29     return 0;
    30 }
    main.cpp
  • 相关阅读:
    IPython notebook(Jupyter notebook)指定IP和端口运行
    spark-2.2.0安装和部署——Spark集群学习日记
    安装Scala-2.11.7——集群学习日记
    hadoop2.7.3在centos7上部署安装(单机版)
    Centos7下面配置静态IP
    css 3列
    css 日历组件(浮雕效果)
    if(!document.getElementById) return false; JS里这句是什么意思?
    网页中图片路径错误时显示默认图片方法
    css3 图片放大缩小闪烁效果
  • 原文地址:https://www.cnblogs.com/ShadowKiller/p/8748705.html
Copyright © 2020-2023  润新知