C++实现路口交通灯模拟系统完整攻略
介绍
本系统利用C++语言实现,模拟了路口交通灯的控制,包括车辆的停止和通行,交通信号的改变等。系统结构清晰,代码简单易懂,适合初学者学习C++语言的基础和面向对象编程的实现。
设计思路
本系统的设计思路涉及到面向对象编程的基本思想。首先将路口、红绿灯、车辆等实体抽象为类,通过类的成员函数实现对对象的控制。同时,本系统利用时钟实现交通信号的周期变化和车辆通行的延迟等功能。
功能设计
- 系统启动
- 输入交通信号灯的周期
- 车辆按照随机时间在四个方向出发
- 如果红绿灯是绿色,则车辆可以通过,否则必须停止等待
- 每次绿灯持续时间结束后,交通信号灯会自动变成红色,另一个方向的红绿灯变为绿色,如此往复。
代码实现
红绿灯类
首先定义红绿灯类,由于红灯和绿灯的状态只能存在一个,因此用枚举类型定义状态。
class TrafficLight
{
public:
enum LightState {Green, Red};
LightState State;
void Change() { State = (State == Green ? Red : Green); }
TrafficLight(): State(Red) {}
};
车辆类
车辆类包含了车辆的出发时间和方向,可以定义一个时间戳表示出发时间,并设置一个随机数生成函数。在模拟时钟滴答的时候,我们需要获取当前时间并让所有车辆检查自己是否可以通过路口,如果不能则停止。
class Car
{
public:
int TimeStamp;
Direction Dir;
int GetRand(int min, int max) { return min + rand() % (max - min + 1); }
Car():TimeStamp(0), Dir(North) {}
bool CanPass(const TrafficLight& tl, int currtime)
{
if (tl.State == TrafficLight::Red)
{
return false;
}
if (currtime - TimeStamp < 10)
{
return false;
}
return true;
}
};
路口类
路口类包含四个方向的车辆列表和两个红绿灯。
class RoadIntersection
{
public:
vector<Car> Cars[4];
TrafficLight Light[2];
void Tick(int currtime);
void Print();
};
在路口类中定义了模拟时钟滴答的函数Tick(),每滴答一次,会让红绿灯变化,并检查车辆是否可以通过路口。
void RoadIntersection::Tick(int currtime)
{
// 红绿灯变换
if (currtime % Light[0].Cycle == 0)
{
Light[0].Change();
Light[1].Change();
}
// 车辆检测
for (int i = 0; i < 4; i++)
{
for (auto& car : Cars[i])
{
if (car.CanPass(Light[i/2], currtime))
{
car.TimeStamp = currtime;
Cars[i].erase(std::find(Cars[i].begin(), Cars[i].end(), car));
Cars[Next(i)].push_back(car);
}
}
}
}
在Tick()中,我们用STL库中的std::find查找车辆是否在当前方向,如果车辆不能通过,则从当前方向删除;如果车辆可以通过,则产生一个新的时间戳,然后将车辆从当前方向删除,并将车辆添加到下一个方向。
接着是交通信号灯的控制:
class TrafficLight
{
public:
void Change() { State = (State == Green ? Red : Green); }
TrafficLight(): State(Red), Cycle(20) {}
LightState State;
int Cycle;
};
定义了两个信号灯,灯的周期是20个单位时间。在滴答中,由第一个信号灯控制车辆行驶的方向,由第二个信号灯控制其它方向的车辆通行。如果是绿色状态,可以直接行驶,否则,要等待红绿灯变为绿色。
class RoadIntersection
{
public:
void Tick(int currtime);
};
可以定义Tick()函数,实现模拟时钟的滴答:
void RoadIntersection::Tick(int currtime)
{
// 红绿灯变换
if (currtime % Light[0].Cycle == 0)
{
Light[0].Change();
Light[1].Change();
}
// 车辆检测
for (int i = 0; i < 4; i++)
{
for (auto& car : Cars[i])
{
if (car.CanPass(Light[i/2], currtime))
{
car.TimeStamp = currtime;
Cars[i].erase(std::find(Cars[i].begin(), Cars[i].end(), car));
Cars[Next(i)].push_back(car);
}
}
}
}
主程序
主程序实现了输入交通灯的周期,和一些车辆的初始化。
int main()
{
srand(time(nullptr));
int Cycle = 20;
RoadIntersection intersection;
int cnt = 0;
while (cnt < 20)
{
intersection.Tick(cnt++);
if (cnt % Cycle == 0)
{
for (int i = 0; i < 4; i++)
{
int ncars = intersection.Lights[i/2].State == TrafficLight::Green ?
intersection.GetRand(1, 10) : 0;
for (int j = 0; j < ncars; j++)
{
intersection.Cars[i].push_back(Car());
}
}
}
intersection.Print();
std::this_thread::sleep_for(chrono::milliseconds(200));
}
return 0;
}
示例说明:
假如我们要模拟一个周期为20的红绿灯定时器,主程序每经过20个单位时间,交通信号灯的第一个信号灯会变色,并且每个方向上的车辆会出发,通过或停止。因此,main()函数里循环计时器定时器,驱动系统滴答。每个周期后,需要获取红绿灯的状态,如果是绿色,随机关数以生成车辆,并将其加入到当前方向的列表中。最后输出所有车辆的状态,用std::this_thread::sleep_for防止程序运行过快。
示例2:
我们可以设置目标物理系统有不同时间点的行为要求。例如:某时刻,南北方向需要有10辆车通过路口,而东西方向只需1辆车通过路口。可以在主程序中按行进方向,决定车辆的行进数量。
int main()
{
srand(time(nullptr));
int Cycle = 20;
RoadIntersection intersection;
int cnt = 0;
while (cnt < 20)
{
intersection.Tick(cnt++);
if (cnt % Cycle == 0)
{
for (int i = 0; i < 4; i++)
{
int ncars = 0;
if (i == North || i == South)
{
ncars = intersection.Lights[0].State == TrafficLight::Green ?
intersection.GetRand(1, 10) : 0;
}
else
{
ncars = intersection.Lights[1].State == TrafficLight::Green ?
intersection.GetRand(1, 2) : 0;
}
for (int j = 0; j < ncars; j++)
{
intersection.Cars[i].push_back(Car());
}
}
}
intersection.Print();
std::this_thread::sleep_for(chrono::milliseconds(200));
}
return 0;
}
总结
本文介绍了如何使用C++实现一个简单的路口交通灯模拟系统。通过理解本系统的代码,能够学习到C++语言的基本语法和面向对象编程的基本思想。同时,对于系统设计的优化,也会有一定的了解。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++实现路口交通灯模拟系统 - Python技术站