源码在文章结尾,需要者自取(有问题欢迎评论批评指教)
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:存储乘客的相关信息,以便于在电梯模块中使用。
(2)struct node*类型的next,用于链接下一个节点。
函数有:(1)append(形参为乘客类数据):因为有头尾指针和头节点,只要把形参链接到尾部即可。
(2)empty:只要头指针指向的next为空就返回true,否则就返回false。
(3)Remove(形参为乘客的ID):if当前节点是否就是所要删除的节点,如果是就根据是否是仅此一个节点或者是多个节点来分开处理;else当前节点不是要删除的节点,那么遍历整个链表去寻找所要删除的节点。
乘客类passenger中
成员有:(1)ID:用于设置乘客的编号。
(2)nowfloor:用于记录乘客当前楼层。
(3)gofloor:用于记录乘客需要去的楼层。
(4)whenwait:用于记录乘客多久进入等待队列。
函数有:(1)默认构造函数以及接口函数。
(2)setdata(参数为乘客ID):对该ID下的乘客进行赋值,并且限制乘客的当前楼层和所要前往的楼层为1-9,一旦超出范围则提示需要重新输入数据。
电梯类elevator中
成员有:(1)State:用于记录电梯的状态。
(2)floor:用于记录电梯所处楼层。
(3)Wait:指向等待队列头节点的指针。
(4)DiantiLI[10]:电梯里的人员数组,下标用于记录该层是否有人下电梯。
(5)All:记录电梯里的人数。
(6)Dir:用于判断电梯处于Up和Down以外时之前所处的状态,以便于下一步的状态判断,-1为初始状态,0为下降,1为上升。
函数有:(1)setnowState(参数为需要设定的电梯状态):用于更改电梯状态。
(2)setAll(参数为需要修改的乘客数量,有符号的整型):将参数与All参数进行加减。
(3)setDir(参数为想要把Dir改变的值):将Dir改变为参数值。
(4)JudgeGiveUp(参数为当前时间):用于判定当前是否有人放弃
如果(指针不为空){
如果(当前访问的节点的等待时间+忍耐时间==当前时间)
删除该节点并提示 }
(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{
如果电梯里外都没有人{
改变电梯状态并且返回空
}
如果floor为1{ //因为此时是电梯里外肯定至少有一种情况不为空
改变电梯状态为Up并且把Dir置为1
}
如果floor为9{
改变电梯状态为Down并且把Dir置为0
}
如果电梯里有人{
遍历数组DiantiLi得到下标i,并通过i来改变电梯状态
}
如果电梯外不为空{
//此时根据电梯关门前的Dir来进行判定是否前往接乘客,此时分4种情况,2种上行,2种下行
如果Dir为1{
如果乘客楼层在当前楼层之上,才有可能前往接乘客{
如果该乘客是上行则将最远请求与该乘客的前往楼层对比,并进行更改
否则如果乘客是下行,就将最远请求与该乘客的当前楼层对比,并进行对比
}
对最远请求进行对比和更改
}
如果Dir为0{
如果乘客楼层在当前楼层之下,才有可能前往接乘客{
如果该乘客是下行则将最远请求与该乘客的前往楼层对比,并进行更改
否则如果乘客是上行,就将最远请求与该乘客的当前楼层对比,并进行对比
}
对最远请求进行对比和更改
}
}
}
如果状态为Waiting{
循环遍历等待队列,找出最先按键的人,去响应该请求
如果ptemp(指向头节点)不为空{
如果便利到进入队列时间最早的乘客{
如果是电梯需要上行
则记录上行的最远请求
如果是电梯需要下行
则记录下行的最远请求
如果两者皆有
则满足先上后下的原则来改变电梯的状态
}
}
}
如果电梯状态为Up{
如果电梯里有人{
遍历DiantiLi数组得到电梯里的乘客的最远请求
}
如果等待队列有人{
遍历整个等待队列
如果有乘客要去的楼层或者当前楼层比最远请求大
则改变最远请求
}
}
如果电梯状态为Down{
如果电梯里有人{
遍历DiantiLi数组得到电梯里的乘客的最远请求
}
如果等待队列有人{
遍历整个等待队列
如果有乘客要去的楼层或者当前楼层比最远请求小
则改变最远请求
}
}
最后调用MoveDirction函数,并把最远请求传入
(7)MoveDirction(参数为最远请求):通过最远请求和目前的状态来调用不同的函数
如果最远请求小于当前楼层
调用MoveDown并返回空
如果最远请求大于当前楼层
调用MoveUp并返回空
如果电梯状态目前为Opening
调用Open函数并返回空
如果电梯状态目前为In
调用IN函数,并且调用JudgeClose函数进行判定此时是否还有人要进入,并返回空
如果电梯状态目前为Out
调用OUT函数,并且调用JudgeClose函数进行判定此时是否还有人要进入,返回空
如果电梯状态目前为Opened
JudgeClose判定是否关门
调用JudgeOut判定是否有人要出门,如果有人出去,调用OUT;调用JudgeIn判定是否有 人要进入,如果有人进入,调用IN,然后返回空
如果电梯状态目前为Closing
调用Close并返回空
如果最远请求等于当前楼层并且电梯里外都无人
将电梯置为Waiting,并且进入NoPassenger输出电梯是空闲状态
如果最远请求等于当前楼层且电梯里外是有人的
此时将电梯置为Opening,并且进入Open
(8)MoveDown:输出电梯下楼每一t的状态
如果record(全局变量,用于输出电梯每一t的状态)小于枚举的值
record自加,输出“电梯正在下楼”并返回空
如果等于枚举的值时
电梯的楼层自减1,并且record置0
如果JudgeOpen为false则继续调用MoveDown显示下楼的状态
如果JudgeOpen为true则将电梯的状态置为Opening
(9)MoveUp:输出电梯上楼每一t的状态
如果record(全局变量,用于输出电梯每一t的状态)小于枚举的值
record自加,输出“电梯正在上楼”并返回空
如果等于枚举的值时
电梯的楼层自加1,并且record置0
如果JudgeOpen为false则继续调用MoveUp显示上楼的状态
如果JudgeOpen为true则将电梯的状态置为Opening
(10)Open:显示电梯开门状态每一t的状态
如果当前状态不为Opening
设置当前状态为Opening,把record置为0,然后返回空
如果record小于枚举的值
record自加,输出“电梯开门中”,返回空
如果是其他情况{
record置为0,输出“开门完成”,将当前状态置为Opened
如果JudgeOut为true就调用OUT
如果JudgeIn为true就调用IN
JudgeClose判断是否关门
}
(11)IN:显示哪些乘客进入电梯以及判定语句
如果电梯里人少于13人{
如果record小于枚举值{
如果当前状态为Opened{
record自加,遍历等待队列,并且加入判断乘客当前楼层必须是等于floor才能 进入电梯
}
如果当前状态为In{
record自加,输出“乘客正在进入电梯”,返回空
}
}
如果是等于枚举值{
record置为0,并且将当前状态置为Opened
}
}
如果电梯里的人数大于13{
输出“电梯内人数已经达到最大值”,将当前状态置为Closing
}
(12)JudgeClose:判断当前电梯是否可以关门
如果当前状态为Opened{
如果record小于枚举值{
record自加,输出“正在关门检测”,然后返回空
}
如果等于枚举值{
输出“关门检测结束”
如果当前状态为Opened{
record置为0,调用Close函数
}
否则 record置为0,并且返回空
}
}
其他情况返回空
(13)Close:显示电梯关门时每一t的状态
如果record小于枚举值{
record自加,设置当前状态为Closing,输出“电梯正在关门中”
}
其他情况{
record置为0,输出“电梯已经关门”,设置当前状态为Closed
如果最大请求为floor{
如果电梯里外有人{
遍历整个等待队列
如果此时等待队列有人发出请求
如果停止前电梯是向上走的
则判断是否在当前楼层之上或者就是当前楼层,如果满足就设置当前状态为Opening
如果停止前电梯是向下走的
则判断是否在当前楼层之下或者就是当前楼层,如果满足就设置当前状态为Opening
}
如果电梯里外都没人
设置当前状态为Waiting,把Dir置为-1
}
如果最大请求不是当前楼层{
保持停止前电梯的状态不变
}
}
调用NoPassenger
(14)OUT:记录乘客下电梯的每一t的状态
如果record小于枚举值{
如果当前状态为Opened{
record自加
如果电梯里有人要下电梯{
根据数组DiantiLi来判定下去多少个乘客并且输出下去时每一t状态,并且设置当前状态为Out,返回空
}
}
如果当前状态为Out{
record自加,输出“乘客正在下电梯”,返回空
}
其他情况则输出“需要下的乘客都已下去”,record置为0,并且把当前状态置为Opened
}
(15)JudgeIn:判断是否可以进乘客
如果All不为13{
如果等待队列不为空{
如果乘客是向上走的并且当前楼层在该层并且电梯之前的方向为向上
则允许进入,返回true
如果乘客是向下走的并且当前楼层在该层并且电梯之前的方向为向下
则允许进入,返回true
}
}
遍历完若没有返回true则此时返回false
(16)JudgeOut:判断乘客是否可以出去
如果电梯里有人{
数组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
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
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
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 }