日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

软件工程团队项目------Beijing Subway

發布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 软件工程团队项目------Beijing Subway 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

零、分工

一、GitHub地址

二、PSP表格

三、控制臺程序解題思路

  • 建模思路和文本信息
  • Dijkstra算法——/b功能
  • /c功能實現
  • /a功能實現
  • 換乘優化
  • /z測試功能實現
  • 四、控制臺程序實現

  • Dijkstra算法——/b功能代碼
  • /a功能代碼
  • /z測試功能代碼
  • 五、控制臺程序性能分析 六、控制臺黑盒測試

    1./b功能

    2./a功能 部分結果

    3./c功能

    4./z測試功能

    七、界面設計

    1.界面設計思路

    2.將C++封裝為dll

    3.圖形界面的實現

    4.繪圖功能的實現

    5.界面功能基本完成

    八、個人感悟

    零、分工

    控制臺:張玉偉

    GUI: 徐志濤

    一、GitHub地址

    github地址:https://github.com/ZhangWuren/SE-Team-Project

    二、PSP表格

    三、控制臺程序解題思路

    1. 建模思路和文本信息
    在本項目中,建模的對象是北京地鐵圖,在建模的過程中,建立了兩個類,分別為類Station和類Map。類Map包含了類Station,具體的類圖在項目完成后展示。

    在文本數據beijing-subway.txt中,記錄了地鐵站及其對應的線路,舉例如下

    1 蘋果園
    1 古城
    1 八角游樂園
    1 八寶山
    1 玉泉路
    1 五棵松
    1 萬壽路
    1 公主墳-10
    1 軍事博物館-9
    1 木樨地
    1 南禮士路
    1 復興門-2
    1 西單-4
    1 天安門西
    1 天安門東
    首列為當前線路,接著是對應的站名,-表示當前車站為換乘車站,跟著的是換乘線路,多個換乘線路用“,”隔開

    經統計,北京市地鐵最新的不重復地鐵站數量為330。

    2. Dijkstra算法——/b功能
    在/b功能的實現過程中,將問題抽象出來,就是一個無向圖最短路問題,整個地鐵圖為無向圖,尋找兩點之間站點最少的路線。很容易想到的就是曾經學過的Dijkstra算法。在Dijkstra算法中,重要的是設置鄰接矩陣。

    3. /c功能實現
    /c功能是輸出整條線路,只需要簡單的輸出同一條線路上的地鐵站即可。

    4. /a功能實現
    /a功能是從選定站點出發,遍歷全部的站點。在思考全遍歷功能時,想起了之前相似的問題有tsp問題,哈密頓回路,歐拉回路等。其中tsp問題要求每個節點只能訪問一次,和哈密頓回路類似。歐拉回路則是要求每個邊都訪問一次。這里的全遍歷功能和它們都不太一樣,本題強調要遍歷所有站點,對于邊并不做要求,只要點遍歷到了,有的邊甚至是可以忽略的,同時每個點的訪問次數也可以是多次的。

    經過在網絡上搜索相關資料,決定采用貪心策略+dijkstra算法,從給定起點start開始,隨機選取一個沒有路過的節點作為end,用之前/b功能的dijkstra算法找到這兩個點之間的最短路。接著將end作為新的start,再選取沒有經歷的節點最后end,直到所有點都遍歷結束,最后再返回給定的初始start。在這個過程中,dijkstra算法的結果是局部最優解,運用貪心的策略,可以判定整個遍歷的過程也可取到最優的解。

    5. 換乘優化
    題目中要求,換乘時因為各種原因,相當于坐了三個站。一開始我陷入了難題,因為每個站點都是獨立的,譬如“公主墳”這個換乘站,公主墳既在1號線,又在10號線,在不考慮換乘為3站的情況下,它和“萬壽路”軍事博物館“”蓮花臺“西釣魚臺”這四個站點的鄰接矩陣權值都是1,但是考慮換乘優化時,權值要根據上一站點變化,陷入了僵局。

    (所說權值均表示鄰接矩陣權值)后來經過很長時間的思考,就是設置多個同名的換乘站表示不同地鐵線上的同一個換成站,同名換乘站之間權值為0,同線路前后站權值為1,不同線路前后站權值為3。用“公主墳”舉例,即創建一個1號線上的公主墳,一個10號線上的公主墳,1號線上的公主墳和“萬壽路”軍事博物館“權值為1,和”蓮花臺“西釣魚臺”權值為3表示換乘,和10號線上的公主墳權值為0,因為同個站點本質上是在一起的,能夠成功的解決換乘優化問題。

    6./z測試功能實現
    /z功能也比較簡單,首先根據設定好的鄰接矩陣來判斷遍歷順序是否合理。然后再判斷節點數以及是否全部遍歷,再給出遺漏的站點,比較簡單。

    四、控制臺程序實現

    1. Dijkstra算法——/b功能代碼

    Dijkstra算法的另一塊重點部分為鄰接矩陣權值的設定,代碼如下


    2. /a功能代碼

    其中函數setTransMartix()為換乘優化時的矩陣,具體如下

    void Map::setTransMartix() {memset(m_maze, INF, sizeof(m_maze));//2、10為環線m_maze[23][38] = 1;m_maze[38][23] = 1;m_maze[173][207] = 1;m_maze[207][173] = 1;for (int i = 0; i < _TOTALS; i++){if (i != 0 && i != _TOTALS - 1)//如果不是第一個和最后一個{if (stations[i].getType()){//如果是換乘車站,則需要考慮換乘的代價{//本條線路上權值仍未1if (stations[i].compareLine(stations[i + 1])) {m_maze[i][i + 1] = 1;}if (stations[i].compareLine(stations[i - 1])) {m_maze[i][i - 1] = 1;}}{//別的線路上可以換乘的站點for (int j = 0; j < _TOTALS; j++){if (stations[i].getNumber() == stations[j].getNumber() && i != j){//找到除了本身以外的同名站點m_maze[i][j] = 0;//同名站點可以直接到達,賦權值為0//和同名站點的相鄰站點,即為換乘,賦權值為3if (j != 392){//需考慮巴溝站沒有j+1站if (stations[j].compareLine(stations[j + 1])) {m_maze[i][j + 1] = 3;}if (stations[j].compareLine(stations[j - 1])) {m_maze[i][j - 1] = 3;}}else{m_maze[i][j - 1] = 3;}}}}}else{//如果不是換乘車站,直接將權值賦為1if (stations[i].compareLine(stations[i + 1])) {m_maze[i][i + 1] = 1;}if (stations[i].compareLine(stations[i - 1])) {m_maze[i][i - 1] = 1;}}}else{if (i == 0){m_maze[i][i + 1] = 1;}else{m_maze[i][i - 1] = 1;m_maze[i][195] = 3;}}} }

    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 << "遺漏的站點有:" << endl;for (int i = 0; novissta[i] != -1; i++){cout << this->getStationbynumber(novissta[i]).getName() << endl;}} }

    五、控制臺程序性能分析

    對全遍歷功能進行性能分析,發現耗時較長的函數是全遍歷函數traversal以及其調用的貪心迪杰斯特拉搜索greedSearch,均控制在較短時間,不再做進一步優化。

    還有讀取地圖的setMap函數,本項目采用txt方式,逐行讀取北京地鐵圖,因為數據量較小,故不做進一步改進。

    六、控制臺黑盒測試

    1./b功能

    和百度地圖比較

    基本類似

    2./a功能 部分結果


    3./c功能
    房山線

    4./z測試功能
    將/a的結果用作測試時,應該為true

    刪除部分/a的結果

    造成錯誤站點

    七、界面設計

    1.界面設計思路
    以C++代碼為功能,將函數封裝為dll供圖形界面調用,因為在小學期的時候用過C#寫過圖形界面,所以決定采用C#構建圖形界面,在C++函數中將要走過的站點依次輸出到文本文件中,然后再根據之前存儲的坐標信息將各個站點的位置和路線畫在以北京地鐵線路圖為背景的畫布上。

    2.將C++封裝為dll
    C++函數封裝成動態鏈接庫時才能提供接口供C#進行調用,首先創建一個dll項目,然后將之前編寫好的C++頭文件復制到這個項目中,再將要用到的函數聲明在dll項目的頭文件中,如下圖所示

    之后在C#中就可以直接聲明調用函數了

    項目目錄大致是這樣的,然后再將項目進行編譯 ,項目目錄下會生成一個名字為Subway_dll.dll的動態鏈接庫文件,我們這時就的到想要的dll文件,然后將這個dll文件復制到C#圖形界面項目的可執行文件目錄下,就能在圖形界面進行C++函數的調用了


    3.圖形界面的實現
    在窗體中導入北京地鐵線路圖,想要正確的繪圖首先要得到各個站點的坐標,然后為了得到各個點的坐標,我寫了一個Onclick事件,每點一次就獲得當前位置的坐標,將各個站點的坐標依次記錄在Beijing_Subway_Location.txt文件中。然后就可以根據經過的站點信息畫圖了。

    為了能夠在C#項目中調用遍歷功能的C++函數,需要再主函數這里引入聲明要調用的函數

    這個函數會將經過的站點信息依次輸出存入txt文件中,然后C#讀這個文件,進行繪圖。

    4.繪圖功能的實現
    因為在繪制路線圖的過程中會反復進行繪圖,所以編寫了一個DrawTool類來實現繪圖功能,這個類中會有兩個功能,一個是畫圖,一個是畫帶箭頭的線來表明路線,代碼如下

    5.界面功能基本完成
    設置了一個Button_Click事件,點擊Search按鈕即可實現繪制線路圖,點擊Search先會調用ResetMap函數來刷新界面,防止上一次的繪圖對本次繪圖發生影響,具體調用繪圖功能的代碼如下

    執行如下命令

    界面如圖所示,手動輸入坐標會有誤差,站點繪制的并不是非常準確,在可以接受的誤差范圍內

    八、個人感悟

    本次結對項目中我負責界面的編寫,學習了運用C#寫圖形界面以及一些C#的語法,了解了dll的用法,也學習了如何合作使用GitHub,本次項目收獲頗豐

    總結

    以上是生活随笔為你收集整理的软件工程团队项目------Beijing Subway的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。