第5篇 Qt实现十字路口交通灯控制系统(四)

1.主角车类Car

车是这个系统的主角,怎么去实现每隔一段时间车辆该不该走,或者是每隔一段时间就移动一段距离呢?这也用到了线程,即这个车类也继承了QThread类,这样的话车辆在生成之后,每隔一段时间就自己去判断自己该不该走或者什么时候转弯,什么时候等待前面的车辆。具体方法在run()函数里实现

1.1.宏常量

主要有一下12个,对应12条路的名字,上篇说过QString不能作为switch开关,所以就用这几个常量代替路名了。
#define S2W 0
#define S2N 1
#define S2E 2
#define N2E 3
#define N2S 4
#define N2W 5
#define E2S 6
#define E2W 7
#define E2N 8
#define W2N 9
#define W2E 10
#define W2S 11

1.2.属性

(1)int start_x, start_y;车的起始位置
刚开始车所在的位置。
(2)int end_x, end_y;//车的终点位置
车要走到的位置。
(3)int velocity;//车的速度
车子行驶过程中的速度。
(4)QString roadName;//路名
车子所在的路的名字。
(5)int roadNum;//路名对应的序号
车子所在路的序号。
(6)int safeLine;//车辆等红绿灯时的安全线
等待红灯时最前面一辆车的安全位置。
(7)bool turnLeft = false;
判断是否左转。
(8)bool turnRight = false;//右转记录,不是一开始就右转
判断是否右转。
(9)bool isAlive = true;//查看车子是否还存在
当车子到达终点位置时,值为假,即不在去判断它是否还继续行驶或者继续等红灯。
(10)QString carImg;//车自身图片
保存对应图片的路径。
(11)int rotationAngle;//转弯车辆的旋转角度
转弯的角度。
(12)int carWidth;//车的宽度;int carHeight;//车的高度
因为车子有横着和竖着的,而且转弯时大小会变,所以不设为静态变量。
(14)int turnline_x, turnline_y;//转弯时加的距离
因为我设计的界面地图,左转转弯线是奇数,而车子行驶速度是偶数,所以不设置的话转弯后悔压线行驶,因此加入两个变量。

1.3.操作

(1)QString getRoadName();
获取路名,主要在生成车子的时候使用。
(2)Car();
车的构造,车的90%都是在这里赋值的,当然你也可以写在外面,但也繁琐,这里面很多值都是固定给的,位置根据自己设计的地图大小规定,所在的路线是随机的。
(3)void run();
该函数有近300行的代码,代码实现也需要放在while循环里,其实看着多,但是很多都是重复的,不过你说他是重复的吧,它又有小的差别在里面,所以我索性就不去研究了,总的来说,车子有三种不同的行驶方法:直行4条路,右转4条路,左转4条路
这里每一种方法就举一个例子吧,四条路大同小异,但就是因为有小异,所以我就没有去想怎么设计出一样的函数来减少代码量了。
(1)直行:
如果车子没到达终点,
则判断车子所在路线红灯是否亮着,判断是否到达停车线,判断该车子前方一定距离是否有车。如果是红灯且到达停车线或者前面一定距离有车,则停车,否则继续行驶。
车子到达终点就删除该车辆。
(2)右转:
如果车子没有到达转弯线,则继续行驶。
否则右转,右转后知道达到终点停止,删除该车辆。
(3)左转:
如果车子没到达左转线,则按直行方式处理。
否则左转,直到到达终点停止,删除该车辆。
(4)int getStart_x();
获取车的当前位置横坐标。
(5)int getStart_y();
获取车的当前位置纵坐标。
(6)int getcarWidth();
获取车的宽度。
(7)int getcarHeight();
获取车的高度。
(8)QString getcarImg();
获取该车辆对应的图片的路径。
(9)bool isTurnLeft();
判断是否左转。
(10)bool isTurnRight();
判断是否右转。
(11)int getrotationAngle();
返回转弯的角度。
(12)int getTurnline_x();
返回转弯时要处理的横坐标添加或减少的值。
(13)int getTurnline_y();
返回转弯时要处理的纵坐标添加或者减少值。

1.4.信号

(1)void updateMain();
每次检测后发出界面重绘请求信号。

1.5.头文件

#ifndef CAR_H
#define CAR_H

#include <QObject>
#include <QString>
#include <QThread>
#include <QVector>

#define S2W 0
#define S2N 1
#define S2E 2
#define N2E 3
#define N2S 4
#define N2W 5
#define E2S 6
#define E2W 7
#define E2N 8
#define W2N 9
#define W2E 10
#define W2S 11

class Car : public QThread
{
    Q_OBJECT
public:
    explicit Car();
    void run();
signals:
    void updateMain();
public slots:
public:
    QString getRoadName();
    int getStart_x();
    int getStart_y();
    int getcarWidth();
    int getcarHeight();
    QString getcarImg();
    bool isTurnLeft();
    bool isTurnRight();
    int getrotationAngle();
    int getTurnline_x();
    int getTurnline_y();
private:
    int start_x, start_y;//车的起始位置
    int end_x, end_y;//车的终点位置
    int velocity;//车的速度
    QString roadName;//路名
    int roadNum;
    int safeLine;//车辆等红绿灯时的安全线
    bool turnLeft = false;
    bool turnRight = false;//右转记录,不是一开始就右转
    bool isAlive = true;//查看车子是否还存在
    QString carImg;//车自身图片
    int rotationAngle;//转弯车辆的旋转角度
    int carWidth;//车的宽度
    int carHeight;//车的高度
    int turnline_x;
    int turnline_y;
};
#endif // CAR_H

1.6.源文件

#include "car.h"

#include "map.h"
#include <QtGlobal>
#include <QTime>
#include <QDebug>
#include <QByteArray>

Car::Car()
{
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    this->roadNum = qrand()%12;
    this->roadName=Map::road[this->roadNum];//车所在道路的选择
    this->velocity = 20;
    this->isAlive = true;
    this->turnLeft = false;
    this->turnRight = false;
    this->rotationAngle = 0;
    this->turnline_x = 0;
    this->turnline_y = 0;

    QByteArray ba = this->roadName.toLatin1();
    char *direction = ba.data();
    switch(direction[0]){
        case 'S':
            this->carImg=Map::car_img[0][qrand()%2];
            this->safeLine=440;carWidth = 30;carHeight = 50;
            switch (direction[2]){
                case 'W':
                    start_x=420;start_y=600;end_x=-60;end_y=250;
                    break;
                case 'N':
                    start_x=450;start_y=600;end_x=450;end_y=-60;
                    break;
                case 'E':
                    start_x=480;start_y=600;end_x=860;end_y=380;
                    break;
            }
            break;
        case 'N':
            this->carImg=Map::car_img[1][qrand()%2];
            this->safeLine=110;carWidth = 30;carHeight = 50;
            switch (direction[2]){
                case 'W':
                    start_x=290;start_y=-50;end_x=-60;end_y=190;break;
                case 'S':
                    start_x=320;start_y=-50;end_x=320;end_y=660;break;
                case 'E':
                    start_x=350;start_y=-50;end_x=860;end_y=300;break;
            }
            break;
        case 'E':
            this->carImg=Map::car_img[2][qrand()%2];
            this->safeLine=540;carWidth = 50;carHeight = 30;
            switch (direction[2]){
                case 'W':
                    start_x=800;start_y=220;end_x=-50;end_y=220;break;
                case 'N':
                    start_x=800;start_y=190;end_x=480;end_y=-50;break;
                case 'S':
                    start_x=800;start_y=250;end_x=370;end_y=660;break;
            }
            break;
        case 'W':
            this->carImg=Map::car_img[3][qrand()%2];
            this->safeLine=210;carWidth = 50;carHeight = 30;
            switch (direction[2]){
                case 'S':
                    start_x=-50;start_y=380;end_x=290;end_y=660;break;
                case 'N':
                    start_x=-50;start_y=320;end_x=400;end_y=-60;break;
                case 'E':
                    start_x=-50;start_y=350;end_x=860;end_y=350;break;
            }
            break;
    }
    delete direction;
}

void Car::run(){
    while(this->isAlive){
        emit updateMain();
        QThread::msleep(64);
        bool redlamp = false;//判断是否红灯
        bool stopline = false;//判断是否到达安全线
        bool befor_hava_car = false;//判断前面是否有车

        switch(this->roadNum) {
            //直走路线
            case S2N://南直走北;正常
                if(this->start_y >= this->end_y){
                    redlamp = !Map::nlampMiddle.getStatus();
                    stopline = (this->start_y == this->safeLine);
                    //判断车距
                    int myIndex = Map::listS2N.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((this->start_y - Map::listS2N.at(myIndex-1)->start_y) <= 60)){
                        befor_hava_car = true;
                    }
                    if((stopline && redlamp) || befor_hava_car){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_y -= this->velocity;
                }
                else{
                    Map::listAll.remove(Map::listAll.indexOf(this,0));
                    Map::listS2N.remove(0);
                    this->isAlive=false;//此线程作废
                }
                break;
            case N2S://北直走南;正常
                if(this->start_y <= this->end_y){
                    redlamp = !Map::nlampMiddle.getStatus();
                    stopline = (this->start_y == this->safeLine);
                    //判断车距
                    int myIndex = Map::listN2S.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((Map::listN2S.at(myIndex-1)->start_y - this->start_y) <= 60)){
                        befor_hava_car = true;
                    }
                    if((stopline && redlamp) || befor_hava_car){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_y += this->velocity;
                }
                else{
                    Map::listAll.remove(Map::listAll.indexOf(this,0));
                    Map::listN2S.remove(0);
                    this->isAlive=false;//此线程作废
                }
                break;
            case E2W://东直走西;正常
                if(this->start_x >= this->end_x){
                    redlamp = !Map::wlampMiddle.getStatus();
                    stopline = (this->start_x == this->safeLine);
                    //判断车距
                    int myIndex = Map::listE2W.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((this->start_x - Map::listE2W.at(myIndex-1)->start_x) <= 60)){
                        befor_hava_car = true;
                    }
                    if((stopline && redlamp) || befor_hava_car){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_x -= this->velocity;
                }
                else{
                    Map::listAll.remove(Map::listAll.indexOf(this,0));
                    Map::listE2W.remove(0);
                    this->isAlive=false;//此线程作废
                }
                break;
            case W2E://西直走东;正常
                if(this->start_x <= this->end_x){
                    redlamp = !Map::wlampMiddle.getStatus();
                    stopline = (this->start_x == this->safeLine);
                    //判断车距
                    int myIndex = Map::listW2E.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((Map::listW2E.at(myIndex-1)->start_x - this->start_x) <= 60)){
                        befor_hava_car = true;
                    }

                    if((stopline && redlamp) || befor_hava_car){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_x += this->velocity;
                }
                else{
                    Map::listAll.remove(Map::listAll.indexOf(this,0));
                    Map::listW2E.remove(0);
                    this->isAlive=false;//此线程作废
                }
                break;
            //左转线路
            case S2W://南左转西;正常
                if(this->start_y > this->end_y){
                    redlamp = !Map::nlampLeft.getStatus();
                    stopline = (this->start_y == this->safeLine);
                    //判断车距
                    int myIndex = Map::listS2W.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((this->start_y - Map::listS2W.at(myIndex-1)->start_y) <= 60)){
                        befor_hava_car = true;
                    }
                    if((stopline && redlamp) || (befor_hava_car && (this->start_y > this->safeLine))){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_y -= this->velocity;
                }
                else{
                    this->carWidth = 50;
                    this->carHeight = 30;
                    this->turnline_y = 10;
                    this->turnLeft = true;
                    this->start_x -= this->velocity;
                    if(this->start_x <= this->end_x){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listS2W.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
            case N2E://北左转东;正常
                if(this->start_y < this->end_y){
                    redlamp = !Map::slampLeft.getStatus();
                    stopline = (this->start_y == this->safeLine);
                    //判断车距
                    int myIndex = Map::listN2E.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((Map::listN2E.at(myIndex-1)->start_y - this->start_y) <= 60)){
                        befor_hava_car = true;
                    }
                    if((stopline && redlamp) || (befor_hava_car && (this->start_y < this->safeLine))){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_y += this->velocity;
                }
                else{
                    this->carWidth = 50;
                    this->carHeight = 30;
                    this->turnline_y = 10;
                    this->turnLeft = true;
                    this->start_x += this->velocity;
                    if(this->start_x >= this->end_x){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listN2E.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
            case E2S://东左转南;正常
                if(this->start_x > this->end_x){
                    redlamp = !Map::wlampLeft.getStatus();
                    stopline = (this->start_x == this->safeLine);
                    //判断车距
                    int myIndex = Map::listE2S.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((this->start_x - Map::listE2S.at(myIndex-1)->start_x) <= 60)){
                        befor_hava_car = true;
                    }
                    if((stopline && redlamp) || (befor_hava_car && (this->start_x > this->safeLine))){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_x -= this->velocity;
                }
                else{
                    this->carWidth = 30;
                    this->carHeight = 50;
                    this->turnLeft = true;
                    this->turnline_x = -10;
                    this->start_y += this->velocity;
                    if(this->start_y >= this->end_y){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listE2S.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
            case W2N://西左转北 ;正常
                if(this->start_x < this->end_x){
                    redlamp = !Map::elampLeft.getStatus();
                    stopline = (this->start_x == this->safeLine);
                    //判断车距
                    int myIndex = Map::listW2N.indexOf(this);//定义一个变量来保存this(自己)在集合中的位置
                    if(myIndex > 0 && ((Map::listW2N.at(myIndex-1)->start_x - this->start_x) <= 60)){
                        befor_hava_car = true;
                    }
                    if((stopline && redlamp) || (befor_hava_car && (this->start_x < this->safeLine))){
                        this->velocity = 0;
                    }
                    else{
                        this->velocity = 20;
                    }
                    this->start_x += this->velocity;
                }
                else{
                    this->carWidth = 30;
                    this->carHeight = 50;
                    this->turnLeft = true;
                    this->turnline_x = 10;
                    this->start_y -= this->velocity;
                    if(this->start_y <= this->end_y){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listW2N.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
            //右转路线
            case S2E://南右转东;正常
                if(this->start_y > this->end_y){
                    this->start_y -= this->velocity;
                }
                else{
                    this->turnRight = true;
                    this->carWidth = 50;this->carHeight = 30;
                    this->start_x += this->velocity;
                    if(this->start_x >= this->end_x){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listS2E.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
            case N2W://北右转西;正常
                if(this->start_y < this->end_y){
                    this->start_y += this->velocity;
                }
                else{
                    this->turnRight = true;
                    this->carWidth = 50;this->carHeight = 30;
                    this->start_x -= this->velocity;
                    if(this->start_x <= this->end_x){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listN2W.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
            case E2N://东右转北;正常
                if(this->start_x > this->end_x){
                    this->start_x -= this->velocity;
                }
                else{
                    this->turnRight = true;
                    this->carWidth = 30;this->carHeight = 50;
                    this->start_y -= this->velocity;
                    if(this->start_y <= this->end_y){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listE2N.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
            case W2S://西右转南;正常
                if(this->start_x < this->end_x){
                    this->start_x += this->velocity;
                }
                else{
                    this->turnRight = true;
                    this->carWidth = 30;this->carHeight = 50;
                    this->start_y += this->velocity;
                    if(this->start_y >= this->end_y){
                        Map::listAll.remove(Map::listAll.indexOf(this,0));
                        Map::listW2S.remove(0);
                        this->isAlive=false;
                    }
                }
                break;
        }//switch语句
    }
}

QString Car::getRoadName(){
    return this->roadName;
}

int Car::getStart_x(){
    return this->start_x;
}

int Car::getStart_y(){
    return this->start_y;
}

int Car::getcarWidth(){
    return this->carWidth;
}

int Car::getcarHeight(){
    return this->carHeight;
}

QString Car::getcarImg(){
    return this->carImg;
}

bool Car::isTurnLeft(){
    return this->turnLeft;
}

bool Car::isTurnRight(){
    return this->turnRight;
}

int Car::getrotationAngle(){
    return this->rotationAngle;
}

int Car::getTurnline_x()
{
    return this->turnline_x;
}

int Car::getTurnline_y()
{
    return this->turnline_y;
}

2.车的控制类ControlCar

该类看着想多余的,但是是我想了两天才想出来的,所以舍不得删它,这个Qt在并发生成车的这一方面不好实现,所以加了这个,值得说明的是,它是一个线程类,继承于QThread类主要作用在于,每秒钟发出一个生成车的信号,让生成车的相关类生成车。

2.1.操作

(1)void run();
在while循环里,每隔一秒发出创建车的信号。

2.2.信号

(1)void create();
请求相关类创建车子。

2.3.头文件

#ifndef CONTROLCAR_H
#define CONTROLCAR_H

#include <QObject>
#include <QThread>

class ControlCar : public QThread
{
    Q_OBJECT
public:
    explicit ControlCar();
    void run();

signals:
    void create();

public slots:
};

#endif // CONTROLCAR_H

2.4.源文件

#include "controlcar.h"

#include "car.h"
#include "map.h"

ControlCar::ControlCar()
{

}

void ControlCar::run(){
    while(true){
        QThread::msleep(1000);
        emit create();
    }
}

3.结语

如果有时间的话,就想办法改一改代码,那个一个函数里300行代码很不好,其实是借鉴过来的,已经减少了几百行了。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以帮您解答。如果您想在Qt实现LED交通灯的亮灭,可以通过以下步骤进行: 1. 创建一个新的Qt工程,并添加三个QLabel控件,分别代表红灯、黄灯和绿灯。 2. 设置QLabel的背景色,分别设置红色、黄色和绿色。 3. 在Qt使用QTimer类,定时器每隔一段时间就切换灯的状态。例如,红灯亮10秒,黄灯亮3秒,绿灯亮15秒,然后再切换到红灯。 4. 在QTimer的槽函数,根据当前灯的状态,改变对应QLabel的背景色,从而实现LED交通灯的亮灭。 以下是一个简单的示例代码: ``` #include <QtWidgets> class TrafficLight : public QWidget { public: TrafficLight(QWidget *parent = nullptr) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(redLabel = new QLabel); layout->addWidget(yellowLabel = new QLabel); layout->addWidget(greenLabel = new QLabel); redLabel->setFixedSize(50, 50); yellowLabel->setFixedSize(50, 50); greenLabel->setFixedSize(50, 50); redLabel->setAutoFillBackground(true); yellowLabel->setAutoFillBackground(true); greenLabel->setAutoFillBackground(true); redLabel->setStyleSheet("background-color: red;"); yellowLabel->setStyleSheet("background-color: gray;"); greenLabel->setStyleSheet("background-color: gray;"); timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &TrafficLight::changeLight); timer->start(1000); } private: QLabel *redLabel; QLabel *yellowLabel; QLabel *greenLabel; QTimer *timer; int state = 0; void changeLight() { switch (state) { case 0: redLabel->setStyleSheet("background-color: red;"); yellowLabel->setStyleSheet("background-color: gray;"); greenLabel->setStyleSheet("background-color: gray;"); state = 1; timer->start(10000); break; case 1: redLabel->setStyleSheet("background-color: gray;"); yellowLabel->setStyleSheet("background-color: yellow;"); greenLabel->setStyleSheet("background-color: gray;"); state = 2; timer->start(3000); break; case 2: redLabel->setStyleSheet("background-color: gray;"); yellowLabel->setStyleSheet("background-color: gray;"); greenLabel->setStyleSheet("background-color: green;"); state = 3; timer->start(15000); break; case 3: redLabel->setStyleSheet("background-color: red;"); yellowLabel->setStyleSheet("background-color: gray;"); greenLabel->setStyleSheet("background-color: gray;"); state = 1; timer->start(10000); break; } } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); TrafficLight light; light.show(); return app.exec(); } ``` 运行上述代码,您将看到一个简单的LED交通灯示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大唐不良猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值