电梯调度的改进
说明:
由于时间的问题,上一篇博客中的电梯调度程序还不够很完善。利用星期日上午的时间做了部分的调整和改进。
改进部分说明:
改进的地方主要有两个部分:
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"); }