2020-09-16QT寫一個(gè)簡單的元胞自動機(jī)(6)

目錄


  1. QTimer介紹
  2. QTimer使用
  3. 車輛運(yùn)動算法
  4. 最終模型展示

1. QTimer介紹


QTimer類為計(jì)時(shí)器提供了高級編程接口。要使用它,需要創(chuàng)建一個(gè)QTimer,將其timeout()信號連接到適當(dāng)?shù)牟宀酆瘮?shù),并調(diào)用start()。從那時(shí)起,它將以恒定的間隔發(fā)出timeout()信號,槽函數(shù)每收到一次信號就會執(zhí)行一次。


2. QTimer使用

2.1 單次觸發(fā)的計(jì)時(shí)器

QTimer可以弄個(gè)單次觸發(fā)的計(jì)時(shí)器


使用靜態(tài)cheng
//Example:
        QApplication app(argc, argv);
        QTimer::singleShot(600000, &app, SLOT(quit()));
              ...
        return app.exec();

2.2 按設(shè)置好的時(shí)間間隔觸發(fā)的計(jì)時(shí)器

        QTimer *timer = new QTimer(this); //設(shè)置父對象this,掛接到對象樹上,這樣程序結(jié)束時(shí)會自動釋放空間
        connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update));//將Qtimer定時(shí)發(fā)出的信號和槽函數(shù)連接起來,
//一旦收到timeout信號,就執(zhí)行槽函數(shù)
        timer->start(1000);//啟動計(jì)時(shí)器,并設(shè)置信號發(fā)出間隔1000ms

注:如果有多個(gè)計(jì)時(shí)器,通過TimerID來引用,這兒不說了

2.3 用計(jì)時(shí)器來更新場景

// .h定義計(jì)時(shí)器
QTimer *timer; //定義計(jì)時(shí)器

//.cpp 計(jì)時(shí)器在構(gòu)造函數(shù)中設(shè)置
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    timer= new QTimer(this);  // 在類的構(gòu)造函數(shù)中初始化timer
    connect(timer,&QTimer::timeout, this, &Widget::on_updateScene_timeout);
    //connect(發(fā)出信號的是誰,誰的哪種信號,誰接受信號,誰的什么函數(shù)接受信號)
    //on_updateScene_timeout是我自定義的槽函數(shù)

    timer->setInterval(100); //設(shè)置,每間隔100ms發(fā)出一次信號
}

計(jì)時(shí)器的啟動和暫停放在開始和暫停按鈕的槽函數(shù)中


image.png

3. 車輛運(yùn)動算法

sceneUpdate()函數(shù)需要考慮兩點(diǎn):1更新順序的問題,2如何更新

3.1更新順序我們可以隨機(jī)選取車輛更新,需要使用到洗牌算法

C++有個(gè)random_shuffle就可以隨機(jī)打亂,但qt用不了

#include <algorithm>
#include <vector>
#include <ctime>
......
    srand((unsigned int)time(NULL));
    vector<int> v;
    for(int i = 0 ; i < 10;i++)
    {
        v.push_back(i);
    }
random_shuffle(v.begin(), v.end());//順序打亂

洗牌算法實(shí)現(xiàn)

void Widget::sceneUpdate()
{
    // 1選擇,2 算法更新
    //洗牌算法,決定誰先更新,0-numV隨機(jī)排序再依次更新
    QVector<int> orderContainer;
    for (int i=0;i<numV;i++) {
        orderContainer.append(i); //初始化序列容器

    }
    //費(fèi)雪耶茲置亂算法
    for(int i=numV-1; i>0; i--)
    {
        int rand=QRandomGenerator::global()->bounded(0,i+1); //[0,i] 內(nèi)生成隨機(jī)整數(shù)
        if(rand==i) continue;
        orderContainer.swapItemsAt(i,rand); //QVector用來交換兩個(gè)位置元素的算法
    }
   qDebug()<<orderContainer;//測試使用


}

測試結(jié)果

算法參考鏈接

3.2 車輛更新

考慮車輛最大速度為5,使用NS模型對車輛進(jìn)行更新

#define speedMax 5 //車輛最大速度,單位元胞

話不多說,對于車輛的更新直接上代碼

       int speedA =(veContainer[order]->speed+1);
       int desiredSpeed = (speedA > speedMax) ? speedMax:speedA;
       int speedLast; //定義最終速度,用來放最后得到的速度

       //用desiredSpeed查看空間,也就是用此速度會不會遇到障礙
       int x= veContainer[order]->pos.x();
       int i = desiredSpeed;// 使用i來進(jìn)行車輛運(yùn)動遇障判斷
       while(i!=0)//每往車前判斷一格,就i自減,直到i為0
       {
           if(x==sL) x=0; //過了右側(cè)邊界,從左側(cè)繼續(xù)判斷
           if(scene[++x][sW/2]==1) break;//一旦有障礙,就跳出此循環(huán)
           i--;
       }
       if(i!=0){//上面的循環(huán),不正常退出
           speedLast=desiredSpeed -i;
       }
       else{
           speedLast=desiredSpeed;
       }

       // 確認(rèn)速度后進(jìn)行車輛的更新,包括(原來元胞的占有去掉,車輛對象的信息更新,占據(jù)新的元胞)
       //定義一個(gè)NotShowOccupied函數(shù),和showOccupied差不多,只是賦值由1變?yōu)?
       notShowOccupied(veContainer[order]->pos.x());
       veContainer[order]->speed=speedLast;

       int pos = veContainer[order]->pos.x()+speedLast; //原位置加速度得到現(xiàn)在的位置
       int posLast = (pos >= sL)? (pos-sL) : pos; //考慮右邊界,得到車輛最終速度
       veContainer[order]->pos.setX(posLast); //使用QPoint的方法來設(shè)置x坐標(biāo)
       showOccupied(posLast);//scene數(shù)組也更新一下

4. 最終模型展示

1

2
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容