電梯模擬C++


源碼在文章結尾,需要者自取(有問題歡迎評論批評指教)

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:存儲乘客的相關信息,以便於在電梯模塊中使用。

2struct node*類型的next,用於鏈接下一個節點。

 函數有:(1append(形參為乘客類數據):因為有頭尾指針和頭節點,只要把形參鏈接到尾部即可。

2empty:只要頭指針指向的next為空就返回true,否則就返回false

3Remove(形參為乘客的ID):if當前節點是否就是所要刪除的節點,如果是就根據是否是僅此一個節點或者是多個節點來分開處理;else當前節點不是要刪除的節點,那么遍歷整個鏈表去尋找所要刪除的節點。

 

乘客類passenger

成員有:(1ID:用於設置乘客的編號。

2nowfloor:用於記錄乘客當前樓層。

3gofloor:用於記錄乘客需要去的樓層。

4whenwait:用於記錄乘客多久進入等待隊列。

函數有:(1)默認構造函數以及接口函數。

2setdata(參數為乘客ID):對該ID下的乘客進行賦值,並且限制乘客的當前樓層和所要前往的樓層為1-9,一旦超出范圍則提示需要重新輸入數據。

 

電梯類elevator

成員有:(1State:用於記錄電梯的狀態。

2floor:用於記錄電梯所處樓層。

3Wait:指向等待隊列頭節點的指針。

4DiantiLI[10]:電梯里的人員數組,下標用於記錄該層是否有人下電梯。

5All:記錄電梯里的人數。

6Dir:用於判斷電梯處於UpDown以外時之前所處的狀態,以便於下一步的狀態判斷,-1為初始狀態,0為下降,1為上升。

函數有:(1setnowState(參數為需要設定的電梯狀態):用於更改電梯狀態。

2setAll(參數為需要修改的乘客數量,有符號的整型):將參數與All參數進行加減。

(3)setDir(參數為想要把Dir改變的值):將Dir改變為參數值。

4JudgeGiveUp(參數為當前時間):用於判定當前是否有人放棄

如果(指針不為空){

如果(當前訪問的節點的等待時間+忍耐時間==當前時間)

刪除該節點並提示  }

(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{

     如果電梯里外都沒有人{

         改變電梯狀態並且返回空

     }

     如果floor1{     //因為此時是電梯里外肯定至少有一種情況不為空

    改變電梯狀態為Up並且把Dir置為1

      }

     如果floor9{

    改變電梯狀態為Down並且把Dir置為0

      }

      如果電梯里有人{

            遍歷數組DiantiLi得到下標i,並通過i來改變電梯狀態

      }

      如果電梯外不為空{

      //此時根據電梯關門前的Dir來進行判定是否前往接乘客,此時分4種情況,2種上行,2種下行

    如果Dir1{

      如果乘客樓層在當前樓層之上,才有可能前往接乘客{

                如果該乘客是上行則將最遠請求與該乘客的前往樓層對比,並進行更改

                否則如果乘客是下行,就將最遠請求與該乘客的當前樓層對比,並進行對比

                 }

                 對最遠請求進行對比和更改

             }

    如果Dir0{

                 如果乘客樓層在當前樓層之下,才有可能前往接乘客{

                 如果該乘客是下行則將最遠請求與該乘客的前往樓層對比,並進行更改

                 否則如果乘客是上行,就將最遠請求與該乘客的當前樓層對比,並進行對比

                 }

                 對最遠請求進行對比和更改

            }

       }

}

如果狀態為Waiting{

           循環遍歷等待隊列,找出最先按鍵的人,去響應該請求

           如果ptemp(指向頭節點)不為空{

      如果便利到進入隊列時間最早的乘客{

                       如果是電梯需要上行

                            則記錄上行的最遠請求

                       如果是電梯需要下行

                            則記錄下行的最遠請求

                       如果兩者皆有

                             則滿足先上后下的原則來改變電梯的狀態

                }

           }

}

如果電梯狀態為Up{

        如果電梯里有人{

     遍歷DiantiLi數組得到電梯里的乘客的最遠請求

         }

   如果等待隊列有人{

                遍歷整個等待隊列

                如果有乘客要去的樓層或者當前樓層比最遠請求大

                        則改變最遠請求

          }

}

如果電梯狀態為Down{

        如果電梯里有人{

      遍歷DiantiLi數組得到電梯里的乘客的最遠請求

         }

   如果等待隊列有人{

                 遍歷整個等待隊列

                 如果有乘客要去的樓層或者當前樓層比最遠請求小

                        則改變最遠請求

           }

}

最后調用MoveDirction函數,並把最遠請求傳入

7MoveDirction(參數為最遠請求):通過最遠請求和目前的狀態來調用不同的函數

    如果最遠請求小於當前樓層

           調用MoveDown並返回空

    如果最遠請求大於當前樓層

           調用MoveUp並返回空

    如果電梯狀態目前為Opening

           調用Open函數並返回空

    如果電梯狀態目前為In

           調用IN函數,並且調用JudgeClose函數進行判定此時是否還有人要進入,並返回空

    如果電梯狀態目前為Out

           調用OUT函數,並且調用JudgeClose函數進行判定此時是否還有人要進入,返回空

   如果電梯狀態目前為Opened

           JudgeClose判定是否關門

           調用JudgeOut判定是否有人要出門,如果有人出去,調用OUT;調用JudgeIn判定是否有      人要進入,如果有人進入,調用IN,然后返回空

   如果電梯狀態目前為Closing

          調用Close並返回空    

   如果最遠請求等於當前樓層並且電梯里外都無人

          將電梯置為Waiting,並且進入NoPassenger輸出電梯是空閑狀態

   如果最遠請求等於當前樓層且電梯里外是有人的

           此時將電梯置為Opening,並且進入Open   

8MoveDown:輸出電梯下樓每一t的狀態

     如果record(全局變量,用於輸出電梯每一t的狀態)小於枚舉的值

            record自加,輸出“電梯正在下樓”並返回空

     如果等於枚舉的值時

             電梯的樓層自減1,並且record0

  如果JudgeOpenfalse則繼續調用MoveDown顯示下樓的狀態

             如果JudgeOpentrue則將電梯的狀態置為Opening

(9)MoveUp:輸出電梯上樓每一t的狀態

    如果record(全局變量,用於輸出電梯每一t的狀態)小於枚舉的值

           record自加,輸出“電梯正在上樓”並返回空

    如果等於枚舉的值時

           電梯的樓層自加1,並且record0

 如果JudgeOpenfalse則繼續調用MoveUp顯示上樓的狀態

            如果JudgeOpentrue則將電梯的狀態置為Opening

10Open:顯示電梯開門狀態每一t的狀態

      如果當前狀態不為Opening

            設置當前狀態為Opening,把record置為0,然后返回空

      如果record小於枚舉的值

             record自加,輸出“電梯開門中”,返回空

      如果是其他情況{

             record置為0,輸出“開門完成”,將當前狀態置為Opened

             如果JudgeOuttrue就調用OUT

             如果JudgeIntrue就調用IN

             JudgeClose判斷是否關門

       }

11IN:顯示哪些乘客進入電梯以及判定語句

如果電梯里人少於13{

             如果record小於枚舉值{

                    如果當前狀態為Opened{

                             record自加,遍歷等待隊列,並且加入判斷乘客當前樓層必須是等於floor才能             進入電梯

                     }

        如果當前狀態為In{

                      record自加,輸出“乘客正在進入電梯”,返回空

                     }

             }

     如果是等於枚舉值{

                     record置為0,並且將當前狀態置為Opened

              }

}

如果電梯里的人數大於13{

   輸出“電梯內人數已經達到最大值”,將當前狀態置為Closing

}

(12)JudgeClose:判斷當前電梯是否可以關門

如果當前狀態為Opened{

   如果record小於枚舉值{

                record自加,輸出“正在關門檢測”,然后返回空

          }

   如果等於枚舉值{

      輸出“關門檢測結束”

      如果當前狀態為Opened{

                        record置為0,調用Close函數

                 }

      否則 record置為0,並且返回空

            }

}

其他情況返回空

13Close:顯示電梯關門時每一t的狀態

如果record小於枚舉值{

        record自加,設置當前狀態為Closing,輸出“電梯正在關門中”

}

其他情況{

         record置為0,輸出“電梯已經關門”,設置當前狀態為Closed

         如果最大請求為floor{

                 如果電梯里外有人{

                         遍歷整個等待隊列

                         如果此時等待隊列有人發出請求

                         如果停止前電梯是向上走的

            則判斷是否在當前樓層之上或者就是當前樓層,如果滿足就設置當前狀態為Opening

                        如果停止前電梯是向下走的

                                則判斷是否在當前樓層之下或者就是當前樓層,如果滿足就設置當前狀態為Opening

                  }

                   如果電梯里外都沒人

                         設置當前狀態為Waiting,把Dir置為-1

            }

    如果最大請求不是當前樓層{

                  保持停止前電梯的狀態不變

            }

}

調用NoPassenger

14OUT:記錄乘客下電梯的每一t的狀態

如果record小於枚舉值{

   如果當前狀態為Opened{

                 record自加

                 如果電梯里有人要下電梯{

         根據數組DiantiLi來判定下去多少個乘客並且輸出下去時每一t狀態,並且設置當前狀態為Out,返回空

                  }

          }

          如果當前狀態為Out{

                  record自加,輸出“乘客正在下電梯”,返回空

           }

          其他情況則輸出“需要下的乘客都已下去”,record置為0,並且把當前狀態置為Opened

}

15JudgeIn:判斷是否可以進乘客

 如果All不為13{

          如果等待隊列不為空{

                   如果乘客是向上走的並且當前樓層在該層並且電梯之前的方向為向上

                            則允許進入,返回true

                   如果乘客是向下走的並且當前樓層在該層並且電梯之前的方向為向下

                           則允許進入,返回true

              }

  }

遍歷完若沒有返回true則此時返回false

16JudgeOut:判斷乘客是否可以出去

如果電梯里有人{

        數組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
passenger.h

 

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
elevator.h

 

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
Node.h

 

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 }
main.cpp

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM