C語言實現(xiàn)--校園導航系統(tǒng)

設(shè)計目的

現(xiàn)在的大學占地面積越來越大,建筑物越來越多,功能越來越多樣,校內(nèi)的道路也是縱橫交錯,校園導航系統(tǒng)可以幫助用戶更加快速的了解學校的路線,建筑布局及建筑物的基本信息等(用戶主要是新生、家長、教職工、外來參觀人員等),在幫助用戶了解校園路線、實現(xiàn)導航的功能的基礎(chǔ)上,校園導航系統(tǒng)還錄入了學校各個地點的相關(guān)信息,以供使用者更方便快捷的找到目的地。
隨著科學技術(shù)的不斷發(fā)展,計算機科學日漸成熟,其強大的功能已為人們所深刻認識,它己進入人類社會的各個領(lǐng)域并發(fā)揮著越來越重要的作用。采用計算機進行校園導航已成為衡量校園數(shù)字化的重要標志。校園導航效率的好壞對于來校參觀的客人和學校管理者來說都至關(guān)重要,在很大程度上影響著校園的數(shù)字化建設(shè)和學校的影響力。因此,本次課程設(shè)計研究的校園導航系統(tǒng)具有一定的使用價值和現(xiàn)實意義。

設(shè)計需求

1.從西南大學的平面圖中選取一些有代表性的景點,抽象成一個無向帶權(quán)圖.
2.使用迪杰斯特拉算法提供最優(yōu)路徑查詢

設(shè)計內(nèi)容

該校園導航的使用者分為游客和管理者,功能如下:

游客

-針對游客的校園導航使用說明
-查看校園全景圖,附有校園地點的所有路線情況
-輸入任意地點,查詢該地點的信息,包括地點介紹和相關(guān)路線
-輸入任意兩地點,輸出兩點之間的所有簡單路線
-輸入任意兩地點,輸出兩點之間的一條中轉(zhuǎn)次數(shù)最少的最短路線
-輸入任意兩地點,輸出兩點之間的一條帶權(quán)路徑最短的最有路線
-輸入任意地點,輸出從該點出發(fā)的最佳布網(wǎng)方案

管理員(除游客功能外,還有以下功能)

-使用管理員功能首先需要登錄,登陸成功方可使用導航管理員功能
-可以在地圖中添加新地點
-可以在地圖中添加新路線
-可以在地圖中撤銷舊路線
-注冊新的管理員帳號

各個模塊詳細的功能描述

導航使用說明:描述該導航應該如何使用,具有什么功能

校園平面簡圖:輸出一張有校園所有地點的平面圖,可以直觀的看出校園地點的分布。這是利用了每個地點所存儲的坐標,通過對矩陣元素的遍歷,輸出了各地點的具體方位。并且在平面圖下面以這樣的形式附有校園兩地點相連的所有路線信息:起點<—->終點:xxx m

查看地點信息:任意輸入一個地點序號,輸出該地點的介紹,以及所有與該地點連通的路線及其距離

查詢簡單路徑:任意輸入兩個地點,輸出兩地點間所有的簡單路徑。利用圖的深度搜索遍歷,用棧將經(jīng)過的地點序號存起來,然后每條路線的地點逐個輸出,最后得到所有簡單路徑

查詢最短路徑:任意輸入兩個地點,輸出兩地點間一條中轉(zhuǎn)次數(shù)最少的路線。利用圖的廣度搜索遍歷,用隊列將要遍歷的地點存起來,通過對隊列的操作得到中轉(zhuǎn)次數(shù)最少的路線

查詢最優(yōu)路徑:任意輸入兩個地點,輸出兩地點間一條帶權(quán)路徑最短的路線。利用迪杰斯特拉算法,通過對dist和 path的操作得出最終的最短路線

最佳布網(wǎng)方案:任意輸入一個地點,輸出從該點出發(fā)的最佳布網(wǎng)方案。這是利用了最小生成樹的思想,運用了Prim算法的思想

添加新地點:輸入新地點的名稱和坐標,通過對文件增刪改的操作,將新地點存儲到文件里,就生成了一張新地圖

添加新路線:輸入新路線的起點、終點 、距離,通過對文件增刪改的操作,將新路線存儲到文件里,就生成了一條新路線

撤銷舊路線:輸入要撤銷路線的起點、終點、距離,通過對文件增刪改的操作,將改動后的路線信息存儲到文件里

管理員的登錄:管理員可在此輸入帳號和密碼進行登錄,在輸入密碼時也可以選擇是否隱藏密碼,如果輸入帳號密碼不對應,則可重新輸入,若錯誤三次則自動退出系統(tǒng)。通過對用戶輸入的帳號密碼和“admin.txt”文件里保存的帳號密碼進行比較,如果相同則可登錄

管理員的注冊:管理員可在此輸入帳號和密碼進行注冊,密碼需要輸入兩遍,相同則注冊成功。通過對“admin.txt”文件增刪改的操作,將新帳號和密碼存儲到文件里,就生成了一個新的管理員帳號

隊列的操作:有隊列的判空、隊列的初始化、出隊、入隊函數(shù)

創(chuàng)建無向圖:采用鄰接矩陣的結(jié)構(gòu),通過對“路線信息”文件和“地點介紹”文件的讀取,將信息存儲到鄰接矩陣中,然后創(chuàng)建出帶權(quán)無向圖

游客和管理員菜單:游客和管理員可在其對應的菜單頁面進行功能選擇

重點設(shè)計及相關(guān)代碼

數(shù)據(jù)結(jié)構(gòu)類型的選擇:鄰接矩陣

#define MAXVEX 50
#define INFINITY 32768
#define MAXL 20
#define MAXC 66

int visited[INFINITY];
int stack[INFINITY];
int count;

struct user //保存管理員帳號密碼的結(jié)構(gòu)體
{
    char id[20];  //管理員帳號
    char passwd[20];  //管理員密碼
    struct user *next;
};
typedef struct //保存地點信息的結(jié)構(gòu)體
{
    int No;    //校園地點序號
    char name[20];    //校園地點名
    char description[200];  //地點描述
}Vextype;
typedef struct //鄰接矩陣
{
    int arcs[MAXVEX][MAXVEX];   //邊集
    Vextype vex[MAXVEX];        //頂點集
    int vexnum;                 //頂點數(shù)目
    int arcnum;                 //邊數(shù)目
}AdjMatrix;
typedef struct //坐標矩陣
{
    int point; //該點是否為校園地點
    char name[20]; //該點校園地點名
    int No; //該點校園地點序號
}SchoolMap;

typedef struct Node
{
    int date;  //隊列元素的值,存儲地點序號
    struct Node *next;
}LinkQueueNode;
typedef struct
{
    LinkQueueNode *front; //頭指針
    LinkQueueNode *fear; //尾指針
}LinkQueue;
int IsEmpty(LinkQueue *Q) //隊列判空
{
    if(Q->front == Q->fear)
        return 1;
    else
        return 0;
}
int InitQueue(LinkQueue *Q)//隊的初始化
{
    Q->front = (LinkQueueNode *)malloc(sizeof(LinkQueueNode));
    if(Q->front != NULL) {
        Q->fear = Q->front;
        Q->front->next = NULL;
        return 1;
    }
    else {
        return 0;
    }
}

創(chuàng)建帶權(quán)無向圖

// 采用鄰接矩陣創(chuàng)建無向圖
int Create(AdjMatrix *G,SchoolMap M[MAXL][MAXC])
{
    int i,j,weight,m,n;

    FILE *fp1;
    fp1=fopen("路線信息.txt","r");

    //從"路線信息.txt"文件中讀取校園圖的景點數(shù)目和路線數(shù)目
    fscanf(fp1, "%d %d", &G->vexnum, &G->arcnum);

    //初始化鄰接矩陣
    for(i = 1; i <= G->vexnum; i++)
        for(j = 1; j<= G->vexnum; j++) {
            G->arcs[i][j] = INFINITY;
    }
    //讀取"路線信息.txt"文件中兩點序號及距離,并賦值給鄰接矩陣
    while(fscanf(fp1,"%d %d %d",&i,&j,&weight) != EOF) {
            G->arcs[i][j] = weight;
            G->arcs[j][i] = weight;
    }
    fclose(fp1);

    FILE *fp2;
    fp2 = fopen("地點介紹.txt", "rt");

    //從"地點介紹.txt"文件中讀取校園圖中的景點名及描述
    for(i = 1; i <= G->vexnum; i++) { 
        G->vex[i].No = i; // 將頂點集中的地點序號設(shè)為i值
        // fscanf()函數(shù)是根據(jù)數(shù)據(jù)格式(format),從輸入流(stream)中讀入數(shù)據(jù),存儲到argument中,遇到空格和換行時結(jié)束。
        // 數(shù)據(jù)依次是:地點名稱、、、地點簡介
        fscanf(fp2, "%s %d %d %s", G->vex[i].name,&m,&n,G->vex[i].description);
        M[m][n].point = 1;
        M[m][n].No = i;
        strcpy(M[m][n].name,G->vex[i].name);
    }
    fclose(fp2);
    return 1;
}

查詢所有簡單路徑:深度搜索遍歷DFS算法

void DFS(AdjMatrix *G, int m, int i, int end)
{
    int j,k;
    for(j = 1; j <= G->vexnum; j++){
        if(G->arcs[i][j] != INFINITY && visited[j] == 0) {
            visited[j] = 1;
            if(j == end) {
                count++;
                printf("★%d.",count);
                for(k = 1; k < m; k++) {
                    printf("%s->", G->vex[stack[k]].name);
                }
                printf("%s\n", G->vex[end].name);
                visited[j] = 0;
            }
            else {
                stack[m] = j;
                m++;
                DFS(G, m, j, end);
                m--;
                visited[j] = 0;
            }
        }
    }
}

查詢中轉(zhuǎn)次數(shù)最少路徑:廣度搜索遍歷BFS算法

void BFS(AdjMatrix *G, int start, int end)
{
    int vis[INFINITY];
    int i, num;
    int w, v;
    LinkQueue *Q;

    Q=(LinkQueue*)malloc(sizeof(LinkQueue));
    if(start == end)
        return;
    memset(vis, 0, INFINITY);
    vis[start] = 1;
    InitQueue(Q);
    EnterQueue(Q, start);
    while(Q->front != Q->fear){
        DeleteQueue(Q, &v);
        num = v;
        for(i = 1;i <= G->vexnum; i++){
            if(G->arcs[num][i] != INFINITY) {
                w = i;  //求出當前節(jié)點的第一個鄰接點(求出序號)
                while(w != -1){
                    if(vis[w] == 0){
                        if(w == end){
                            BFS(G, start, num);
                            printf("%s->",G->vex[num].name);
                            return;
                        }
                        vis[w] = 1;
                        EnterQueue(Q, w);
                        w = NextAdjVertex(G, w, v);
                        //w是求的得第一個鄰接點,v是相對w下一個鄰接點(求出下一個鄰接點的序號)
                    }
                    break;
                }
            }
        }
    }
}

查詢帶權(quán)路徑最短:Dijkstra算法

// Dijkstra算法
void Dijkstra(AdjMatrix *G, int start, int end, int dist[], int path[][MAXVEX])
{
    int mindist, i, j, k, t = 1;
    for(i = 1; i <= G->vexnum; i++) {
        dist[i] = G->arcs[start][i];  //對dist數(shù)組初始化
        if(G->arcs[start][i] != INFINITY)
            path[i][1] = start;  //如果該弧存在,則path[i][1]為源點
    }
    path[start][0] = 1; //start加入到S中
    for(i = 2; i <= G->vexnum; i++) {  //尋找各條最短路徑
        mindist = INFINITY;
        for(j = 1; j <= G->vexnum; j++)
            if(!path[j][0] && dist[j] < mindist) {
                k = j;
                mindist = dist[j];
            }

            if(mindist == INFINITY)
                return ;
            path[k][0] = 1;   //找到最短路徑,將該點加入到S集合中
            for(j = 1; j <= G->vexnum; j++) {  //修改路徑
                if(!path[j][0] && G->arcs[k][j] < INFINITY && dist[k]+G->arcs[k][j] < dist[j]) {
                    dist[j] = dist[k] + G->arcs[k][j];
                    t = 1;
                    while(path[k][t] != 0) {
                        path[j][t] = path[k][t];
                        t++;
                    }
                    path[j][t] = k;
                    path[j][t+1] = 0;
                }
            }
    }

    for(i = 1; i <= G->vexnum; i++)
        if(i == end)
            break;
    printf("\n    ★★★%s--->%s的最短路線為: 從%s",G->vex[start].name,G->vex[end].name,G->vex[start].name);
    for(j = 2; path[i][j] != 0; j++) {
        printf("->%s",G->vex[path[i][j]].name);
    }
    printf("->%s, 距離為%d m\n",G->vex[end].name,dist[i]);
    printf("\n\t\t\t\t\t按任意鍵返回...");
    getch();
}

最佳布網(wǎng)方案:最小生成樹Prim算法

// prim算法構(gòu)建最小生成樹
void Prim(AdjMatrix *G, int start)
{
    struct
    {
        int adjvex;
        int lowcost;
    }closedge[MAXVEX];
    int i, e, k, m, min;
    closedge[start].lowcost = 0;

    // 對除了出發(fā)點以外deep所有頂點初始化對應的closedge數(shù)組
    for(i = 1; i <= G->vexnum; i++) {
        if(i != start) {
            closedge[i].adjvex = start;
            closedge[i].lowcost = G->arcs[start][i];
        }
    }

    for(e = 1; e <= G->vexnum-1; e++)  //控制選中的n-1條符合條件的邊
    {
        //選擇權(quán)值最小的邊
        min = INFINITY;
        for(k = 1; k <= G->vexnum; k++) {
            if(closedge[k].lowcost != 0 && closedge[k].lowcost < min) {
                m = k;
                min = closedge[k].lowcost;
            }
        }
        printf("\t\t\t\t\t從%s---%s:%d m\n", G->vex[closedge[m].adjvex].name,G->vex[m].name,closedge[m].lowcost);
        closedge[m].lowcost = 0;

        for(i = 1; i <= G->vexnum; i++) {
            if(i != m && G->arcs[m][i] < closedge[i].lowcost) {
                closedge[i].lowcost = G->arcs[m][i];
                closedge[i].adjvex = m;
            }
        }
    }
    printf("\n\t\t\t\t\t按任意鍵返回...");
    getch();
}

測試結(jié)果

初始界面

image.png

游客界面
image.png

管理員登錄

管理員界面
image.png

導航說明界面
image.png

校園平面簡圖


查詢景點信息

查詢簡單路線

查詢中轉(zhuǎn)次數(shù)最少的路徑

查詢最優(yōu)路徑

查詢最佳布網(wǎng)方案
image.png

添加新地點

添加新路線

撤銷舊路線

管理員注冊
image.png

寫在后面

終于寫完啦?。。?br> 剛了好幾個星期!??!
這個項目幾乎囊括了數(shù)據(jù)結(jié)構(gòu)大部分知識,在這個過程中查了不少的資料,也看了不少視頻,總結(jié)了許多。雖然這個demo還有bug,后面會繼續(xù)改進!

詳細代碼

https://github.com/ljr7822/iwenHub

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • 一、設(shè)計目的 現(xiàn)在的大學占地面積越來越大,建筑物越來越多,功能越來越多樣,校內(nèi)的道路也是縱橫交錯,校園導航系統(tǒng)可以...
    ggdd5151閱讀 705評論 0 2
  • 1.設(shè)計思想 利用迪杰斯特拉求單源最短路算法,設(shè)計出鄭州升達經(jīng)貿(mào)管理學院的校園導航,求出學校一個景點到另一個景點的...
    LEMFOooO閱讀 1,324評論 0 0
  • 1 需求分析 設(shè)計并顯示某學校的校園平面圖 地點(地點名稱、地點介紹) 路線(公里數(shù))均不少于10個(文件存儲) ...
    ggdd5151閱讀 717評論 0 1
  • 一直以為只要自己努力了,就會有收獲,才發(fā)現(xiàn)付出和收獲不是成正比的,也許自己太過于急功近利,亦或是自己太在意這份收獲...
    奕聿心言閱讀 96評論 0 0
  • 下周我們要進行一次辯論賽,主題是,無友不如己。 我們支持的是不交。 我覺得不應該交和自己志向不同的朋友,如果志向不...
    TATA鴨閱讀 571評論 2 1