基於LOOK磁碟排程演算法寫一個電梯執行模擬器
阿新 • • 發佈:2018-12-26
大四上學期的一門軟體理論專題課要求課程結束之後寫個大作業,在外苦逼實習一節課沒上的我居然還要寫這個玩意,懷著日樂購的心情隨便選了一個電梯模擬系統的題。
題目拿到手,首先考慮要不就寫了大一時期的字元介面的吧,轉念一想字元介面還是不符合我的氣質,所以我又搬出牛逼哄哄的DuiLib介面庫,雖然這個介面庫已經停止維護了,不過怎麼說人家現在也還是微信採用的介面庫啊,這裡附上寫的很好的一篇duilib教程
,然後仔細研究了一下電梯的執行原理,為此下班上樓時專門仔細注意了一下電梯,後來百度一下發現原來這個叫做LOOK磁碟排程演算法,這裡你可能會疑惑為什麼電梯的執行演算法扯到了磁碟排程,因為電梯執行時類似於磁碟尋道,磁碟尋道時通常是磁頭執行到相應的請求的磁軌再將資料讀入記憶體,LOOK排程演算法的原理是每次只執行到最外層的請求道就返回,舉個例子:
假設某個磁碟磁軌編號為1~200,當前磁頭的位置在100, 請求序列為 : 45 、 99 、 160 、 3
這時磁頭的訪問順序就是160、99、45、3
在電梯的實際執行中包含上樓的請求、下樓的請求和進入電梯之後需要前往的目標層,採用LOOK演算法之後,若電梯當前處在向上執行的狀態電梯會一直執行到最高的請求層之後,再調轉方向,反正同理。
我採用了連結串列來儲存請求層和目標層,上向請求層升序排列,下向請求層降序排列這樣可方便拿到最高的請求層和最低的請求層,建立一個電梯物件來標識電梯的位置,在迴圈中監控電梯的位置是否到達目標點,話不多說直接上程式碼:
while(1)
{
bool isArrive = false;
if(elevator->getStatus()) //電梯是否在執行,若在執行再看執行方向
{
::PostMessage(hWnd, WM_TARBTNOPEN, 0L, 0);
if(elevator->isUp())
{
elevator->Upstairs();
::PostMessage(hWnd, WM_REDRAW, 0L, 0);
if(request_down_head != NULL)
{
if(request_down_head->floor == elevator->getFloor())
{
::PostMessage(hWnd, WM_CHANGEDBTNCOLOR, 0L, 0);
//到達了最高的一個下向請求層
FreeDownRequest(request_down_head);
::MessageBox(NULL, _T("到達請求樓層,開門!"), _T("注意安全"), NULL);
isArrive = true;
elevator->setDown();
}
}
else if(FindRequestUp(elevator->getFloor()))
{
::PostMessage(hWnd, WM_CHANGEUBTNCOLOR, 0L, 0); //到達了上向請求層
::MessageBox(NULL, _T("到達請求樓層,開門!"), _T("注意安全"), NULL);
isArrive = true;
}
if(FindTarget(elevator->getFloor()))
{
::PostMessage(hWnd, WM_CHANGENBTNCOLOR, 0L, 0);
::MessageBox(NULL, _T("到達了目標樓層,開門!"), _T("注意安全"), NULL);
isArrive = true;
}
}
else if(elevator->isDown())
{
elevator->Downstairs();
::PostMessage(hWnd, WM_REDRAW, 0L, 0);
if(request_up_head != NULL)
{
if(request_up_head->floor == elevator->getFloor())
{
::PostMessage(hWnd, WM_CHANGEUBTNCOLOR, 0L, 0);
::MessageBox(NULL, _T("到達請求樓層,開門!"), _T("注意安全"), NULL);
FreeUpRequest(request_up_head);
isArrive = true;
elevator->setUp();
}
}
else if(FindRequestDown(elevator->getFloor()))
{
::PostMessage(hWnd, WM_CHANGEDBTNCOLOR, 0L, 0);
::MessageBox(NULL, _T("到達請求樓層,開門!"), _T("注意安全"), NULL);
isArrive = true;
}
if(FindTarget(elevator->getFloor()))
{
//::PostMessage(hWnd, WM_CHANGEUBTNCOLOR, 0L, 0); //到達了上向請求層
::PostMessage(hWnd, WM_CHANGENBTNCOLOR, 0L, 0);
::MessageBox(NULL, _T("到達了目標樓層,開門!"), _T("注意安全"), NULL);
isArrive = true;
}
}
if(target_head == NULL && request_down_head == NULL && request_up_head == NULL) //沒有目標了就停下來
{
//::MessageBox(NULL, _T("停!"), _T("注意安全"), NULL);
elevator->stop();
}
if(isArrive)
{
::Sleep(5000);
::MessageBox(NULL, _T("電梯關門!"), _T("注意安全"), NULL);
if(target_head == NULL)
{
if(elevator->isDown() && request_down_head == NULL && request_up_head != NULL)
{
if(request_up_head->floor >= elevator->getFloor())
{
elevator->setUp();
}
}
if(elevator->isUp() && request_up_head != NULL && request_down_head == NULL)
{
if(request_up_head->floor <= elevator->getFloor())
{
elevator->setDown();
}
}
}
}
if(!elevator->getStatus())
{
::PostMessage(hWnd, WM_TARBTNCLOSE, 0L, 0);
}
}
else //當前狀態為停止時:
{
/**/
if(request_down_head != NULL) //有下向請求層時,設定狀態為執行,根據位置設定方向
{
if(request_down_head->floor > elevator->getFloor())
{
elevator->setUp();
elevator->run();
}else if(request_down_head->floor == elevator->getFloor())
{
::MessageBox(NULL, _T("到達請求樓層,開門!"), _T("注意安全"), NULL);
FreeDownRequest(request_down_head);
::PostMessage(hWnd, WM_CHANGEDBTNCOLOR, 0L, 0);
::PostMessage(hWnd, WM_TARBTNOPEN, 0L, 0);
elevator->setDown();
::Sleep(5000);
::MessageBox(NULL, _T("電梯關門!"), _T("注意安全"), NULL);
}
else
{
elevator->setDown();
elevator->run();
}
::PostMessage(hWnd, WM_TARBTNOPEN, 0L, 0);
}
else if(request_up_head != NULL) //有上向請求層時,設定狀態為執行,根據位置設定方向
{
if(request_up_head->floor > elevator->getFloor())
{
elevator->setUp();
elevator->run();
}
else if(request_up_head->floor == elevator->getFloor())
{
::MessageBox(NULL, _T("到達請求樓層,開門!"), _T("注意安全"), NULL);
FreeUpRequest(request_up_head);
::PostMessage(hWnd, WM_CHANGEUBTNCOLOR, 0L, 0);
::PostMessage(hWnd, WM_TARBTNOPEN, 0L, 0);
elevator->setUp();
::Sleep(5000);
::MessageBox(NULL, _T("電梯關門!"), _T("注意安全"), NULL);
}
else
{
elevator->setDown();
elevator->run();
}
::PostMessage(hWnd, WM_TARBTNOPEN, 0L, 0);
}
else if(target_head != NULL) //有目標層時,設定狀態為執行,根據位置設定方向
{
if(target_head->floor > elevator->getFloor())
{
elevator->setUp();
elevator->run();
}else if(target_head->floor == elevator->getFloor())
{
::MessageBox(NULL, _T("到達目標層,開門!"), _T("注意安全"), NULL);
FreeTarget(target_head);
::PostMessage(hWnd, WM_CHANGENBTNCOLOR, 0L, 0);
::PostMessage(hWnd, WM_TARBTNOPEN, 0L, 0);
//elevator->setUp();
::Sleep(20000);
}
else
{
elevator->setDown();
elevator->run();
}
::PostMessage(hWnd, WM_TARBTNOPEN, 0L, 0);
}
}
::Sleep(500);
}
這裡更新軟體介面是採用MFC的訊息對映來完成,介面的程序和邏輯的程序需要同步執行
最終寫出來的軟體長這樣:
迷之介面有沒有…哈哈哈
具體專案已上傳至GitHub
上傳至GitHub