C++项目——基于QT的电梯仿真系统

某贸易中心共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());
    }
}