源碼在文章結尾,需要者自取(有問題歡迎評論批評指教)
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 }