C语言电梯模拟程序

C语言电梯模拟程序

一直以来我对电梯很感兴趣,起初认为用C语言不可能实现电梯模拟,需要多线程的支持,因此一直以来也没有想着做。最近数据结构习题书的这道题引起了我的注意,通过几天的努力终于实现了,先将程序的实现与大家分享出来。

在这个程序关键是处理好电梯运行状态转换与乘客进出的同步进行。好在题目要求每次输入时要输入下一个乘客到来的时间,使得程序变简单了。通过一个模拟时钟,根据模拟时钟判断该运行哪个函数。以下是模拟时钟的代码。

void DoTime(){
	//此函数用于模拟时钟 
	while(1){
		if(Time>MaxTime)
			return;
		TestPeople();//两个始终都会被调用的函数 
		Controler(); 
		struct Activity* p=activity.next;
		if(p==NULL){
			Time=MaxTime;
		}
		if(p&&Time>=p->time){//取出活动队头的,检测定时是否到了 
			activity.next=p->next;
			p->fn();
			free(p);
		}
		Time++;
	}
}
在这个先不管TestPeople()、Controler()是什么,其中activity是关键,它是一个链表在链表的头部是计时器时间最小的函数,根据模拟时钟判断是否调用这个函数以及删除这个节点。以下是Activity的具体定义。

typedef struct Activity{
	int time;
	void(*fn)(void);
	struct Activity* next;
}Activity;
以及全局变量activity

Activity activity={0,NULL,NULL};
下面的代码用于将一个函数加入activity链表,这是根据时钟值从小到大插入activity的。

void AddAct(int time,void(*fn)(void)){//将一个活动加入定时器,时间到了会调用这个函数 
	time=Time+time;					//这个函数参数必须是void,返回值也必须是void
	struct Activity* act;
	act=(struct Activity*)malloc(sizeof(struct Activity));
	act->next=NULL;
	act->fn=fn;
	act->time=time;
	struct Activity* p=&activity;
	while(p->next!=NULL){
		if(p->next->time>time)
			break;
		p=p->next;
	}
	act->next=p->next;
	p->next=act;
}
一个简单的活动加入计时器。

void Input(void){//输入人员信息,这个需要手动调用一次,之后就根据定时器调用了 
	Person* p = (Person*)malloc(sizeof(Person));
	int infloor,outfloor,giveuptime,intertime;
	while(1){
		printf("请输入用户的起始楼层:");
		scanf("%d",&infloor);
		printf("请输入用户的目标的楼层:");
		scanf("%d",&outfloor);
		printf("请输入用户的最长容忍时间:");
		scanf("%d",&giveuptime);
		printf("请输入下一个用户的到来时间:");
		scanf("%d",&intertime);
		if(!(infloor<0||infloor>MaxFloor-1||outfloor<0||outfloor>MaxFloor-1)&&(infloor!=outfloor))
			break;
		printf("错误的用户信息录入!\n");
	}
	p->Id=PersonId++;
	p->GiveupTime=giveuptime+Time;
	p->next=NULL;
	p->OutFloor=outfloor;
	if(outfloor>infloor)
		CallUp[infloor]=1;
	else
		CallDown[infloor]=1;
	AddQueue(infloor,p);
	AddAct(intertime,Input);
}
这使得main函数可以写的很简单。

int main(){
	Init();
	Input();
	DoTime();
	return 0;
}
这样整个电梯程序大体就搭建起来了。下面看Controler()这个函数,它就是判断电梯的运行状态,然后决定电梯的下一个运行状态。AddAct()很重要,这很好的实现了一个需要时间的过程,如电梯的开门,上升,减速。

void Controler(void){
	if(State==Idle||State==Stop){ 
		if(CallUp[Floor]||CallDown[Floor]||CallCar[Floor]){
			//当前层有请求,需要开门进出
			if(CallCar[BaseFloor]==2){
				CallCar[BaseFloor]=0;
				State=Idle;
				printf("现在在%d层,无人请求电梯!\n",BaseFloor);
				return;
			}
			State=DoorOpening;
			AddAct(DoorTime,doopendoor);
		}
		else{
			//当前层无请求,判断其他层请求
			int whitch=GetWhere();
			if(whitch==GoingUp){
				State=SpeedUp;
				AddAct(Accelerate,domove);
			}else if(whitch==GoingDown){
				State=SpeedDown;
				AddAct(Accelerate,domove);
			}else{
				State=Idle;
				if(Floor!=BaseFloor)
					AddAct(OverTime,tofirst);
			}
		}
	}
	//否则电梯忙碌 
	return;
}
下面是一些用到宏定义以及全局变量。

#define GoingUp 1//匀速上升
#define GoingDown 2//匀速下降
#define SpeedUp 3//加速上升
#define SpeedDown 4//加速下降
#define SlowUp 5//减速上升准备停靠
#define SlowDown 6//减速下降准备停靠
#define Idle 7//空闲
#define Stop 8//停止且已关门
#define DoorOpen 9//停止且门已打开
#define DoorOpening 10
#define DoorCloseing 11

#define	CloseTest 40	//电梯关门测试时间
#define OverTime  300	//电梯停候超时时间
#define Accelerate 15	//加速时间
#define UpTime	51	//上升时间
#define DownTime 61	//下降时间
#define UpDecelerate 14	//上升减速
#define DownDecelerate 23	//下降减速
#define DoorTime	20	//开门关门时间
#define InOutTime	25	//进出电梯时间

#define MaxTime 10000
#define MaxFloor 5
#define BaseFloor 1

//初始每层电梯等待队列和栈 
#define Init() ({int i;\
	for(i=0;i<MaxFloor;i++){\
		Stack[i].next=NULL;\
		Queue[i].next=NULL;\
	}\
	activity.next=NULL;\
})
typedef struct Person{
	int Id;
	int OutFloor;
	int GiveupTime;
	struct Person* next;
}Person;

typedef struct Activity{
	int time;
	void(*fn)(void);
	struct Activity* next;
}Activity;

typedef struct Person_Ele{
	int Id;
	struct Person_Ele* next;
}Person_Ele;
int Time=0;
int CallUp[MaxFloor]={0,};
int CallDown[MaxFloor]={0,};
int CallCar[MaxFloor]={0,};
int Floor=BaseFloor;
int State=Idle;
int PersonId=0;
Activity activity={0,NULL,NULL};
Person_Ele Stack[5]={0,};
Person Queue[5]={0,};
下面是Controler()具体调用细节。

void testinout(void){//检测有无人进出 
	if(Queue[Floor].next||Stack[Floor].next)
		AddAct(CloseTest,testinout);
	else{
		State=DoorCloseing;
		CallUp[Floor]=0;
		CallDown[Floor]=0;
		CallCar[Floor]=0;
		AddAct(DoorTime,doclosedoor);
	}
}

void doclosedoor(void){//电梯门关了 
	printf("电梯门关了\n");
	State=Stop;
}

void doopendoor(void){//打开电梯门 
	printf("电梯门开了\n");
	State=DoorOpen;//门打开了 
	AddAct(CloseTest,testinout);
	if(Stack[Floor].next)
		AddAct(InOutTime,doout);
	else{//没人出,就看有没有进的 
		if(Queue[Floor].next)
			AddAct(InOutTime,doin);
	}
}

void doout(void){
	//根据栈出人,如果没有看是否有人进 
	if(Stack[Floor].next){
		Person_Ele* p=Stack[Floor].next;
		Stack[Floor].next=p->next;
		;//显示信息 
		printf("用户%d走出电梯\n",p->Id);
		free(p);
	}
	if(Stack[Floor].next){
		AddAct(InOutTime,doout);
	}else{
		if(Queue[Floor].next)
			AddAct(InOutTime,doin);
	}
}

void doin(void){//人进入电梯,这里不用关电梯门它会定时关的 
	Person* p=Queue[Floor].next;
	if(p){
		Queue[Floor].next=p->next;
		Person_Ele* pe=(Person_Ele*)malloc(sizeof(Person_Ele));
		int in=p->OutFloor;
		CallCar[in]=1;//置位请求 
		pe->next=Stack[in].next;
		pe->Id=p->Id;
		Stack[in].next=pe;
		printf("用户%d走入电梯\n",p->Id);
		free(p);
	}
	if(Queue[Floor].next){
		AddAct(InOutTime,doin);
	}
}

int GetWhere(void){
	static int old=0;//保存上一次电梯的方向,保证电梯尽可能在一个方向走 
	int isup=0,isdown=0;
	int i;
	for(i=Floor+1;i<MaxFloor;i++){
		if(CallDown[i]||CallUp[i]||CallCar[i])
			isup=1;
	}
	for(i=Floor-1;i>=0;i--){
		if(CallDown[i]||CallUp[i]||CallCar[i])
			isdown=1;
	}
	if(isup==0&&isdown==0){
		return 0;
	}
	if(old==0){
		if(isdown) old=GoingDown;
		if(isup) old=GoingUp;
		return old;
	}
	if(old==GoingUp&&isup)
		return old;
	else if(old==GoingDown&&isdown)
		return old;
	else if(isdown) 
		old=GoingDown;
	else if(isup) 
		old=GoingUp;
	else
		printf("在选择方向时发生错误!\n");
	return old;
}

void tofirst(void){//去第一层
	if(State!=Idle||Floor==BaseFloor)
		return;
	printf("长时间没人请求电梯!将进入%d层\n",BaseFloor);
	CallCar[BaseFloor]=2;//给电梯一个虚拟的去1层的请求,这并不会开门 
}

void doslow(void){//电梯停了 
	printf("电梯停了,当前层是%d\n",Floor);
	State=Stop;
}

void doup(void){ 
	Floor++;
	printf("电梯正在上升!现已到了%d层!\n",Floor);
	if(CallDown[Floor]||CallUp[Floor]||CallCar[Floor]){
		State=SlowUp;
		AddAct(UpDecelerate,doslow);
	}else{
		if(Floor==MaxFloor-1){
			State=SlowUp;
			AddAct(UpDecelerate,doslow);
		}else{
			AddAct(UpTime,doup);
		}
	}
}

void dodown(void){
	Floor--;
	printf("电梯正在下降!现已到了%d层!\n",Floor);
	if(CallUp[Floor]||CallDown[Floor]||CallCar[Floor]){
		State=SlowDown;
		AddAct(DownDecelerate,doslow);
	}else{
		if(Floor==0){
			State=SlowDown;
			AddAct(DownDecelerate,doslow);
		}else{
			AddAct(DownTime,dodown);
		}
	}
}

void domove(void){//加速完成,将进入正常速度 
	if(State==SpeedUp){
		printf("电梯已加速上升!\n");
		State=GoingUp;
		AddAct(UpTime,doup);
	}else{
		printf("电梯已加速下降!\n");
		State=GoingDown;
		AddAct(DownTime,dodown);
	}
}
他们之间尽管没有直接调用关系,但都是通过AddAct()联系起来的。下面是TestPeople()的实现,我知道DoTime()每次都调用它严重影响效率,但是这需要修改AddAct(),增加复杂性。

void TestPeople(){//这是检测每层队列是否有人放弃,有人放弃就将他踢出队列 
	int i;//这个函数每个时间都会被调用,效率相对较低 
	for(i=0;i<MaxFloor;i++){
		Person* p=Queue[i].next;
		Person* q=&Queue[i];
		if(p==NULL)
			continue;
		while(p!=NULL){
			if(p->GiveupTime<=Time){
				if(Floor=i&&(State>=Idle))
					break;
				q->next=p->next;
				printf("用户%d放弃了等待!\n",p->Id);
				free(p);
				p=q->next;
				continue;
			}
			q=p;
			p=p->next;
		}
	}
}
下面是所有的源代码:

Dianti.h

#ifndef _DIANTI_H_
#define _DIANTI_H_
#include <stdio.h>
#include <stdlib.h>

#define GoingUp 1//匀速上升
#define GoingDown 2//匀速下降
#define SpeedUp 3//加速上升
#define SpeedDown 4//加速下降
#define SlowUp 5//减速上升准备停靠
#define SlowDown 6//减速下降准备停靠
#define Idle 7//空闲
#define Stop 8//停止且已关门
#define DoorOpen 9//停止且门已打开
#define DoorOpening 10
#define DoorCloseing 11

#define	CloseTest 40	//电梯关门测试时间
#define OverTime  300	//电梯停候超时时间
#define Accelerate 15	//加速时间
#define UpTime	51	//上升时间
#define DownTime 61	//下降时间
#define UpDecelerate 14	//上升减速
#define DownDecelerate 23	//下降减速
#define DoorTime	20	//开门关门时间
#define InOutTime	25	//进出电梯时间

#define MaxTime 10000
#define MaxFloor 5
#define BaseFloor 1

//初始每层电梯等待队列和栈 
#define Init() ({int i;\
	for(i=0;i<MaxFloor;i++){\
		Stack[i].next=NULL;\
		Queue[i].next=NULL;\
	}\
	activity.next=NULL;\
})
typedef struct Person{
	int Id;
	int OutFloor;
	int GiveupTime;
	struct Person* next;
}Person;

typedef struct Activity{
	int time;
	void(*fn)(void);
	struct Activity* next;
}Activity;

typedef struct Person_Ele{
	int Id;
	struct Person_Ele* next;
}Person_Ele;

int AddQueue(int floor,struct Person* p); 
void AddAct(int time,void(*fn)(void));
void TestPeople();
void DoTime();
void Input(void);
//以下函数与电梯决策有关 
void testinout(void);
void doclosedoor(void);
void doopendoor(void);
void doout(void);
void doin(void);
void doup(void);
void dodown(void);
void domove(void);
void doslow(void);
void tofirst();
int GetWhere(void);
#endif
Dianti.c

#include "Dianti.h"

int Time=0;
int CallUp[MaxFloor]={0,};
int CallDown[MaxFloor]={0,};
int CallCar[MaxFloor]={0,};
int Floor=BaseFloor;
int State=Idle;
int PersonId=0;
Activity activity={0,NULL,NULL};
Person_Ele Stack[5]={0,};
Person Queue[5]={0,};

int main(){
	Init();
	Input();
	DoTime();
	return 0;
}

int AddQueue(int floor,Person* p){//加入相应层的客户等待队列 
	Person* tmp=&Queue[floor];//这始终加在链表的最后一位, 
	while(tmp->next!=NULL){
		tmp=tmp->next;
	}
	tmp->next=p;
	return 0;
}

void AddAct(int time,void(*fn)(void)){//将一个活动加入定时器,时间到了会调用这个函数 
	time=Time+time;					//这个函数参数必须是void,返回值也必须是void
	struct Activity* act;
	act=(struct Activity*)malloc(sizeof(struct Activity));
	act->next=NULL;
	act->fn=fn;
	act->time=time;
	struct Activity* p=&activity;
	while(p->next!=NULL){
		if(p->next->time>time)
			break;
		p=p->next;
	}
	act->next=p->next;
	p->next=act;
}

void TestPeople(){//这是检测每层队列是否有人放弃,有人放弃就将他踢出队列 
	int i;//这个函数每个时间都会被调用,效率相对较低 
	for(i=0;i<MaxFloor;i++){
		Person* p=Queue[i].next;
		Person* q=&Queue[i];
		if(p==NULL)
			continue;
		while(p!=NULL){
			if(p->GiveupTime<=Time){
				if(Floor=i&&(State>=Idle))
					break;
				q->next=p->next;
				printf("用户%d放弃了等待!\n",p->Id);
				free(p);
				p=q->next;
				continue;
			}
			q=p;
			p=p->next;
		}
	}
}



void Input(void){//输入人员信息,这个需要手动调用一次,之后就根据定时器调用了 
	Person* p = (Person*)malloc(sizeof(Person));
	int infloor,outfloor,giveuptime,intertime;
	while(1){
		printf("请输入用户的起始楼层:");
		scanf("%d",&infloor);
		printf("请输入用户的目标的楼层:");
		scanf("%d",&outfloor);
		printf("请输入用户的最长容忍时间:");
		scanf("%d",&giveuptime);
		printf("请输入下一个用户的到来时间:");
		scanf("%d",&intertime);
		if(!(infloor<0||infloor>MaxFloor-1||outfloor<0||outfloor>MaxFloor-1)&&(infloor!=outfloor))
			break;
		printf("错误的用户信息录入!\n");
	}
	p->Id=PersonId++;
	p->GiveupTime=giveuptime+Time;
	p->next=NULL;
	p->OutFloor=outfloor;
	if(outfloor>infloor)
		CallUp[infloor]=1;
	else
		CallDown[infloor]=1;
	AddQueue(infloor,p);
	AddAct(intertime,Input);
}

void testinout(void){//检测有无人进出 
	if(Queue[Floor].next||Stack[Floor].next)
		AddAct(CloseTest,testinout);
	else{
		State=DoorCloseing;
		CallUp[Floor]=0;
		CallDown[Floor]=0;
		CallCar[Floor]=0;
		AddAct(DoorTime,doclosedoor);
	}
}

void doclosedoor(void){//电梯门关了 
	printf("电梯门关了\n");
	State=Stop;
}

void doopendoor(void){//打开电梯门 
	printf("电梯门开了\n");
	State=DoorOpen;//门打开了 
	AddAct(CloseTest,testinout);
	if(Stack[Floor].next)
		AddAct(InOutTime,doout);
	else{//没人出,就看有没有进的 
		if(Queue[Floor].next)
			AddAct(InOutTime,doin);
	}
}

void doout(void){
	//根据栈出人,如果没有看是否有人进 
	if(Stack[Floor].next){
		Person_Ele* p=Stack[Floor].next;
		Stack[Floor].next=p->next;
		;//显示信息 
		printf("用户%d走出电梯\n",p->Id);
		free(p);
	}
	if(Stack[Floor].next){
		AddAct(InOutTime,doout);
	}else{
		if(Queue[Floor].next)
			AddAct(InOutTime,doin);
	}
}

void doin(void){//人进入电梯,这里不用关电梯门它会定时关的 
	Person* p=Queue[Floor].next;
	if(p){
		Queue[Floor].next=p->next;
		Person_Ele* pe=(Person_Ele*)malloc(sizeof(Person_Ele));
		int in=p->OutFloor;
		CallCar[in]=1;//置位请求 
		pe->next=Stack[in].next;
		pe->Id=p->Id;
		Stack[in].next=pe;
		printf("用户%d走入电梯\n",p->Id);
		free(p);
	}
	if(Queue[Floor].next){
		AddAct(InOutTime,doin);
	}
}

int GetWhere(void){
	static int old=0;//保存上一次电梯的方向,保证电梯尽可能在一个方向走 
	int isup=0,isdown=0;
	int i;
	for(i=Floor+1;i<MaxFloor;i++){
		if(CallDown[i]||CallUp[i]||CallCar[i])
			isup=1;
	}
	for(i=Floor-1;i>=0;i--){
		if(CallDown[i]||CallUp[i]||CallCar[i])
			isdown=1;
	}
	if(isup==0&&isdown==0){
		return 0;
	}
	if(old==0){
		if(isdown) old=GoingDown;
		if(isup) old=GoingUp;
		return old;
	}
	if(old==GoingUp&&isup)
		return old;
	else if(old==GoingDown&&isdown)
		return old;
	else if(isdown) 
		old=GoingDown;
	else if(isup) 
		old=GoingUp;
	else
		printf("在选择方向时发生错误!\n");
	return old;
}

void tofirst(void){//去第一层
	if(State!=Idle||Floor==BaseFloor)
		return;
	printf("长时间没人请求电梯!将进入%d层\n",BaseFloor);
	CallCar[BaseFloor]=2;//给电梯一个虚拟的去1层的请求,这并不会开门 
}

void doslow(void){//电梯停了 
	printf("电梯停了,当前层是%d\n",Floor);
	State=Stop;
}

void doup(void){ 
	Floor++;
	printf("电梯正在上升!现已到了%d层!\n",Floor);
	if(CallDown[Floor]||CallUp[Floor]||CallCar[Floor]){
		State=SlowUp;
		AddAct(UpDecelerate,doslow);
	}else{
		if(Floor==MaxFloor-1){
			State=SlowUp;
			AddAct(UpDecelerate,doslow);
		}else{
			AddAct(UpTime,doup);
		}
	}
}

void dodown(void){
	Floor--;
	printf("电梯正在下降!现已到了%d层!\n",Floor);
	if(CallUp[Floor]||CallDown[Floor]||CallCar[Floor]){
		State=SlowDown;
		AddAct(DownDecelerate,doslow);
	}else{
		if(Floor==0){
			State=SlowDown;
			AddAct(DownDecelerate,doslow);
		}else{
			AddAct(DownTime,dodown);
		}
	}
}

void domove(void){//加速完成,将进入正常速度 
	if(State==SpeedUp){
		printf("电梯已加速上升!\n");
		State=GoingUp;
		AddAct(UpTime,doup);
	}else{
		printf("电梯已加速下降!\n");
		State=GoingDown;
		AddAct(DownTime,dodown);
	}
}

void Controler(void){
	if(State==Idle||State==Stop){ 
		if(CallUp[Floor]||CallDown[Floor]||CallCar[Floor]){
			//当前层有请求,需要开门进出
			if(CallCar[BaseFloor]==2){
				CallCar[BaseFloor]=0;
				State=Idle;
				printf("现在在%d层,无人请求电梯!\n",BaseFloor);
				return;
			}
			State=DoorOpening;
			AddAct(DoorTime,doopendoor);
		}
		else{
			//当前层无请求,判断其他层请求
			int whitch=GetWhere();
			if(whitch==GoingUp){
				State=SpeedUp;
				AddAct(Accelerate,domove);
			}else if(whitch==GoingDown){
				State=SpeedDown;
				AddAct(Accelerate,domove);
			}else{
				State=Idle;
				if(Floor!=BaseFloor)
					AddAct(OverTime,tofirst);
			}
		}
	}
	//否则电梯忙碌 
	return;
}

void DoTime(){
	//此函数用于模拟时钟 
	while(1){
		if(Time>MaxTime)
			return;
		TestPeople();//两个始终都会被调用的函数 
		Controler(); 
		struct Activity* p=activity.next;
		if(p==NULL){
			Time=MaxTime;
		}
		if(p&&Time>=p->time){//取出活动队头的,检测定时是否到了 
			activity.next=p->next;
			p->fn();
			free(p);
		}
		Time++;
	}
}
附程序运行结果:









八、 实验内容和要求: 要求根据下面的功能说明描述实现模拟电梯控制软件 (一)电梯配置 1. 共有1个电梯 2. 共有maxfloor层楼层。maxfloor=9。 3. 中间层每层有上下两个按钮,最下层只有上行按钮,最上层只有上行按钮。每层都有相应的指示灯,灯亮表示该按钮已经被按下,如果该层的上行或者下行请求已经被响应,则指示灯灭 4. 电梯内共有maxfloor个目标按钮,表示有乘客在该层下电梯。有指示灯指示按钮是否被按下。乘客按按钮导致按钮指示灯亮,如果电梯已经在该层停靠则该按钮指示灯灭 5. 另有一启动按钮(GO)。当电梯停在某一楼层后,接受到GO信息就继续运行。如果得不到GO信息,等待一段时间也自动继续运行。 6. 电梯内设有方向指示灯表示当前电梯运行方向。 说明:由于本次实验不使用可视化框架,所以无法作到从图形界面上获取按钮请求。因此电梯按钮的设计,不在图形界面上体现,仅用来设计键盘的模拟输入。 (二)电梯的运行控制 1.电梯的初始状态是电梯位于第一层处,所有按钮都没有按下。 2.乘客可以在任意时刻按任何一个目标钮和呼叫钮。呼叫和目标对应的楼层可能不是电梯当前运行方向可达的楼层。 3. 如果电梯正在向I层驶来,并且位于I层与相邻层(向上运行时是I-1层或者向下运行时是I+1层)之间,则因为安全考虑不响应此时出现的I层目标或者请求。如果电梯正好经过了I楼层,运行在I楼层和下一楼层之间,则为了直接响应此时出现的I层目标或者请求,必须至少到达运行方向上的下一楼层然后才能掉头到达I楼层(假设掉头无须其它额外时间),如果I楼层不是刚刚经过的楼层则可以在任意位置掉头,此时掉头后经过的第一个楼层不可停。 4. 电梯系统依照某种预先定义好的策略对随机出现的呼叫和目标进行分析和响应。 5. 乘客数量等外界因素(可能导致停靠时间的长短变化)不予考虑。假设电梯正常运行一层的时间是5S,停靠目标楼层、上下乘客和电梯继续运行的时间是5S。 6. 当电梯停靠某层时,该层的乘客如果错误的按目标或呼叫按钮都不予响应。 7. 电梯停要某一层后,苦无目标和呼叫,则电梯处于无方向状态,方向指示灯全灭,否则电梯内某个方向的指示灯亮,表示电梯将向该方向运行。等接到“GO”信号后电梯立即继续运行。若无GO信号,则电梯在等了上下乘客和电梯继续运行时间后也将继续运行。 8. 当一个目标(呼叫)已经被服务后,应将对应的指示灯熄灭。 (三)电梯运行的控制策略 以下是几个候选策略: 1.先来先服务策略: 将所有呼叫和目标按到达时间排队,然后一一完成。这是相当简单的策略,只需要设计一个将呼叫和目标排队的数据结构。因为该策略效率也很低,所以没有实际的电梯采用这种策略。 2. 顺便服务策略: 顺便服务是一种最常见的简单策略。这种策略在运行控制中所规定的安全前提下,一次将一个方向上的所有呼叫和目标全部完成。然后掉转运行方向完成另外一个方向上的所有呼叫和目标。 可以采用设定目标楼层的办法来实现这个策略,即电梯向一个目标楼层运行,但这个楼层可以修改。具体策略如下: 1) 修改目标楼层的策略: a.如果电梯运行方向向上,那么如果新到一个介于当前电梯所处楼层和目标楼层之间,又可以安全到达的向上呼叫或者目标,将目标楼层修改为这个新的楼层。 b.如果电梯运行方向向下,那么如果新到一个介于当前电梯所处楼层和目标楼层之间,又可以安全到达的向下呼叫或者目标,将目标楼层修改为这个新的楼层。 2)确定新的目标楼层: 如果电梯向上运行,当它到达某个目标楼层后,则依照以下顺序确定下一个目标楼层: a.如果比当前层高的楼层有向上呼叫或者目标,那么以最低的高于当前楼层的有向上呼叫或者目标的楼层为目标。 b.如果无法确定目标楼层,那么以最高的向下呼叫或者目标所在楼层为电梯当前目标楼层。 c.如果无法确定目标楼层,那么以最低的向上呼叫所在楼层为电梯当前的目标楼层。 d.如果仍然不能确定目标楼层(此时实际上没有任何呼叫和目标),那么电梯无目标,运行暂停。 如果电梯向下运行,依照以下顺序确定下一目标楼层: a.如果比当前层低的楼层有向下呼叫或者目标,那么以最高的低于当前楼层的有向下呼叫或者目标的楼层为目标。 b.如果无法确定目标楼层,那么以最低的向上呼叫或者目标所在楼层为电梯当前目标楼层。 c.如果无法确定目标楼层,那么以最高的向下呼叫楼层为目标楼层。 d.如果仍然不能确定目标楼层(此时实际上没有任何呼叫和目标),那么电梯无目标,运行暂停。 3)最快响应策略: 响应所有的现在存在的所有呼叫和目标所需时间(采用不同方案电梯停靠时间相同,所以不必考虑)最短的策略。 可选方案一是电梯先向上运行响应经过各层的目标和向上呼叫,再向下运行响应所有向下呼叫以及途经各层的目标,最后再向上响应剩余的向上呼叫。二是恰好相反,
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值