学号1120161789
代码仓库地址:subway
结对搭档博客地址:https://blog.csdn.net/V5ZSQ/article/details/86554215?tdsourcetag=s_pctim_aiomsg
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 30 | |
Development | 开发 | ||
· Analysis | · 需求分析(包括学习新技术) | 180 | |
· Design Spec | · 生成设计文档 | 60 | |
· Design Review | · 设计复审(和同事审核设计文档) | 60 | |
· Coding Standard | · 代码规范(为目前的开发制定合适的规范) | 30 | |
· Design | · 具体设计 | 240 | |
· Coding | · 具体编码 | 2400 | |
· Code Review | · 代码复审 | 120 | |
· Test | · 测试(自我测试,修改代码,提交修改) | 960 | |
Reporting | 报告 | ||
· Test Report | · 测试报告 | 120 | |
· Size Measurement | · 计算工作量 | 30 | |
· Postmortem & Process Improvement Plan | · 事后总结,并提出过程改进 | 30 | |
合计 | 4260 |
根据项目需求,subway需要实现以下功能:
- 建立北京地铁线路图,保存地铁线路,站点,换乘信息和站点的坐标信息
- 寻找两个站点之间的最短路径(换乘后站点数额外加3)
- 从一个站点出发,遍历图中所有站点
- 通过图形界面对结果进行展示
最终我们实现的功能包括:
- 建立地铁线路图并保存站点信息等内容
- 将原本的txt格式文档修改为json格式以便适应之后的图形化
- 若第一个命令行参数为‘/g’则显示图形界面并将最短路搜索结果在图中进行展示,用户所要搜索的起始站点和终点站点将在图形界面中进行输入,程序从用户所输入的文本中获取站点名称并进行搜索最短路径
- 若第一个命令行参数为‘/b’则可直接在命令行键入起点和终点,程序运行后将反馈最佳路线(每次换乘额外加3站)
- 若第一个命令行参数为‘/l’则在命令行中键入想要获取信息的线路名称如“九号线”,程序运行后将反馈线路中的所有站点
- 若第一个命令行参数为‘/a’则在命令行键入起点,程序运行后反馈由该点出发遍历地图上所有节点的结果。该功能我们没能完全实现,最后输出的结果中虽然遍历了所有节点,但是存在不合理的遍历次序,比如:从“古城”到“莲花桥”
- 若第一个命令行参数为‘/z’则在命令行中键入要测试的目标文件的绝对路径,可以检测出目标文件的内容是否出现以下两个方面的错误:
1、车站的遍历次序不合理,比如从“知春路”到了“中关村”
2、车站遍历次序合理,但有遗漏的站点,或者车站数量错误
使用VisualStudio的性能分析器分析结果如下:
本项目中要实现输出两个站点之间的最短路径的部分并不难,可以采用Dijkstra算法或SPFA算法,由于在GUI的设计中需要使用C#,所以用C#实现了SPFA算法
private Dictionary<int, List<Edge>> adj;//用于存储返回的搜索出的最短路径结果
public UndirectedGraph()
{
adj = new Dictionary<int, List<Edge>>();
}
public void AddEdge(int from, int to, int line)
{
if (!adj.ContainsKey(from))
adj[from] = new List<Edge>();
if (!adj.ContainsKey(to))
adj[to] = new List<Edge>();
adj[from].Add(new Edge(to, line));
adj[to].Add(new Edge(from, line));
}
public KeyValuePair<int, List<KeyValuePair<int, int>>> ShortestPath(int source, int target)
{
Dictionary<int, int> dist = new Dictionary<int, int>();
Dictionary<int, KeyValuePair<int, int>> pre = new Dictionary<int, KeyValuePair<int, int>>();
foreach (int id in adj.Keys)
{
dist[id] = 0x3f3f3f3f;
}
dist[source] = 1;
Queue<Edge> q = new Queue<Edge>();
HashSet<Edge> vis = new HashSet<Edge>();
q.Enqueue(new Edge(source, -1));
vis.Add(new Edge(source, -1));
while (q.Count != 0)
{
Edge x = q.Dequeue();
foreach (Edge e in adj[x.To])
{
int temp = dist[x.To] + 1;
if (x.Line != -1 && e.Line != x.Line) temp += 3;//若有换乘线路则+3
if (dist[e.To] > temp)
{
dist[e.To] = temp;
pre[e.To] = new KeyValuePair<int, int>(x.To, e.Line);
if (!vis.Contains(e))
{
q.Enqueue(e);
vis.Add(e);
}
}
}
vis.Remove(x);
}
List<KeyValuePair<int, int>> path = new List<KeyValuePair<int, int>>();
for (int i = target; pre.ContainsKey(i); i = pre[i].Key)
path.Add(pre[i]);
return new KeyValuePair<int, List<KeyValuePair<int, int>>>(dist[target], path);
}
在设计遍历功能的过程中,我们查阅了相关资料,了解到通过增加和删除边的方法将地铁图修改成为欧拉回路之后,再对欧拉回路进行深度优先搜索实现遍历的方法,但是最终没能将地铁图修改成为欧拉回路,采用深度优先搜索进行遍历,结果中出现了不合理的遍历次序。
void DFS(int a)
{
int b;
visited[a] = true;
DFS_count++;
path[DFS_count] = a;
for (int i = 1; i <= graph[a].rear; i++) {
b = graph[a].arclist[i].to;
if(visited[b] == false || graph[a].rear == 1 )
DFS(b);
}
}
void searchAll(char *begin)
{
DFS_count = 0;
bool flag;
flag = true;
memset(visited, false, sizeof(visited));
memset(dist, INF, sizeof(dist));
for (int i = 1; i <= node_num; i++)
{
if (visited[i] == false)
{
flag = false;
}
}
int a;
a = locateStation(begin);
if ( a == 0) {
cout << "站点名称错误" << endl;
return;
}
DFS(a);
cout << DFS_count << endl;
for (int i = 1; i <= DFS_count; i++)
{
cout << node[path[i]].name << endl;
}
}
在编写GUI图形界面时,我们首先遇到的问题是插入北京地铁线路图。添加pictureBox之后,按常规思路将图片添加在Image处,却出现了因分辨率过大导致图片无法完全显示的问题,最终我们选择将图片添加在BackgroundImage处,并将SizeMode修改为Zoom,解决了问题,并且可以通过鼠标滚轮实现图片的放大和缩小。
在本项目中如果要处理其他地方的地铁线路,比如上海,则需要按照规范编写存储上海地铁线路信息的文档并修改GUI中的背景图等相关部分。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 30 | 20 |
Development | 开发 | ||
· Analysis | · 需求分析(包括学习新技术) | 180 | 160 |
· Design Spec | · 生成设计文档 | 60 | 45 |
· Design Review | · 设计复审(和同事审核设计文档) | 60 | 30 |
· Coding Standard | · 代码规范(为目前的开发制定合适的规范) | 30 | 45 |
· Design | · 具体设计 | 240 | 235 |
· Coding | · 具体编码 | 2400 | 2560 |
· Code Review | · 代码复审 | 120 | 150 |
· Test | · 测试(自我测试,修改代码,提交修改) | 960 | 900 |
Reporting | 报告 | ||
· Test Report | · 测试报告 | 120 | 100 |
· Size Measurement | · 计算工作量 | 30 | 25 |
· Postmortem & Process Improvement Plan | · 事后总结,并提出过程改进 | 30 | 45 |
合计 | 4260 | 4240 |
在本次开发是首次两人一组进行项目开发的宝贵经历,在图形界面设计、遍历算法和两点之间最短路径算法的设计过程中,我们通过讨论和查阅资料解决了大部分问题(虽然还有一些问题没有解决,体现在了我们最终功能的缺陷上)。