这个程序是我上研二上学期时下一届师弟师妹们的面向对象课程大作业,当时我正好看过两三本 C++ 书籍,虽然忙着项目,但还是忙里偷闲检验了下自己。从设计到实现,耗时一周左右,完成于 2013 年年底。

虽是面向对象课程作业,但是只用到了“封装”,没有触及“继承”和“多态”,只是基于对象而已。

以前的做一个东西都会查阅不少资料,这次纯粹是靠想象了。

源码托管在 Github 上:点击进入链接,命名遵循“匈牙利命名法”尽量做到“self-documenting”,当然也有必要的注释

可执行程序:点击进入链接

题目(完整pdf):

设计说明:

红绿灯类,保存灯的颜色、总持续时间、当前倒计时等,操作倒计时和颜色转换;

用一个枚举类型保存道路端点;

路径类,用一个 map 保存所有路径端点及其对应的折点,可通过路线端点获取其对应的路线折点;

车辆类,随机产生车辆时,就随机设置其颜色和行驶路线,类中保存车辆行驶路线端点、当前行驶区间、当前位置,可获取车辆状态或更新位置。

道路类,这是一个二维矩阵,安插了多个红绿灯,每一点都有一个标记,如果有车辆在此位置则激活。

仿真图示:定时扫描道路类中的所有点,获取对应的交通灯或车辆,然后绘制到界面上。

坐标假设:原点在左上角,向右为 x 轴正方向,向下为 y 轴正方向。

重难点:
1、红绿灯更替规则,封装到红绿灯类内从而得到简化;
2、复杂的转弯、让道规则,通过保存路线解决;
3、更新 1 秒:

 // 车辆行进 1 秒
void CTrafficSimulationDlg::MoveOneSec(CMyPoint& ptCarPos)
{
for (auto it = m_vecCars.begin(); it != m_vecCars.end(); ++it) {
if (it->GetPos() == ptCarPos) { // 在车辆集合中找到该车辆
pair<CMyPoint, CMyPoint> pairCurInterval = it->GetCurInterval();
CMyPoint ptFrom = pairCurInterval.first;
CMyPoint ptTo = pairCurInterval.second; if (ptTo.GetX() == ptCarPos.GetX()
&& ptTo.GetY() == ptCarPos.GetY()) { // 行驶到一个区间的终点 vector<CMyPoint>& vecTurningPoints
= m_paths.GetTurningPoints(it->GetPath()); if (it->m_nPtIdx < vecTurningPoints.size()) { // 更新区间
ptFrom = ptTo;
ptTo = vecTurningPoints.at(it->m_nPtIdx++);
it->SetCurInterval(ptFrom, ptTo);
}
else { // 行驶到路线的终点,在车辆集合中删除该车
m_vecCars.erase(it);
m_roadMain.DeactivatePoint(ptCarPos);
return ;
}
} CMyPoint ptNewCarPos;
if (ptFrom.GetX() != ptTo.GetX()) { // 沿着 x 轴行驶
int n = ptTo.GetX() - ptFrom.GetX() > ? +: -;
ptNewCarPos = CMyPoint(ptCarPos.GetX()/gc_nScalar+n, ptCarPos.GetY()/gc_nScalar);
}
else { // 沿着 y 轴行驶
int n = ptTo.GetY() - ptFrom.GetY() > ? +: -;
ptNewCarPos = CMyPoint(ptCarPos.GetX()/gc_nScalar, ptCarPos.GetY()/gc_nScalar+n);
} bool bGreen = true;
if ( ptNewCarPos != ptTo // 如果不转弯,则查看红绿灯
&& m_setLightPos.find(ptCarPos) != m_setLightPos.end() ) // 遇到红绿灯
bGreen = m_roadMain.IsGreen(ptCarPos); // 车辆行进 1 秒
if ( bGreen && !m_roadMain.IsPointActivated(ptNewCarPos) ) {
m_roadMain.DeactivatePoint(ptCarPos);
m_roadMain.ActivatePoint(ptNewCarPos);
it->SetPos(ptNewCarPos);
} return ; // 更新完毕
}
}
}

是否要更换行驶区间(当前车辆位置是否与区间终点重合)、是否行驶到尽头(删除车辆);
判断当前区间是水平的(区间 x 轴坐标不相等)还是竖直的(区间 y 轴坐标不相等),然后决定沿着 x 或 y 的正方向还是反方向;
通过判断是否在路口转弯(新车辆位置与区间终点重合),从而决定是否忽略红绿灯。

运行截图:

双十字路口交通仿真程序(VS2010+MFC)的更多相关文章

  1. VS2010/MFC编程入门之五(MFC消息映射机制概述)

    VS2010/MFC编程入门之五(MFC消息映射机制概述)-软件开发-鸡啄米 http://www.jizhuomi.com/software/147.html 上一讲鸡啄米为大家简单分析了MFC应用 ...

  2. VS2010/MFC编程入门之四(MFC应用程序框架分析)

    VS2010/MFC编程入门之四(MFC应用程序框架分析)-软件开发-鸡啄米 http://www.jizhuomi.com/software/145.html   上一讲鸡啄米讲的是VS2010应用 ...

  3. VS2010/MFC编程入门之三(VS2010应用程序工程中文件的组成结构)

    VS2010/MFC编程入门之三(VS2010应用程序工程中文件的组成结构)-软件开发-鸡啄米 http://www.jizhuomi.com/software/143.html   鸡啄米在上一讲中 ...

  4. VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)

    VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)-软件开发-鸡啄米 http://www.jizhuomi.com/software/141.html   上一讲中讲了VS20 ...

  5. VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)

    原文地址: VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)-软件开发-鸡啄米 http://www.jizhuomi.com/software/139.html   上一讲中鸡 ...

  6. VS2010/MFC编程入门教程之目录和总结

    鸡啄米的这套VS2010/MFC编程入门教程到此就全部完成了,虽然有些内容还未涉及到,但帮助大家进行VS2010/MFC的入门学习业已足够.以此教程的知识为基础,学习VS2010/MFC较为深入的内容 ...

  7. 《VS2010/MFC编程入门教程》——读书笔记

    推荐两个比较好的学习网站:http://v.dxsbb.com/jisuanji/555/ http://www.jizhuomi.com/software/257.html MFC全称Microso ...

  8. VS2010/MFC编程入门之五十二(Ribbon界面开发:创建Ribbon样式的应用程序框架)

    上一节中鸡啄米讲了GDI对象之画刷CBrush,至此图形图像的入门知识就讲完了.从本节开始鸡啄米将为大家带来Ribbon界面开发的有关内容.本文先来说说如何创建Ribbon样式的应用程序框架. Rib ...

  9. VS2010/MFC编程入门之五十(图形图像:GDI对象之画笔CPen)

    上一节中鸡啄米讲了CDC类及其屏幕绘图函数,本节的主要内容是GDI对象之画笔CPen. GDI对象 在MFC中,CGdiObject类是GDI对象的基类,通过查阅MSDN我们可以看到,CGdiObje ...

随机推荐

  1. delphi局域网Ping各主机方法及设置本地ip方法

    1. 首先引用winsock单元 function PingHost(HostIP: String): Boolean; type PIPOptionInformation=^TIPOptionInf ...

  2. Oracle中索引名称的唯一性

    数据库索引处理是遇到的一点问题,简单记录下 oracle的规定,在同一个SCHEMA下的对象是不能用相同的名字命名的,一般创建索引名用“表名_字段名”,这样能很快知道这个索引,是属于哪个表的. col ...

  3. MySql存储过程、函数

    存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...

  4. hive 安装警告 WARN conf.HiveConf: HiveConf of name hive.metastore.local does not exist

    解决方法: 在0.10  0.11或者之后的HIVE版本 hive.metastore.local 属性不再使用. 在配置文件里面:  <property>  <name>hi ...

  5. (1)sql server 同网段复制

    转自:https://blog.csdn.net/hliq5399/article/details/51678774(文末有复制系列文章链接) 一.背景 在复制的运用场景中,事务发布是使用最为广泛的, ...

  6. IDEA 跑spring项目找不到get,set的问题

    @Autowired的用法和作用 这个注解就是spring可以自动帮你把bean里面引用的对象的setter/getter方法省略,它会自动帮你set/get. iDEA下安装lombok这个插件就可 ...

  7. Latex技巧:在图表序号中加入章节号(实现诸如“图1.1.2”这样的图表序号)

    平时看书经常看到"图1.2"这样的编号,含义是第1章的第2幅插图:或者"图1.1.2",含义是第1章第1节的第2幅插图.而在LaTeX中如果直接插图的话只会显示 ...

  8. 如何删除github中的仓库?

    使用Github管理项目确实有些好处,但删除仓库(repositories)确实不太好找到. 首先进入要删除的仓库,点击右下角的“settings” 然后拉到页面最下面在danger zone 按“d ...

  9. 剑指offer 面试17题

    面试17题: 题目:打印从1到最大的n位数 题:输入数字n,按顺序打印出从1到最大的n位十进制数,比如输入3,则打印出1.2.3一直到最大的3位数999. 解题思路:需要考虑大数问题,这是题目设置的陷 ...

  10. $SublimeText2常用快捷键

    1.删除一行:ctrl + shift + K2.替换:ctrl + H3.设置书签:Ctrl+F2设置书签F2 下一个书签Shift+F2上一个书签4.查找:ctrl + F 查找F3 查找下一个s ...