说明:
由于时间的问题,上一篇博客中的电梯调度程序还不够很完善。利用星期日上午的时间做了部分的调整和改进。
改进部分说明:
改进的地方主要有两个部分:
1、接受多个用户同时输入请求;
2、多个用户可以同时进入电梯,并选择自己的目的楼层。
3、关于电梯运行状态的更改,由于多处用到这个部分,此处改为函数,避免重复,使代码精简。
具体实现说明:
1、多用户同时输入
其实当初在这个方面多做思考,程序的查找功能、电梯需要停靠楼层和电梯状态的更新都是用独立的函数实现的。所以想支持多个用户的输入也很简单,只需在原有的基础上加一个循环。循环调用用户的输入函数、电梯查找函数、以及电梯停靠标记。
cout << "几人输入";
cin >> c;
if (c > 0)
{
for (int i = 0; i < c;i++)
Inset();
}
change();
2、多个用户同时进入电梯
此处的实现和多个用户同时输入基本一样,也是利用加循环的办法,只是此处需要更改的地方较多。
(1)乘客进电梯部分(函数void geiIn(int i))
首先需要用户输入几人进入电梯,然后再用for循环控制,循环体包括用户输入目的楼层,判断电梯是否到达目的楼层,如果到达标记为停靠。同时也要改变电梯里的人数,控制超重。
cout << "请输入几人进入电梯";
cin >> num;
for (int m = 0; m < num && a[i].ifFloor == 0; m++)
{
int f;
cout << "输入目的层数";
cin >> f;
if (f % 2 == a[i].serveFloor || a[i].serveFloor == 3)//此电梯是否到目的层
{
a[i].nowPeople++;
ifFull(i);
if (a[i].staut == 0)//电梯如果是暂停状态,更改目的状态
{
if (a[i].floor > f)
a[i].staut = -1;
if (a[i].floor < f)
a[i].staut = 1;
}
a[i].inPeople[f] = 1;//标记目的层数
}
else
{
cout << "此电梯不到目的层";
}
}
(2)乘客出电梯部分(函数void getOut(int i))
首先需要用户输入几人出电梯,然后再用for循环控制,循环体包括恢复电梯此楼层不需停靠(a[i].inPeople[a[i].floor] = -1),同时也要改变电梯里的人数。
cout << "请输入几人出电梯";
cin >> num;
for (int m = 0; m < num; m++)
{
a[i].nowPeople--;
ifFull(i);
a[i].inPeople[a[i].floor] = -1;
}
(3)电梯状态控制封装为函数
函数原型为:int ifRun(int i)。返回值为int类型,返回1表示电梯还需以现在的状态继续运行,返回0表示电梯更改为静止状态。实现方法主要是,判断电梯的是否外部响应和内部响应,也就是说要同时满足,电梯外没有用户需要,电梯内没有用户。即,数组inPeople[21]和outPeople[21]的值全部为-1.
int ifRun(int i)
{
int flag1, flag2;
flag1 = 1;
flag2 = 1;
for (int j = 0; j < 21; j++)//电梯是否需要继续运行
{
if (flag1 == 1 && a[i].inPeople[j] == -1)
continue;
else
{
flag1 = 0;
break;
}
}
for (int j = 0; j < 21; j++)
{
if (flag2 == 1 && a[i].outPeople[j] == -1)
continue;
else
{
flag2 = 0;
break;
}
}
if (flag1 == 1 && flag2 == 1)
{
a[i].staut = 0;
return 0;
}
else
return 1;
}
程序调试及结果分析:
首先先对输入的数据进行说明以及结果预测:
4个用户输入->1)8 -1(8楼用户下楼请求)-> 3号电梯响应 -> 1人进入电梯 -> 目的楼层0 -> 1人出电梯
2)19 -1(19楼用户下楼请求)-> 1号电梯响应 -> 11人进入电梯(1号电梯最大载重为10,最后一人不能上电梯) -> 目的楼层全部为0 -> 1人出电梯
3)3 1(3楼用户上楼请求)-> 4号电梯响应 -> 2人进入电梯 -> 目的楼层5 -> 1人出电梯
-> 目的楼层8-> 1人出电梯
4)7 1(3楼用户上楼请求)-> 2号电梯响应 -> 2人进入电梯 -> 目的楼层11 -> 1人出电梯
-> 目的楼层12-> 此电梯不到目的层(2号电梯为单数电梯)
1、用户输入

2、电梯做出响应

3、19楼到了11人进入电梯,最后一人无法进入

4、7楼到了用户进入电梯,输入目的楼层,此电梯为单层服务

5、8楼到了,请输入几人进入电梯

6、5楼到了,请输入几人出电梯

7、电梯运行完整,恢复暂停状态,等待用户输入

总结:
这次主要对上次不完善的地方做了点改进,我也会和队友继续讨论,找到程序还存在的问题,并且找到解决办法,不断的完善。
源代码:
#include<iostream>
#include<Windows.h>
#include <conio.h>
using namespace std;
struct elevator
{
int maxPeople;//电梯最大载重量
int nowPeople;//电梯目前装载4人数
int ifFloor;//是否超载(已满1、未满0)
int serveFloor;//电梯服务楼层(全部3、单层1、双层0)
int outPeople[21];//外部人按电梯请求楼层(数组下标表示楼层,数值值表示是否停靠。停靠1、不停靠-1)
int inPeople[21];//电梯内部人按电梯请求楼层
int staut;//上升1、下降-1、停止0
int floor;//电梯目前楼层
};
struct elevator a[4];
int ifRun(int i)
{
int flag1, flag2;
flag1 = 1;
flag2 = 1;
for (int j = 0; j < 21; j++)//电梯是否需要继续运行
{
if (flag1 == 1 && a[i].inPeople[j] == -1)
continue;
else
{
flag1 = 0;
break;
}
}
for (int j = 0; j < 21; j++)
{
if (flag2 == 1 && a[i].outPeople[j] == -1)
continue;
else
{
flag2 = 0;
break;
}
}
if (flag1 == 1 && flag2 == 1)
{
a[i].staut = 0;
return 0;
}
else
return 1;
}
int number(int x)//取绝对值
{
if (x < 0)
return -x;
else
return x;
}
void Iint()//各个电梯初始化
{
for (int i=0; i < 4; i++)
{
for (int j = 0; j < 21; j++)
{
a[i].inPeople[j] = -1;
a[i].outPeople[j] = -1;
}
a[i].nowPeople = 0;
a[i].ifFloor = 0;
}
a[0].maxPeople = 10;
a[0].serveFloor = 3;
a[0].staut = 0;
a[0].floor = 20;
a[1].maxPeople = 10;
a[1].serveFloor = 1;
a[1].staut = 0;
a[1].floor = 9;
a[2].maxPeople = 20;
a[2].serveFloor = 0;
a[2].staut = 0;
a[2].floor = 10;
a[3].maxPeople = 20;
a[3].serveFloor = 3;
a[3].staut = 0;
a[3].floor = 1;
}
void gotoxy(HANDLE hOut, int x, int y)//光标移到指定位置
{
COORD pos;
pos.X = x; //横坐标
pos.Y = y; //纵坐标
SetConsoleCursorPosition(hOut, pos);
}
void ifFull(int i)//判断电梯是否超载
{
if (a[i].maxPeople < a[i].nowPeople)
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
gotoxy(hOut, 0, 4);
cout << "电梯已满!" << endl;
Sleep(1000);
gotoxy(hOut, 0, 4);
cout << " ";
a[i].ifFloor = 1;
return;
}
else
{
a[i].ifFloor = 0;
return;
}
}
void getIn(int i)//进入电梯
{
a[i].outPeople[a[i].floor] = -1;
ifRun(i);
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
gotoxy(hOut, 0, 5);
int num;
cout << "请输入几人进入电梯";
cin >> num;
gotoxy(hOut, 0, 5);
cout << " ";
for (int m = 0; m < num && a[i].ifFloor == 0; m++)
{
int f;
gotoxy(hOut, 0, 3);
cout << "输入目的层数";
cin >> f;
gotoxy(hOut, 0, 3);
cout << " ";
if (f % 2 == a[i].serveFloor || a[i].serveFloor == 3)//此电梯是否到目的层
{
a[i].nowPeople++;
ifFull(i);
if (a[i].staut == 0)//电梯如果是暂停状态,更改目的状态
{
if (a[i].floor > f)
a[i].staut = -1;
if (a[i].floor < f)
a[i].staut = 1;
}
a[i].inPeople[f] = 1;//标记目的层数
}
else
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
gotoxy(hOut, 0, 4);
cout << "此电梯不到目的层";
Sleep(1000);
gotoxy(hOut, 0, 4);
cout << " ";
}
}
}
void getOut(int i)//出电梯
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
int num;
gotoxy(hOut, 0, 5);
cout << "请输入几人出电梯";
cin >> num;
gotoxy(hOut, 0, 5);
cout << " ";
for (int m = 0; m < num; m++)
{
a[i].nowPeople--;
ifFull(i);
a[i].inPeople[a[i].floor] = -1;
}
}
void display()//结果显示
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
for (int i = 0, j = 0; i < 4; i++,j=j+6)
{
gotoxy(hOut, j, 0);
if (a[i].staut == 1)
{
if (a[i].floor>=10)
cout << "↑" << a[i].floor;
else
cout << "↑0" << a[i].floor;
}
if (a[i].staut == 0)
{
if (a[i].floor >= 10)
cout << "__" << a[i].floor;
else
cout << "__0" << a[i].floor;
}
if (a[i].staut == -1)
{
if (a[i].floor >= 10)
cout << "↓" << a[i].floor;
else
cout << "↓0" << a[i].floor;
}
}
}
void change()//更新电梯状态
{
int flag, i;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
for (i = 0; i < 4; i++)
{
if (a[i].staut == 1)//上升状态的电梯
{
if (a[i].inPeople[a[i].floor] == 1)
{
gotoxy(hOut, 0, 4);
cout << a[i].floor << "到了! 乘客出电梯";
Sleep(1000);
gotoxy(hOut, 0, 4);
cout << " ";
getOut(i);
}
if (a[i].outPeople[a[i].floor] == 1)
{
gotoxy(hOut, 0, 4);
cout << a[i].floor << "到了! 乘客进入电梯";
Sleep(1000);
gotoxy(hOut, 0, 4);
cout << " ";
getIn(i);
}
flag = ifRun(i);
if (flag==1)
a[i].floor++;//电梯继续上行
}
if (a[i].staut == -1)//下降状态的电梯
{
if (a[i].inPeople[a[i].floor] == 1)
{
gotoxy(hOut, 0, 4);
cout << a[i].floor << "到了! 乘客出电梯";
Sleep(1000);
gotoxy(hOut, 0, 4);
cout << " ";
getOut(i);
}
if (a[i].outPeople[a[i].floor] == 1)
{
gotoxy(hOut, 0, 4);
cout << a[i].floor << "到了! 乘客进入电梯";
Sleep(1000);
gotoxy(hOut, 0, 4);
cout << " ";
getIn(i);
}
flag = ifRun(i);
if (flag == 1)
a[i].floor--;//电梯继续下降
}
}
display();
}
int ifSever(int floor, int direction, int elevator)//判断电梯是否相应此用户
{
if (a[elevator].ifFloor == 0)//不超载
{
if (a[elevator].serveFloor == 3 || floor % 2 == a[elevator].serveFloor)//全部和双层
{
if (a[elevator].staut == 0)//停止状态
return 1;
if (a[elevator].staut == 1 && a[elevator].staut == direction)//上升且用户也上升
{
if (a[elevator].floor <= floor)
return 1;
else
return 0;
}
if (a[elevator].staut == -1 && a[elevator].staut == direction)//下降且用户也下降
{
if (a[elevator].floor >= floor)
return 1;
else
return 0;
}
return 0;
}
else
return 0;
}
else
return 0;
}
int search(int floor,int direction)//查询哪个电梯为用户服务
{
int min[4] = { 100, 100, 100, 100 };
int flag;
int x;
for (int i = 0; i < 4; i++)
{
flag = ifSever(floor, direction, i);
if (flag==1)//计算电梯运行距离
{
x = a[i].floor - floor;
min[i] = number(x);
}
else
continue;
}
int temp, num;
temp = min[0];
num = 0;//标记电梯号
for (int i = 1; i < 4; i++)//计算最近楼层
{
if (min[i] < temp)
{
temp = min[i];
num = i;
}
}
if (temp != 100)
{
a[num].outPeople[floor] = 1;
if (a[num].staut==0)
{
if (a[num].floor > floor)
a[num].staut = -1;
if (a[num].floor < floor)
a[num].staut = 1;
if (a[num].floor == floor)
a[num].staut = direction;
}
return 1;
}
return 0;
}
void Inset()//用户输入
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
int peopleFloor, peopleDirection, flag;
gotoxy(hOut, 0, 2);
cout << "输入请求的楼层数和方向(1为向上,-1为向下)";
cin >> peopleFloor;
cin >> peopleDirection;
gotoxy(hOut, 0, 2);
cout << " ";
flag = search(peopleFloor, peopleDirection);
if (flag == 1)//如果查询到服务的电梯
return;
else
{
while (flag == 0)
{
change();
flag = search(peopleFloor, peopleDirection);
}
}
}
void main()
{
Iint();
display();
int c;
while (1)
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
gotoxy(hOut, 0, 1);
cout << "几人输入";
cin >> c;
if (c > 0)
{
for (int i = 0; i < c;i++)
Inset();
}
change();
}
system("pause");
}