第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行代码很不好,其实是借鉴过来的,已经减少了几百行了。