目錄
- QTimer介紹
- QTimer使用
- 車輛運(yùn)動算法
- 最終模型展示
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