1.項目要求
某貿易中心共10層,設有載客電梯1部。爲了處理問題的方便,有以下的限定條件:
(1) 電梯的運行規則是:可到達每層。
(2) 每部電梯的最大乘員量均爲K人(K值可以根據仿真情況在10~20人之間確定)。
(3) 仿真開始時,電梯隨機地處於其符合運行規則的任意一層,爲空梯。
(4) 仿真開始後,有N人(>20人)在該國際貿易中心的1層,開始乘梯活動。
(5) 每個人初次所要到達的樓層是隨機的,開始在底層等待電梯到來。
(6) 每個人乘坐電梯到達指定樓層後,再隨機地去往另一樓層,依此類推,當每人乘坐過L次(L值可以根據仿真情況在3~10次之間確定)電梯後,第L+1次爲下至底層並結束乘梯行爲。到所有人結束乘梯行爲時,本次仿真結束。
(7) 電梯運行速度爲S秒/層(S值可以根據仿真情況在1~5之間確定),每人上下時間爲T秒(T值可以根據仿真情況在2~10之間確定)。
(8) 電梯運行的方向由先發出請求者決定,不允許後發出請求者改變電梯的當前運行方向,除非是未被請求的空梯。
軟件開發要求:
(1)設計一個易於理解的界面,動態顯示各梯的載客與運行情況(上、下或停止),動態顯示各樓層的人員停留情況與要求乘梯情況;動態顯示從仿真開始到目前的時間。
(2)可變動的參數(K、N、L、S、T)應在程序開始時從對話框輸入。
2.執行過程
基於面對對象的思想,我們創建了大樓類、電梯類、乘客類三個主要類,對照生活中的經驗,爲每個類編寫各自的函數,體現“高內聚、低耦合”的設計,每個類只做自己的事情。
1. 創建MainWidget類,它初始化界面
2. 當我們按下“開始”按鈕時,SimuThread類構造,綁定信號和槽。在SimuThread類構造中,又構造了building類和elevator類
3. SimuThread類繼承了Simulation,調用Simulation類的run方法,開始Simulation中的主流程
2.1主流程
這個電梯遵循傳統的電梯調度算法:順向截停,即在電梯的運行過程中,只有跟電梯相同方向的請求才會被響應,電梯開門。當電梯到了這個方向的盡頭時,後續方向無請求,則換方向,開始處理反方向的請求。
//0.初始請求已在構造乘客時完成,乘客都在1樓,且要去的樓層隨機。電梯會出現在隨機的樓層。
while(finished!=num&&!stopFlag){
//1.電梯請求處理
//若當前有方向:1.後續無請求,則變爲無方向; 2.後續有請求,繼續該方向
//若當前無方向,根據請求變更方向
elevator->reqHandler(building);
//2.電梯移動一層
elevator->move();
//3.電梯判斷是否需要開門:根據電梯內的按鈕和樓道上的按鈕
bool open = elevator->open(building);
if(open){
//4.若開門且無方向,則修正方向,說明到了這個方向的盡頭了,需要換個反方向
RequestBtn bt = building->getButtonsByLevel(elevator->getLevel());
elevator->correctMovingDir(bt);
qDebug("open");
QTest::qWait(Elevator::timeToMoveOneLevel*1000/RATE);
//把下客分爲2個步驟的原因是:如果將步驟5.3放到5.2之前的話,那麼剛下去的客人,
//在請求方向和電梯方向相同的情況下,又會馬上進電梯,我們要防止這種情況。在下一輪再去處理這種請求,模擬真實情況。
//5.1 下客1
elevator->passengerOut(passengerVec1);
//5.2 上客
building->passengerOut(elevator,passengerVec2);
elevator->passengerIn(passengerVec2);
//5.3 下客2
building->passengerIn(elevator, passengerVec1);
}
//6.乘客請求:電梯內的人,在上次出電梯時決定了要去的樓層,需要按下電梯內的樓層按鈕。
//樓道上的人,在步驟5出電梯的時候決定了下次要去的樓層,然後按下樓道上的按鈕
elevator->afterMove();
building->afterMove(elevator->getLevel());
}
}