软件工程团队项目------Beijing Subway
目錄
零、分工
一、GitHub地址
二、PSP表格
三、控制臺程序解題思路
四、控制臺程序?qū)崿F(xiàn)
五、控制臺程序性能分析 六、控制臺黑盒測試
1./b功能
2./a功能 部分結(jié)果
3./c功能
4./z測試功能
七、界面設(shè)計(jì)
1.界面設(shè)計(jì)思路
2.將C++封裝為dll
3.圖形界面的實(shí)現(xiàn)
4.繪圖功能的實(shí)現(xiàn)
5.界面功能基本完成
八、個(gè)人感悟
零、分工
控制臺:張玉偉
GUI: 徐志濤
一、GitHub地址
github地址:https://github.com/ZhangWuren/SE-Team-Project
二、PSP表格
三、控制臺程序解題思路
1. 建模思路和文本信息
在本項(xiàng)目中,建模的對象是北京地鐵圖,在建模的過程中,建立了兩個(gè)類,分別為類Station和類Map。類Map包含了類Station,具體的類圖在項(xiàng)目完成后展示。
在文本數(shù)據(jù)beijing-subway.txt中,記錄了地鐵站及其對應(yīng)的線路,舉例如下
1 蘋果園
1 古城
1 八角游樂園
1 八寶山
1 玉泉路
1 五棵松
1 萬壽路
1 公主墳-10
1 軍事博物館-9
1 木樨地
1 南禮士路
1 復(fù)興門-2
1 西單-4
1 天安門西
1 天安門東
首列為當(dāng)前線路,接著是對應(yīng)的站名,-表示當(dāng)前車站為換乘車站,跟著的是換乘線路,多個(gè)換乘線路用“,”隔開
經(jīng)統(tǒng)計(jì),北京市地鐵最新的不重復(fù)地鐵站數(shù)量為330。
2. Dijkstra算法——/b功能
在/b功能的實(shí)現(xiàn)過程中,將問題抽象出來,就是一個(gè)無向圖最短路問題,整個(gè)地鐵圖為無向圖,尋找兩點(diǎn)之間站點(diǎn)最少的路線。很容易想到的就是曾經(jīng)學(xué)過的Dijkstra算法。在Dijkstra算法中,重要的是設(shè)置鄰接矩陣。
3. /c功能實(shí)現(xiàn)
/c功能是輸出整條線路,只需要簡單的輸出同一條線路上的地鐵站即可。
4. /a功能實(shí)現(xiàn)
/a功能是從選定站點(diǎn)出發(fā),遍歷全部的站點(diǎn)。在思考全遍歷功能時(shí),想起了之前相似的問題有tsp問題,哈密頓回路,歐拉回路等。其中tsp問題要求每個(gè)節(jié)點(diǎn)只能訪問一次,和哈密頓回路類似。歐拉回路則是要求每個(gè)邊都訪問一次。這里的全遍歷功能和它們都不太一樣,本題強(qiáng)調(diào)要遍歷所有站點(diǎn),對于邊并不做要求,只要點(diǎn)遍歷到了,有的邊甚至是可以忽略的,同時(shí)每個(gè)點(diǎn)的訪問次數(shù)也可以是多次的。
經(jīng)過在網(wǎng)絡(luò)上搜索相關(guān)資料,決定采用貪心策略+dijkstra算法,從給定起點(diǎn)start開始,隨機(jī)選取一個(gè)沒有路過的節(jié)點(diǎn)作為end,用之前/b功能的dijkstra算法找到這兩個(gè)點(diǎn)之間的最短路。接著將end作為新的start,再選取沒有經(jīng)歷的節(jié)點(diǎn)最后end,直到所有點(diǎn)都遍歷結(jié)束,最后再返回給定的初始start。在這個(gè)過程中,dijkstra算法的結(jié)果是局部最優(yōu)解,運(yùn)用貪心的策略,可以判定整個(gè)遍歷的過程也可取到最優(yōu)的解。
5. 換乘優(yōu)化
題目中要求,換乘時(shí)因?yàn)楦鞣N原因,相當(dāng)于坐了三個(gè)站。一開始我陷入了難題,因?yàn)槊總€(gè)站點(diǎn)都是獨(dú)立的,譬如“公主墳”這個(gè)換乘站,公主墳既在1號線,又在10號線,在不考慮換乘為3站的情況下,它和“萬壽路”軍事博物館“”蓮花臺“西釣魚臺”這四個(gè)站點(diǎn)的鄰接矩陣權(quán)值都是1,但是考慮換乘優(yōu)化時(shí),權(quán)值要根據(jù)上一站點(diǎn)變化,陷入了僵局。
(所說權(quán)值均表示鄰接矩陣權(quán)值)后來經(jīng)過很長時(shí)間的思考,就是設(shè)置多個(gè)同名的換乘站表示不同地鐵線上的同一個(gè)換成站,同名換乘站之間權(quán)值為0,同線路前后站權(quán)值為1,不同線路前后站權(quán)值為3。用“公主墳”舉例,即創(chuàng)建一個(gè)1號線上的公主墳,一個(gè)10號線上的公主墳,1號線上的公主墳和“萬壽路”軍事博物館“權(quán)值為1,和”蓮花臺“西釣魚臺”權(quán)值為3表示換乘,和10號線上的公主墳權(quán)值為0,因?yàn)橥瑐€(gè)站點(diǎn)本質(zhì)上是在一起的,能夠成功的解決換乘優(yōu)化問題。
6./z測試功能實(shí)現(xiàn)
/z功能也比較簡單,首先根據(jù)設(shè)定好的鄰接矩陣來判斷遍歷順序是否合理。然后再判斷節(jié)點(diǎn)數(shù)以及是否全部遍歷,再給出遺漏的站點(diǎn),比較簡單。
四、控制臺程序?qū)崿F(xiàn)
1. Dijkstra算法——/b功能代碼
Dijkstra算法的另一塊重點(diǎn)部分為鄰接矩陣權(quán)值的設(shè)定,代碼如下
2. /a功能代碼
其中函數(shù)setTransMartix()為換乘優(yōu)化時(shí)的矩陣,具體如下
3./z測試功能代碼
void Map::test(string filename) {this->setMartix();memset(this->m_tvis, false, sizeof(m_tvis));fstream fin(filename);string readline;string stas[_TOTALS * 10];for (int i = 0; i < _TOTALS * 10; i++){stas[i].clear();}getline(fin, readline);int count = stoi(readline);int count1 = 0;int i = 0;while (getline(fin, readline)){stas[i] = readline;i++;}for (int i = 1; !stas[i].empty(); i++){Station s1 = this->getStationbyname(stas[i]);Station s2 = this->getStationbyname(stas[i - 1]);m_tvis[s1.getNumber()] = true;m_tvis[s2.getNumber()] = true;if (!this->m_maze[s1.getNumber()][s2.getNumber()]){cout << "error" << endl;return;}}int novissta[_TOTAL];memset(novissta, -1, sizeof(novissta));for (int i = 0, j = 0; i < _TOTAL; i++){if (this->m_tvis[i] == false){novissta[j] = i;j++;}}if (novissta[0] == -1){cout << "true" << endl;}else{cout << "false" << endl;cout << "遺漏的站點(diǎn)有:" << endl;for (int i = 0; novissta[i] != -1; i++){cout << this->getStationbynumber(novissta[i]).getName() << endl;}} }五、控制臺程序性能分析
對全遍歷功能進(jìn)行性能分析,發(fā)現(xiàn)耗時(shí)較長的函數(shù)是全遍歷函數(shù)traversal以及其調(diào)用的貪心迪杰斯特拉搜索greedSearch,均控制在較短時(shí)間,不再做進(jìn)一步優(yōu)化。
還有讀取地圖的setMap函數(shù),本項(xiàng)目采用txt方式,逐行讀取北京地鐵圖,因?yàn)閿?shù)據(jù)量較小,故不做進(jìn)一步改進(jìn)。
六、控制臺黑盒測試
1./b功能
和百度地圖比較
基本類似
2./a功能 部分結(jié)果
3./c功能
房山線
4./z測試功能
將/a的結(jié)果用作測試時(shí),應(yīng)該為true
刪除部分/a的結(jié)果
造成錯(cuò)誤站點(diǎn)
七、界面設(shè)計(jì)
1.界面設(shè)計(jì)思路
以C++代碼為功能,將函數(shù)封裝為dll供圖形界面調(diào)用,因?yàn)樵谛W(xué)期的時(shí)候用過C#寫過圖形界面,所以決定采用C#構(gòu)建圖形界面,在C++函數(shù)中將要走過的站點(diǎn)依次輸出到文本文件中,然后再根據(jù)之前存儲的坐標(biāo)信息將各個(gè)站點(diǎn)的位置和路線畫在以北京地鐵線路圖為背景的畫布上。
2.將C++封裝為dll
C++函數(shù)封裝成動態(tài)鏈接庫時(shí)才能提供接口供C#進(jìn)行調(diào)用,首先創(chuàng)建一個(gè)dll項(xiàng)目,然后將之前編寫好的C++頭文件復(fù)制到這個(gè)項(xiàng)目中,再將要用到的函數(shù)聲明在dll項(xiàng)目的頭文件中,如下圖所示
之后在C#中就可以直接聲明調(diào)用函數(shù)了
項(xiàng)目目錄大致是這樣的,然后再將項(xiàng)目進(jìn)行編譯 ,項(xiàng)目目錄下會生成一個(gè)名字為Subway_dll.dll的動態(tài)鏈接庫文件,我們這時(shí)就的到想要的dll文件,然后將這個(gè)dll文件復(fù)制到C#圖形界面項(xiàng)目的可執(zhí)行文件目錄下,就能在圖形界面進(jìn)行C++函數(shù)的調(diào)用了
3.圖形界面的實(shí)現(xiàn)
在窗體中導(dǎo)入北京地鐵線路圖,想要正確的繪圖首先要得到各個(gè)站點(diǎn)的坐標(biāo),然后為了得到各個(gè)點(diǎn)的坐標(biāo),我寫了一個(gè)Onclick事件,每點(diǎn)一次就獲得當(dāng)前位置的坐標(biāo),將各個(gè)站點(diǎn)的坐標(biāo)依次記錄在Beijing_Subway_Location.txt文件中。然后就可以根據(jù)經(jīng)過的站點(diǎn)信息畫圖了。
為了能夠在C#項(xiàng)目中調(diào)用遍歷功能的C++函數(shù),需要再主函數(shù)這里引入聲明要調(diào)用的函數(shù)
這個(gè)函數(shù)會將經(jīng)過的站點(diǎn)信息依次輸出存入txt文件中,然后C#讀這個(gè)文件,進(jìn)行繪圖。
4.繪圖功能的實(shí)現(xiàn)
因?yàn)樵诶L制路線圖的過程中會反復(fù)進(jìn)行繪圖,所以編寫了一個(gè)DrawTool類來實(shí)現(xiàn)繪圖功能,這個(gè)類中會有兩個(gè)功能,一個(gè)是畫圖,一個(gè)是畫帶箭頭的線來表明路線,代碼如下
5.界面功能基本完成
設(shè)置了一個(gè)Button_Click事件,點(diǎn)擊Search按鈕即可實(shí)現(xiàn)繪制線路圖,點(diǎn)擊Search先會調(diào)用ResetMap函數(shù)來刷新界面,防止上一次的繪圖對本次繪圖發(fā)生影響,具體調(diào)用繪圖功能的代碼如下
執(zhí)行如下命令
界面如圖所示,手動輸入坐標(biāo)會有誤差,站點(diǎn)繪制的并不是非常準(zhǔn)確,在可以接受的誤差范圍內(nèi)
八、個(gè)人感悟
本次結(jié)對項(xiàng)目中我負(fù)責(zé)界面的編寫,學(xué)習(xí)了運(yùn)用C#寫圖形界面以及一些C#的語法,了解了dll的用法,也學(xué)習(xí)了如何合作使用GitHub,本次項(xiàng)目收獲頗豐
總結(jié)
以上是生活随笔為你收集整理的软件工程团队项目------Beijing Subway的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 联想家悦微型计算机的包装箱,08年联想家
- 下一篇: Android-环境搭建