C++实现路口交通灯模拟系统

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技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C++设计模式之享元模式(Flyweight)

    C++设计模式之享元模式(Flyweight)攻略 概述 享元模式是一种结构型设计模式,它的主要目标是减少对象的数量,通过尽可能多的与其他相似对象共享来最小化内存占用和计算量。 在享元模式中,所有共享对象都以一个单一的实例存在于内存中,因此系统需要考虑识别这些对象以便正确地重用已经存在的实例,而不是创建新的对象。具体实现时,享元模式通过将需要重复使用的属性划…

    C 2023年5月22日
    00
  • C程序 打印半直角号码金字塔图案

    C程序 打印半直角号码金字塔图案 使用攻略 程序实现功能 本程序是用C语言实现打印半直角号码金字塔图案,可根据输入的行数打印出不同大小的金字塔图案,程序较为简单易懂,适合初学者学习练手。 使用攻略 本程序主要使用的控制语句是循环,包括for循环和while循环,同时也运用了条件判断语句和输出语句。以下是本程序代码的详细解析: 用户输入要打印的金字塔的行数(c…

    C 2023年5月9日
    00
  • JSON在Java中的使用方法实例

    下面是JSON在Java中的使用方法实例的详细攻略: 什么是JSON JSON是一种轻量级的数据交换格式,全称为JavaScript Object Notation。它是一种易于读写的文本格式,可与几乎所有编程语言一起使用,包括Java。 Java中的JSON库 Java中有多个库可以用于处理JSON,其中最流行的库是GSON和Jackson。这里我们以GS…

    C 2023年5月23日
    00
  • C++中的RAII机制详解

    C++中的RAII机制详解 什么是RAII RAII是一种资源获取即初始化的技术,它能够确保在使用完资源后,自动释放资源。RAII在C++中是一种很常见的技术,可以被用于管理内存、文件句柄、互斥锁等各种资源。 RAII的实现方式 RAII的实现方式是通过C++的构造函数和析构函数来实现的。C++中的构造函数用于初始化对象的内部状态,而析构函数则在对象被销毁时…

    C 2023年5月22日
    00
  • 深入数据库通用的连接方式详解

    深入数据库通用的连接方式详解 在使用数据库时,我们需要连接数据库才能操作数据库。下面将介绍一些通用的连接方式,其中包括主流的两种数据库:MySQL和PostgreSQL。 MySQL连接方式 MySQL连接方式主要有三种:使用命令行连接、使用图形化界面连接和使用编程语言连接。下面将对三种连接方式进行介绍。 使用命令行连接 使用命令行连接MySQL需要使用My…

    C 2023年5月22日
    00
  • iOS底层探索之自动释放池原理解析

    iOS底层探索之自动释放池原理解析 什么是自动释放池 自动释放池是一种机制,用于在Objective-C中管理内存。具体来说,自动释放池是一个用于暂时存储不需要的Objective-C对象的容器,当自动释放池被销毁时,它所包含的所有对象都被发送一条autorelease消息。autorelease消息会将这些对象的引用计数减一,如果引用计数变为0,对象会立即…

    C 2023年5月23日
    00
  • 提高C程序效率的10种有效方法

    提高C程序效率的10种有效方法 在编写C程序时,有时我们需要注重程序的效率,尤其是在处理大数据、复杂算法和高性能计算等场景下更是如此。下面是10种提高C程序效率的有效方法: 1. 使用指针而不是数组下标 指针和数组下标都可以用来访问数组元素,但是指针更加高效。数组下标需要进行大小检查,并且要在内存中查找元素的位置;而指针直接指向元素的地址,更加快速高效。例如…

    C 2023年5月23日
    00
  • 详解python 3.6 安装json 模块(simplejson)

    安装json模块(simplejson)可以帮助我们在Python 3.6中更方便地处理JSON数据格式。下面是安装和使用simplejson的完整攻略。 安装simplejson模块 要安装simplejson模块,可以使用pip命令在控制台进行安装。输入以下命令: pip install simplejson 如果你使用的是Python 3.6及以上版本…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部