电梯模拟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:存储乘客的相关信息,以便于在电梯模块中使用。
(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 //乘客类头文件,存放乘客的相关信息以及更改值的接口函数
#ifndef PASSENGER_H
#define PASSENGER_H
#include<iostream>
using namespace std; class passenger {
private:
int ID;
int nowfloor;
int gofloor;
int whenwait;
public:
passenger();
void setdata(int ID1);
void setnowfloor(int nowfloor1);
void setgofloor(int gofloor1);
void setwhenwait(int whenwait1);
int getnowfloor()const;
int getgofloor()const;
int getID()const;
int getwhenwait()const;
}; passenger::passenger() {
ID = ;
nowfloor = ;
gofloor = ;
whenwait = ;
} void passenger::setdata(int ID1) {
ID = ID1; int i = ;
while (i) {
cout << "请输入第" << ID << "位乘客的信息" << endl;
cout << "该乘客目前在哪一层:"; cin >> nowfloor;
cout << "该乘客去哪一层:"; cin >> gofloor;
cout << "该乘客何时上电梯:"; cin >> whenwait;
if (nowfloor > || nowfloor < ) {
cout << "乘客目前的楼层有误,请重输入!" << endl;
}
if (gofloor > || gofloor < ) {
cout << "乘客要去的楼层有误,请重输入!" << endl;
}
else i = ;
}
} void passenger::setnowfloor(int nowfloor1) {
nowfloor = nowfloor1;
} void passenger::setgofloor(int gofloor1) {
gofloor = gofloor1;
} void passenger::setwhenwait(int whenwait1) {
whenwait = whenwait1;
} int passenger::getnowfloor()const {
return nowfloor;
} int passenger::getgofloor()const {
return gofloor;
} int passenger::getID()const {
return ID;
} int passenger::getwhenwait()const {
return whenwait;
} #endif // !PASSENGER_H
#pragma once
passenger.h
elevator.h //电梯类头文件,存放枚举信息以及电梯的属性和相关判断函数
#ifndef ELEVATOR_H
#define ELEVATOR_H
#include"Node.h"
#include"passenger.h" enum state {
Opening,
Opened,
Closing,
Closed,
Waiting,
Up,
Down,
In,
Out,
Decelerate
}; int holdtime = ,record=,near=;
enum timeX
{
test = ,
open = ,
close = ,
in = ,
out = ,
quick = ,
up = ,
updecelerate = ,
down = ,
downdecelerate = ,
peoplewait = ,
wait =
}; class elevator {
private:
state State=Waiting;
int floor = ;
PNODE Wait=p_head;
int DiantiLi[] = {};
int All = ;
int Dir=-;//判断上下的情况
public:
state getnowState()const;
void setnowState(state t);
int getfloor()const;
void setfloor(int floor1);
int getAll()const;
void setAll(int num);//num为外部上电梯的人数
int getDir()const;
void setDir(int x);
void addpassenger(const passenger &x);//添加乘客
bool NoPassenger();//判断是否有乘客请求
void JudgeDirction();//判断电梯行走方向
bool JudgeOpen();//判断是否开门
void Open();//电梯门打开
bool JudgeOut();//判断乘客出去
void OUT();//乘客出去
bool JudgeIn();//判断乘客进入
void IN();//乘客进入
void Close();//关门
void MoveUp();//向上移动
void MoveDown();//向下移动
void JudgeClose();//40t时间来判断是否关门
void MoveDirction(const int floor1);//用来改变电梯的状态
void JudgeGiveUp(int waittime);//判断是否有人放弃,用在函数最开始
}; state elevator::getnowState()const {
return State;
}
void elevator::setnowState(state t) {
State = t;
}
int elevator::getfloor()const {
return floor;
}
void elevator::setfloor(int floor1) {
floor = floor1;
}
int elevator::getAll()const {
return All;
}
void elevator::setAll(int num) {
All += num;
}
int elevator::getDir()const {
return Dir;
}
void elevator::setDir(int num) {
Dir = num;
}
void elevator::addpassenger(const passenger &x) {
append(x);
cout << " 第" << x.getID() << "名乘客进入等待队列 " ;
}
bool elevator::NoPassenger() {
//用于判断电梯是否接收乘客的请求
if (getnowState() == Waiting) {
if (holdtime == &&floor!= ) {
//如果等够了300t并且不在1楼的话,开始下行
setnowState(Down);
setDir();
holdtime = ;
MoveDown();
return true;
}
else if (holdtime== && floor == ) {
//如果电梯本身在一楼则不需要进行操作
cout<< "电梯空闲无人,正在等待";
holdtime = ;
return true;
}
else if (All == && empty()==true) {
cout << "电梯空闲无人,正在等待";
holdtime++;
return true;
}
else {
JudgeDirction();
return false;
}
}
else {
JudgeDirction();
return false;
}
} void elevator::JudgeDirction() {
//使用该函数进行判断电梯的走向
near = floor;//初始化near的值,为防止不满足条件的情况出现时依旧可以使用MoveDirction函数
int upoutfar = , downoutfar = ;//定义2个记录上下出去最远请求的变量
int upinfar = , downinfar = ;//定义2个记录上下进来最远请求的变量
if (State == Closed) {
if (getAll() == && empty()==true) {
setnowState(Waiting);
return;
}
if (floor == ) {
setnowState(Up); setDir();
}
if (floor == ) {
setnowState(Down); setDir();
}
if (getAll() != ) {//电梯里依旧有人
//此时需要区分电梯的运行方向,分两种情况来处理(目前还未处理)
for (int i = ; i < ; i++) {
if (DiantiLi[i] != ) {
near = i;
if (i > floor) {
upinfar = i;
setnowState(Up);
setDir();
break;
}
else if (i < floor) {
downinfar = i;
setnowState(Down);
setDir();
break;
}
}
}
}
if (empty() == false) {//电梯外等待的人不为空
PNODE ptemp=p_head->next;
while (ptemp!=NULL) {
if (getDir() == ) {//只接上行乘客
if (ptemp->data.getnowfloor() > floor) {//乘客所处楼层在电梯楼层上,这样才有可能电梯前往接人
//开始检索在链表中的乘客,并且进行判断是否有要上行的
if (ptemp->data.getgofloor() > ptemp->data.getnowfloor()) {
//代表此人是上行,并且是在电梯运行方向的楼上,需要前往接人
if (ptemp->data.getgofloor() > upoutfar)upoutfar = ptemp->data.getgofloor();
}
if (ptemp->data.getgofloor() < ptemp->data.getnowfloor()) {
if (ptemp->data.getnowfloor() > upoutfar)upoutfar = ptemp->data.getnowfloor();
}
}
if (upinfar == && upoutfar == ) { setnowState(Down); setDir(); }
if (upinfar <= upoutfar)near = upoutfar;
else near = upinfar;
} else if (getDir() == ) {//只接下行乘客
if (ptemp->data.getnowfloor() < floor) {//乘客所处楼层在电梯楼层下,这样才有可能电梯前往接人
//开始检索在链表中的乘客,并且进行判断是否有要下行的
if (ptemp->data.getgofloor() < ptemp->data.getnowfloor()) {
//代表此人是下行,并且是在电梯运行方向的楼下,需要前往接人
if (ptemp->data.getgofloor() < downoutfar)downoutfar = ptemp->data.getgofloor();
}
if (ptemp->data.getgofloor() > ptemp->data.getnowfloor()) {
if (ptemp->data.getnowfloor() < downoutfar)downoutfar = ptemp->data.getnowfloor();
}
}
if (downinfar == && downoutfar == ) { setnowState(Up); setDir(); }
if (downinfar <= downoutfar)near = downinfar;
else near = downoutfar;
}
ptemp = ptemp->next;
}
} }
if (State == Waiting) {
PNODE ptemp = p_head->next;
int time_now = ;
while (ptemp!=NULL) {
int Time_now = ptemp->data.getwhenwait();//用于记录最先按的人
time_now = Time_now;
if(ptemp->data.getwhenwait()<time_now){//挑选出最先按键的人,然后进行改变电梯的方向
time_now = ptemp->data.getwhenwait();
}
ptemp = ptemp->next;
}
ptemp = p_head->next;
while (ptemp != NULL) {
int up(floor), down(floor);
if (ptemp->data.getwhenwait() == time_now) {
int x = ptemp->data.getgofloor() - ptemp->data.getnowfloor();
//此时会出现4种情况,并且只会有2种是电梯上行,2种是电梯下行
if ((x > && (ptemp->data.getnowfloor()>floor))||(x<&& (ptemp->data.getnowfloor()>floor))) {
setnowState(Up);
setDir();
upinfar = ptemp->data.getnowfloor();
if (up < upinfar) {
up = upinfar;
}
}
else if ((x > && (ptemp->data.getnowfloor()<floor)) || (x< && (ptemp->data.getnowfloor()<floor))) {
setnowState(Down);
setDir();
downinfar = ptemp->data.getnowfloor();
if (down > downinfar) {
down = downinfar;
}
}
if (down != floor&&up != floor) {//当上下同时有人请求时,满足先上的原则
setnowState(Up); near = upinfar; setDir();
}
else if (up != floor) {//只有上行的请求
setnowState(Up); near = upinfar; setDir();
}
else if (down != floor) {//只有下行的请求
setnowState(Down); near = downinfar; setDir();
}
if (floor == ) { setnowState(Up); setDir(); }
}
ptemp = ptemp->next;
}
if (near == floor) Open();
}
if (State == Up) {
if (getAll()!=) {//电梯里有人
for (int i = ; i < ; i++) {
if (DiantiLi[i] != ) {
if (i >= near) {
upinfar = i;
}
}
}
}
if (empty() == false) {
PNODE ptemp = p_head->next;
while (ptemp != NULL) {
if (ptemp->data.getnowfloor() >= near) {
if (ptemp->data.getgofloor() >= upoutfar) {
upoutfar = ptemp->data.getgofloor();
}
if (ptemp->data.getnowfloor() >= upoutfar) {
upoutfar = ptemp->data.getnowfloor();
}
}
ptemp = ptemp->next;
}
}
if (upinfar >= upoutfar)near = upinfar;
else near = upoutfar;
}
if (State == Down) {
//downinfar = 10, downoutfar = 10;
if (getAll() != ) {//电梯里有人
for (int i = ; i < ; i++) {
if (DiantiLi[i] != ) {
if (i <= near) {
downinfar = i;
break;
}
}
}
}
if (empty() == false) {
PNODE ptemp = p_head->next;
while (ptemp != NULL) {
if (ptemp->data.getnowfloor() <= near) {
if (ptemp->data.getnowfloor() <= downoutfar) {
downoutfar = ptemp->data.getnowfloor();
}
if (ptemp->data.getgofloor() <= downoutfar) {
downoutfar = ptemp->data.getgofloor();
}
}
ptemp = ptemp->next;
}
}
if (getAll() == && empty() == true)near = ;
else if (downinfar >= downoutfar)near = downoutfar;
else near = downinfar;
}
MoveDirction(near);
} bool elevator::JudgeOpen() {//判断此楼层是否有人需要进出
if (JudgeIn() || JudgeOut()) {
Open();
return true;
}
else return false;
} void elevator::Open() {
if (getnowState() != Opening) {
setnowState(Opening);
record = ;
return ;
}
if (record < open) {
record++;
cout << "电梯开门中";
return;
}
else {//开门完成后
record = ;
cout << "开门完成";
setnowState(Opened);
if (JudgeOut())OUT();
if (JudgeIn())IN();
JudgeClose();
}
} bool elevator::JudgeOut() {
if (getAll() != ) {
int j = floor;
if (DiantiLi[j] != )return true;
}
return false;
} void elevator::OUT() {
if (record < out) {
if (getnowState() == Opened) {
record++;
cout << "乘客正在下电梯";
if (DiantiLi[floor] != ) {
cout << "在该层一共下去" << DiantiLi[floor] << "个人";
setAll(-DiantiLi[floor]);
DiantiLi[floor] = ;
}
setnowState(Out);
return;
}
if (getnowState() == Out) {
record++;
cout<< "乘客正在下电梯";
return;
}
}
else {
cout << "电梯里需要下的乘客都已下去";
record = ;
setnowState(Opened);
}
} bool elevator::JudgeIn() {//如果电梯未满,则返回true,可以继续进人
//目前需要完善,因为是先把人删除输入进数组,所以需要进行有个判断
if (getAll() != ) {
if (!empty()) {//不为空则执行if语句
PNODE ptemp = p_head->next; int upnum1=,downnum1=;
while (ptemp != NULL) {
if (ptemp->data.getnowfloor() == floor) {
if ((ptemp->data.getnowfloor() < ptemp->data.getgofloor()) && (getDir() > )) {
//乘客是往上走的
return true;
}
if ((ptemp->data.getnowfloor() > ptemp->data.getgofloor()) && (getDir() == )) {
//乘客下行
return true;
}
if (near == ptemp->data.getnowfloor()) {
//达到了最大请求楼层,如果是与电梯方向同向,则不改变方向,并且允许进入
//如果不与电梯同向,则改变方向,如果两个情况都有,就优先满足同方向的
if (getDir() == ) {
if (ptemp->data.getnowfloor() < ptemp->data.getgofloor()) {
setDir(); upnum1++;
}
if (ptemp->data.getnowfloor() > ptemp->data.getgofloor()) {
setDir(); downnum1++;
}
if (upnum1 != && downnum1 != )setDir();
}
else if (getDir()==) {
if (ptemp->data.getnowfloor() < ptemp->data.getgofloor()) {
setDir(); upnum1++;
}
if (ptemp->data.getnowfloor() > ptemp->data.getgofloor()) {
setDir(); downnum1++;
}
if (upnum1 != && downnum1 != )setDir();
}
return true;
}
}
ptemp = ptemp->next;
}
}
}
return false;
} void elevator::IN() {
if (getAll() < ) {
if (record < in)
{
if (getnowState() == Opened) {
record++;
PNODE ptemp = p_head->next;
while (ptemp != NULL) {
if(ptemp->data.getnowfloor()==floor){//首先人得在电梯楼层,这才能进行判定
if ((ptemp->data.getnowfloor() < ptemp->data.getgofloor()) && (getDir() > )) {
//乘客是往上走的
cout << "第" << ptemp->data.getID() << "个乘客正在进入电梯";
DiantiLi[ptemp->data.getgofloor()] += ;
setAll();
Remove(ptemp->data.getID());
setnowState(In);
return;
}
if ((ptemp->data.getnowfloor() > ptemp->data.getgofloor()) && (getDir() == )) {
//乘客下行
cout << "第" << ptemp->data.getID() << "个乘客正在进入电梯";
DiantiLi[ptemp->data.getgofloor()] += ;
setAll();
Remove(ptemp->data.getID());
setnowState(In);
return;
}
}
ptemp = ptemp->next;
}
}
if (getnowState() == In) {
record++;
cout << "乘客正在进入电梯";
return;
}
}
else {
cout << "乘客已经进入电梯";
record = ;
setnowState(Opened);
}
}
else {
cout << "电梯内人数已经达到最大值";
setnowState(Closing);
}
} void elevator::Close() {
if (record < close) {
record++;
setnowState(Closing);
cout << "电梯正在关门中";
}
else {
record = ;
cout << "电梯已经关门";
setnowState(Closed);
if (near == floor) {//电梯已经到达最大请求楼层,可能会出现4种情况
if (empty() == false||getAll()!=) {//等待队列有人或电梯里也有人
PNODE ptemp = p_head->next; int OutPeople = ;
while (ptemp != NULL) {
if (ptemp->data.getnowfloor() == floor)OutPeople += ;
if (getAll() != && OutPeople!=) {//电梯里有人,外面有人 判断去的方向
if (getDir() == && (ptemp->data.getgofloor() > floor)) {//电梯上行,乘客上行,开门
setnowState(Opening);
}
else if (getDir() == && (ptemp->data.getgofloor() < floor)) {//电梯下行,乘客下行,开门
setnowState(Opening);
}
}
if (getAll() == && OutPeople != ) {//电梯没人,外面有人
if (getDir() == ) {//电梯上行
if (ptemp->data.getgofloor() > floor)
setnowState(Opening);
else if (ptemp->data.getgofloor() < floor) {
setDir(); setnowState(Opening);
}
}
if (getDir() == ) {//电梯下行
if (ptemp->data.getgofloor() < floor)
setnowState(Opening);
else if (ptemp->data.getgofloor() > floor) {
setDir(); setnowState(Opening);
}
}
}
if (getAll() != && OutPeople==) {
//电梯里有人,外面没人,此时应该分是否继续送乘客上行或者下行,首先遍历数组得到乘客要去几层
for (int i = ; i < ; i++) {
if (DiantiLi[i] != ) {
if (i < floor) { setnowState(Down); setDir(); }
if (i > floor) { setnowState(Up); setDir(); }
}
} }
ptemp = ptemp->next;
}
}
else if(empty() == true && getAll() == ){//等待队列没人,电梯也没人
setnowState(Waiting); setDir(-);
}
}
else if (near != floor) {
if (getDir() == ) {
setDir(); setnowState(Up);
}
if (getDir() == ) {
setDir(); setnowState(Down);
}
}
NoPassenger();
}
} void elevator::MoveUp() {
if (record<up) {
record++;
cout << "电梯正在上楼";
return;
}
else {
floor++;
record = ;
if (JudgeOpen() == false)
MoveUp();
else {
cout << "电梯正在上楼";
setnowState(Opening);
}
} } void elevator::MoveDown() {
if (record<down) {
record++;
cout << "电梯正在下楼";
return;
}
else {
floor--;
record = ;
if (JudgeOpen() == false)MoveDown();
else {
cout << "电梯正在下楼";
setnowState(Opening);
}
}
} void elevator::JudgeClose() {
if (getnowState() == Opened){
if (record < test) {
record++;
cout << "正在关门检测";
return;
}
else {
cout << "关门检测结束";
if (getnowState() == Opened) {
record = ;
Close();
return;
}
else {//疑似可以删除
record = ;
return;
}
}
}
else return;
} void elevator::MoveDirction(const int near) {
//near为乘客的请求最远的楼层
if (near<floor) {
setnowState(Down);
setDir();
MoveDown();
return;
}
if (near>floor) {
setnowState(Up);
setDir();
MoveUp();
return;
}
if (getnowState()==Opening) {
Open();
return;
}
if (getnowState() == In) {
IN();
JudgeClose();
return;
}
if (getnowState() == Out) {
OUT();
JudgeClose();
return;
}
if (getnowState()== Opened) {
JudgeClose();
if (JudgeOut())OUT();
if (JudgeIn())IN();
return;
}
if (getnowState() == Closing) {
Close();
return;
}
if (near == floor&&empty()==true&&getAll()==) {
setnowState(Waiting);
NoPassenger();
return;
}
if (near == floor) {
setnowState(Opening);
Open();
return;
}
} void elevator::JudgeGiveUp(int waittime) {
//一进入系统则先判断该时刻是否有人放弃
//waittime为现在的时间,用于和乘客等待的时间+wait来进行判断乘客是否放弃
PNODE ptemp=p_head->next;
while (ptemp != NULL) {
if ((ptemp->data.getwhenwait() + peoplewait) <= waittime) {
cout << "第" << ptemp->data.getID() << "名乘客已放弃等待 ";
Remove(ptemp->data.getID());
}
ptemp = ptemp->next;
}
NoPassenger();
} #endif // ELEVATOR_H
#pragma once
elevator.h
Node.h //节点类头文件,用于创建链表以及链表相关的操作函数
#ifndef NODE_H
#define NODE_H
#include<iostream>
#include"passenger.h"
using namespace std; typedef struct node {
passenger data;
struct node* next;
}NODE, *PNODE; NODE head;//头节点 PNODE p_head = &head;//头指针
PNODE p_tail = &head;//尾指针 void append(passenger data) {
PNODE pnew = (PNODE)malloc(sizeof(NODE));
pnew->data = data; pnew->next = NULL;
if (p_head == NULL) {
p_head = pnew;
p_tail = pnew;
}
else {
p_tail->next = pnew;
p_tail = pnew;
}
} bool empty() {
if (p_head->next == NULL)return true;
else return false;
} void Remove(int ID) {//data为节点所存储的数据,查到就删除
int pnew = ID;
PNODE ptemp = p_head->next;
if (ptemp->data.getID() == pnew) {
if (ptemp == p_tail) {//如果就一个节点
p_head->next = ptemp->next;
p_tail = p_head;
ptemp = NULL;
}
else { //如果是多个节点
p_head->next = ptemp->next;
ptemp = NULL;
}
}
while (ptemp !=NULL) {
if (ptemp->next->data.getID() == pnew) {
if (ptemp->next == p_tail) {
ptemp->next = NULL;
p_tail = ptemp;
}
else ptemp->next = ptemp->next->next;
}
ptemp = ptemp->next;
}
} #endif // !NODE_H
#pragma once
Node.h
main.cpp //主函数,主要调用乘客类的设置属性函数,电梯类的JudgeGiveUp函数,以及电梯类的addpassenger函数,并且显示现在是多少t
#include"elevator.h" int main() {
long int time = ;
int a = ,j=;
cout << "请输入共有几位乘客使用电梯:";
cin >> a;
passenger *people = new passenger[a+];
for (int i = ; i < a+; i++) {
people[i].setdata(i);
cout << endl;
}
elevator x;
long int Time = ;
for (int b = ; b < a + ; b++) {
if (people[b].getwhenwait() > Time)Time = people[b].getwhenwait();
}
Time = a*;//此处的设置并不是最优解,目前还没有找到一个比较合适的值代替
for (; time < Time; time++) {
cout << time << "t时刻 ";
for (int i = ; i < a + ; i++) {
if (people[i].getwhenwait() == time)x.addpassenger(people[i]);
}
cout << "电梯在" << x.getfloor() << "层 ";
x.JudgeGiveUp(time);
cout << endl;
}
delete[]people;
return ;
}
main.cpp
电梯模拟C++的更多相关文章
- OO_BLOG2_多线程电梯模拟
作业2-1 单部多线程傻瓜调度(FAFS)电梯的模拟 I. 基于度量的程序结构分析 1)程序结构与基本度量统计图 2)分析 这次作业基本奠定了本人三次电梯作业的基本架构,简述如下: Elevato ...
- 2019年北航OO第2单元(电梯模拟)总结
1 三次作业的设计策略 经过了上一单元的训练,我也积累了一些设计策略上的经验.在这一单元的一开始,我便尽可能地把问题中的各个功能实体区分开来,分别封装成类,以便于随后作业中新需求的加入.与此同时,我也 ...
- 2019OO第二单元作业总结
OO第二单元的作业主题是模拟电梯. ---------------------------------------------------------------------------------- ...
- OO学习体会与阶段总结(多线程程序)
前言 在最近一个月的面向对象编程学习中,我们进入了编写多线程程序的阶段.线程的创建.调度和信息传递,共享对象的处理,线程安全类的编写,各种有关于线程的操作在一定程度上增加了近三次作业的复杂度与难度,带 ...
- WPF界面设计技巧(7)—模拟电梯升降的缓动动画
原文:WPF界面设计技巧(7)-模拟电梯升降的缓动动画 如同Flash一样,WPF的亮点之一也在于其擅于表现平滑的动画效果,但以移动动画来说,仅凭简单的起始位置.目标位置,所产生的动画仍会非常生硬,这 ...
- OO_JAVA_电梯运行模拟_单元总结
电梯运行模拟--三次作业总结 目录 电梯运行模拟--三次作业总结 总体遵循的设计思路 逻辑解耦 电梯与调度器解耦 楼层信息的存储和变更与电梯.调度器解耦 调度器运行流程解耦 第一次电梯,蠢笨串行先到先 ...
- 自己动手C#模拟电梯的运行V1.0
电梯调度有很多种模式,参见http://www.cnblogs.com/jianyungsun/archive/2011/03/16/1986439.html 1.1先来先服务算法(FCFS) 先来先 ...
- Servlet+AJAX实现的模拟电梯调度
需求产生: 大三下学期天天在学校的同一栋教学楼上课,每天要等四次电梯,有次等电梯无聊了,就想到电梯的运行逻辑该如何用程序来表达呢? 问题描述: 大学的那栋楼有21层,不过在页面中画21层有点密,所以只 ...
- T2483 电梯(模拟题)
https://www.luogu.org/problem/show?pid=T2483 题目背景 开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道. ...
随机推荐
- 删除项目中的.pyc文件
在编写python项目的时候,往往会生成很多的.pyc文件,但是在我们提交代码的时候这些.pyc文件又是不必要的,所以需要对项目里面的.pyc文件进行清理.再此,经过我的查阅资料和尝试,分享出以下方法 ...
- win10环境下利用pyinstaller把python代码(.py)打包成可执行文件(.exe)
前言 最近写了一个小小的检测程序,python写起来只需要短短一百行,可是打包起来就没有C那么容易了.下面记录一下我艰难的"打包"过程. 方法一:py2exe py2exe是一种经 ...
- Java中动态代理工作流程
当谈到动态代理就会想到接口,因为接口是一种规范,动态代理对象通过接口便会很清楚地知道他的实现类(被代理对象)是何种类型的(即有哪些方法).Now,然我们来开始编写一个例子来了解动态代理的全过程: 第一 ...
- 本地mysql无法连接原来是这里有问题啊。。。。。。
1.怎么解决localhost无法链接本地mysql数据库问题_百度经验http://jingyan.baidu.com/article/d45ad14896d1cd69542b805c.html 2 ...
- elasticsearch基本操作之--java基本操作 api
/** * 系统环境: vm12 下的centos 7.2 * 当前安装版本: elasticsearch-2.4.0.tar.gz */ 默认进行了elasticsearch安装和ik安装, 超时配 ...
- Mycat 分片规则详解--固定 hash 分片
实现方式:该算法类似于十进制的求模运算,但是为二进制的操作,例如,取 id 的二进制低 10 位 与 1111111111 进行 & 运算 优点:这种策略比较灵活,可以均匀分配也可以非均匀分配 ...
- extract-text-webpack-plugin---webpack插件
var ExtractTextPlugin=require('extract-text-webpack-plugin');//build使用 { test:/\.css$/, use:ExtractT ...
- POJ-1032-拆数字
Description New convocation of The Fool Land's Parliament consists of N delegates. According to the ...
- zabbix自定义key监控memcache状态及其他服务进程
一.在客户端 1.到/usr/loca/zabbix/conf/zabbix_agentd.conf里添加 UserParameter=memcached_stats[*],(echo ...
- Algorithm --> 二进制中1的个数
行文脉络 解法一——除法 解法二——移位 解法三——高效移位 解法四——查表 扩展问题——异或后转化为该问题 对于一个字节(8bit)的变量,求其二进制“1”的个数.例如6(二进制0000 0110) ...