(一)题目:校园导航系统
【问题描述】
以我校为例,设计一个校园导航系统,主要为来访的客人提供信息查询。系统有两类登陆账号,一类是游客,使用该系统方便校内路线查询;一类是管理员,可以使用该系统查询校内路线,可对校园景点路线可编辑。
【需求分析】
设计学校的平面图,至少包括10个以上景点(场所),每两个景点间可以有不同道路,且路长也可能不同,找出在游人所在景点到其他景点的最短路径,或游人输入的任意两个景点的最短路径。 要求: (1) 以图中顶点表示校园内各景点,存放景点名称、代号、简介等信息;以边表示路径,路径权重为路径长度。 (2) 为游人提供任意景点相关信息查询。 (3)为游人提供任意景点的问路查询,即任意两个景点之间的最短路径。
实现提示: 一般情况下,校园道路是双向通行的,可设计校园平面图是一个无向图。顶点和边均含有相关信息。 选做内容: (1)提供图的编辑功能:增删景点;增删道路;修改已有信息等。 (2)校园导游图的仿真界面。
(二)系统功能模块结构图
(三)各模块的功能
(1) 登陆 void login();
(2) 游客模式void vistor();
(3) 管理员登陆void adminLogin();
(4) 管理员模式 void admin();
(5) 首次使用程序的初始化 void init();
(6) 增加场所 void addPlace();
(7) 删除场所 void delPlace();
(8) 添加道路 void addPath();
(9) 删除道路void delPath();
(10)修改场所信息 void modPlace();
(11)查看全部场所 void showInfo();
(12)求两景点最短距离 void Floyd(int start, int end);
(13)查看某场所详细介绍 void inquiryInfo(int n);
(14)安全地退出 void quit();
(14)读取文件 void readFile();
(14)保存文件 void writeFile();
(15) 抽象数据类型定义:
1、景点
顶点名称 代号 顶点信息简介
typedef struct vertex Vertex;
struct vertex
{
char name[100];
char info[1000];
};
2、图的存储结构:
typedef int Edge;
struct map
{
int placeNum;
int pathNum;
Vertex place[100];
Edge path[100][100];
};
struct map hbuMap;文章来源:https://www.toymoban.com/news/detail-491393.html
(四)数据结构设计及用法说明:
本程序主要最短路径函数都基于Floyd算法得以实现。文章来源地址https://www.toymoban.com/news/detail-491393.html
(五)代码:
/*
author:@myp
QQ:1040843800
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 999999
typedef enum
{
false,
true
} bool;
//登陆
void login();
//游客模式
void vistor();
//管理员登陆
void adminLogin();
//管理员模式
void admin();
//首次使用程序的初始化
void init();
//增加场所
void addPlace();
//删除场所
void delPlace();
//添加道路
void addPath();
//删除道路
void delPath();
//修改场所信息
void modPlace();
//查看全部场所
void showInfo();
//求两景点最短距离
void Floyd(int start, int end);
//查看某场所详细介绍
void inquiryInfo(int n);
//安全地退出
void quit();
//读取文件
void readFile();
//保存文件
void writeFile();
typedef struct vertex Vertex;
struct vertex
{
char name[100];
char info[1000];
};
typedef int Edge;
struct map
{
int placeNum;
int pathNum;
Vertex place[100];
Edge path[100][100];
};
struct map hbuMap;
int flag, a, b, num, temp;
bool isAdmin = false;
FILE *pMap;
void writeFile()
{
if ((pMap = fopen("map.dat", "wb")) == NULL)
{
fputs("打开map.dat文件失败\n", stderr);
//stderr(标准错误),是不带缓冲的,这使得出错信息可以直接尽快地显示出来。
exit(1);
}
rewind(pMap);
//将文件内部的位置 指针重新指向一个流( 数据流/文件)的开头
int size = sizeof(hbuMap);
fwrite(&hbuMap, size, 1, pMap);
fclose(pMap);
}
void readFile()
{
if ((pMap = fopen("map.dat", "a+b")) == NULL)
{
fputs("打开map.dat文件失败\n", stderr);
exit(1);
}
rewind(pMap);
int size = sizeof(hbuMap);
fread(&hbuMap, size, 1, pMap);
fclose(pMap);
}
void login()
{
printf(" ***************************** \n");
printf(" * 1.游客登录 *\n");
printf(" * 2.管理员登陆 *\n");
printf(" * 3.退出 *\n");
printf(" *****************************\n");
scanf("%d", &flag);
switch (flag)
{
case 1:
{
vistor();
break;
}
case 2:
{
if (isAdmin == true)
admin();
adminLogin();
break;
}
case 3:
{
quit();
break;
}
default:
{
printf("输入错误,请重新输入!\n");
login();
break;
}
}
}
void init()
{
hbuMap.placeNum = 31;
hbuMap.pathNum = 56;
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < 100; j++)
{
hbuMap.path[i][j] = INF;
}
}
strcpy(hbuMap.place[0].name, "第七教学楼");
strcpy(hbuMap.place[0].info, "就是个教学楼。。。。。");
strcpy(hbuMap.place[1].name, "南院餐厅");
strcpy(hbuMap.place[1].info, "没去过。。。。");
strcpy(hbuMap.place[2].name, "综合教学楼");
strcpy(hbuMap.place[2].info, "没去过。。。。");
strcpy(hbuMap.place[3].name, "第八教学楼");
strcpy(hbuMap.place[3].info, "没去过。。。。");
strcpy(hbuMap.place[4].name, "文苑楼");
strcpy(hbuMap.place[4].info, "没去过。。。。");
strcpy(hbuMap.place[5].name, "北1门口");
strcpy(hbuMap.place[5].info, "没去过。。。。");
strcpy(hbuMap.place[6].name, "国际交流学院");
strcpy(hbuMap.place[6].info, "没去过。。。。");
strcpy(hbuMap.place[7].name, "敏秀园");
strcpy(hbuMap.place[7].info, "没去过。。。。");
strcpy(hbuMap.place[8].name, "第九教学楼");
strcpy(hbuMap.place[8].info, "没去过。。。。");
strcpy(hbuMap.place[9].name, "图书馆");
strcpy(hbuMap.place[9].info, "没去过。。。。");
strcpy(hbuMap.place[10].name, "主楼");
strcpy(hbuMap.place[10].info, "没去过。。。。");
strcpy(hbuMap.place[11].name, "北2门口");
strcpy(hbuMap.place[11].info, "没去过。。。。");
strcpy(hbuMap.place[12].name, "多功能馆");
strcpy(hbuMap.place[12].info, "没去过。。。。");
strcpy(hbuMap.place[13].name, "南2门口");
strcpy(hbuMap.place[13].info, "没去过。。。。");
strcpy(hbuMap.place[14].name, "南1门口");
strcpy(hbuMap.place[14].info, "没去过。。。。");
strcpy(hbuMap.place[15].name, "物理学院");
strcpy(hbuMap.place[15].info, "没去过。。。。");
strcpy(hbuMap.place[16].name, "竞学楼");
strcpy(hbuMap.place[16].info, "没去过。。。。");
strcpy(hbuMap.place[17].name, "化学学院");
strcpy(hbuMap.place[17].info, "没去过。。。。");
strcpy(hbuMap.place[18].name, "电信学院");
strcpy(hbuMap.place[18].info, "没去过。。。。");
strcpy(hbuMap.place[19].name, "逸夫楼");
strcpy(hbuMap.place[19].info, "没去过。。。。");
strcpy(hbuMap.place[20].name, "理化中心");
strcpy(hbuMap.place[20].info, "没去过。。。。");
strcpy(hbuMap.place[21].name, "生科院");
strcpy(hbuMap.place[21].info, "没去过。。。。");
strcpy(hbuMap.place[22].name, "建工学院");
strcpy(hbuMap.place[22].info, "没去过。。。。");
strcpy(hbuMap.place[23].name, "校医院");
strcpy(hbuMap.place[23].info, "没去过。。。。");
strcpy(hbuMap.place[24].name, "北院餐厅");
strcpy(hbuMap.place[24].info, "没去过。。。。");
strcpy(hbuMap.place[25].name, "篮球场网球场");
strcpy(hbuMap.place[25].info, "没去过。。。。");
strcpy(hbuMap.place[26].name, "操场");
strcpy(hbuMap.place[26].info, "没去过。。。。");
strcpy(hbuMap.place[27].name, "宿舍梅园1号");
strcpy(hbuMap.place[27].info, "没去过。。。。");
strcpy(hbuMap.place[28].name, "宿舍梅园2号");
strcpy(hbuMap.place[28].info, "没去过。。。。");
strcpy(hbuMap.place[29].name, "宿舍梅园3,4,5号");
strcpy(hbuMap.place[29].info, "没去过。。。。");
strcpy(hbuMap.place[30].name, "宿舍梅园6号");
strcpy(hbuMap.place[30].info, "没去过。。。。");
hbuMap.path[0][1] = hbuMap.path[1][0] = 150;
hbuMap.path[0][2] = hbuMap.path[2][0] = 144;
hbuMap.path[1][2] = hbuMap.path[2][1] = 110;
hbuMap.path[1][3] = hbuMap.path[3][1] = 75;
hbuMap.path[1][4] = hbuMap.path[4][1] = 93;
hbuMap.path[2][3] = hbuMap.path[3][2] = 42;
hbuMap.path[3][4] = hbuMap.path[4][3] = 44;
hbuMap.path[2][6] = hbuMap.path[6][2] = 169;
hbuMap.path[2][8] = hbuMap.path[8][2] = 73;
hbuMap.path[3][8] = hbuMap.path[8][3] = 87;
hbuMap.path[4][5] = hbuMap.path[5][4] = 60;
hbuMap.path[6][7] = hbuMap.path[7][6] = 139;
hbuMap.path[6][8] = hbuMap.path[8][6] = 167;
hbuMap.path[7][8] = hbuMap.path[8][7] = 20;
hbuMap.path[8][9] = hbuMap.path[9][8] = 78;
hbuMap.path[8][10] = hbuMap.path[10][8] = 190;
hbuMap.path[7][10] = hbuMap.path[10][7] = 20;
hbuMap.path[5][9] = hbuMap.path[9][5] = 134;
hbuMap.path[9][11] = hbuMap.path[11][9] = 77;
hbuMap.path[10][11] = hbuMap.path[11][10] = 114;
hbuMap.path[10][12] = hbuMap.path[12][10] = 91;
hbuMap.path[11][12] = hbuMap.path[12][11] = 96;
hbuMap.path[5][13] = hbuMap.path[13][5] = 37;
hbuMap.path[11][14] = hbuMap.path[14][11] = 39;
hbuMap.path[5][11] = hbuMap.path[11][5] = 210;
hbuMap.path[13][14] = hbuMap.path[14][13] = 202;
hbuMap.path[13][15] = hbuMap.path[15][13] = 179;
hbuMap.path[13][19] = hbuMap.path[19][13] = 93;
hbuMap.path[14][15] = hbuMap.path[15][14] = 59;
hbuMap.path[14][16] = hbuMap.path[16][14] = 56;
hbuMap.path[19][21] = hbuMap.path[21][19] = 92;
hbuMap.path[21][23] = hbuMap.path[23][21] = 82;
hbuMap.path[21][22] = hbuMap.path[22][21] = 111;
hbuMap.path[19][20] = hbuMap.path[20][19] = 105;
hbuMap.path[20][22] = hbuMap.path[22][20] = 80;
hbuMap.path[19][17] = hbuMap.path[17][19] = 178;
hbuMap.path[22][24] = hbuMap.path[24][22] = 84;
hbuMap.path[22][17] = hbuMap.path[17][22] = 91;
hbuMap.path[15][16] = hbuMap.path[16][15] = 53;
hbuMap.path[15][17] = hbuMap.path[17][15] = 57;
hbuMap.path[16][18] = hbuMap.path[18][16] = 115;
hbuMap.path[17][18] = hbuMap.path[18][17] = 108;
hbuMap.path[17][24] = hbuMap.path[24][17] = 114;
hbuMap.path[18][24] = hbuMap.path[24][18] = 102;
hbuMap.path[24][25] = hbuMap.path[25][24] = 24;
hbuMap.path[24][30] = hbuMap.path[30][24] = 44;
hbuMap.path[18][25] = hbuMap.path[25][18] = 15;
hbuMap.path[18][26] = hbuMap.path[26][18] = 70;
hbuMap.path[25][26] = hbuMap.path[26][25] = 5;
hbuMap.path[25][30] = hbuMap.path[30][25] = 49;
hbuMap.path[30][29] = hbuMap.path[29][30] = 92;
hbuMap.path[25][29] = hbuMap.path[29][25] = 20;
hbuMap.path[28][29] = hbuMap.path[29][28] = 20;
hbuMap.path[26][27] = hbuMap.path[27][26] = 10;
hbuMap.path[26][28] = hbuMap.path[28][26] = 10;
hbuMap.path[27][28] = hbuMap.path[28][27] = 134;
writeFile();
}
void showInfo()
{
printf("****景点目录****\n");
for (num = 0; num < hbuMap.placeNum; num++)
printf("【%d】 %s\n", num + 1, hbuMap.place[num].name);
printf("**************\n");
}
void inquiryInfo(int n)
{
printf("景点编号:%d\n景点名称:%s\n景点介绍:%s\n", n, hbuMap.place[n - 1].name, hbuMap.place[n - 1].info);
}
void Floyd(int start, int end)
{
printf("起始地:%s,目的地:%s\n", hbuMap.place[start - 1].name, hbuMap.place[end - 1].name);
if (hbuMap.placeNum <= 0)
{
printf("地图中无任何景点!\n");
return;
}
if (hbuMap.placeNum == 1)
{
printf("地图中只有一个景点,无法查询!\n");
return;
}
if (hbuMap.pathNum <= 0)
{
printf("地图中无道路!\n");
return;
}
int e[100][100];//邻接矩阵
int pre[100][100];//存路径
int i, j, k;
//初始化
for (i = 0; i < hbuMap.placeNum; i++)
for (j = 0; j < hbuMap.placeNum; j++)
{
e[i][j] = hbuMap.path[i][j];
pre[i][j] = j;
}
//更新路径
for (k = 0; k < hbuMap.placeNum; k++)
for (i = 0; i < hbuMap.placeNum; i++)
for (j = 0; j < hbuMap.placeNum; j++)
{
if (e[i][j] > e[i][k] + e[k][j])
{
e[i][j] = e[i][k] + e[k][j];
pre[i][j] = pre[i][k];
}
}
// 打印路径
// 无穷大,无路径
if (e[end - 1][start - 1] == INF)
{
printf("从%s无法到达%s\n", hbuMap.place[start - 1].name, hbuMap.place[end - 1].name);
} else
{
printf("%s到%s的最短路径路程为:%d米\n", hbuMap.place[start - 1].name, hbuMap.place[end - 1].name,
e[end - 1][start - 1]);
printf("路径为:\n%s", hbuMap.place[start - 1].name);
if (pre[start - 1][end - 1] == end - 1)
{ // 如果可以直连
printf("->%s", hbuMap.place[end - 1].name);
} else
{ //需要绕路
temp = start - 1; //初始化temp为终点
while (temp != end - 1)
{
printf("->%s", hbuMap.place[pre[temp][end - 1]].name);
temp = pre[temp][end - 1];
}
}
printf("\n");
}
}
void vistor()
{
printf("==========游客============\n"
" 0.返回 \n"
" 1.查询校内路线\n"
" 2.景点信息\n"
" 3.退出\n"
"=========请输入序号========\n");
scanf("%d", &flag);
switch (flag)
{
case 0:
{
login();
}
case 1:
{
int start, end;
showInfo();
printf("请输入起始地编号\n");
scanf("%d", &start);
printf("请输入目的地编号\n");
scanf("%d", &end);
if (start < 1 || start > hbuMap.placeNum || end < 1 || end > hbuMap.placeNum || start == end)
{
printf("起始点/结束点不存在或者起始地不能与目的地相同!");
vistor();
}
Floyd(start, end);
vistor();
break;
}
case 2:
{
showInfo();
printf("请输入景点编号\n");
scanf("%d", &num);
inquiryInfo(num);
vistor();
break;
}
case 3:
{
quit();
break;
}
default:
{
printf("输入错误,请重新输入!\n");
vistor();
}
}
}
void quit()
{
float y, x, z, f;
for (y = 1.5f; y > -1.5f; y -= 0.1f)
{
for (x = -1.5f; x < 1.5f; x += 0.05f)
{
z = x * x + y * y - 1;
f = z * z * z - x * x * y * y * y;
putchar(f <= 0.0f ? "*********"[(int) (f * -8.0f)] : ' ');
}
putchar('\n');
}
getchar();
if (isAdmin == true)
writeFile();
exit(0);
}
void adminLogin()
{
printf("=========管理员登录======\n");
printf("请输入管理员密码:\n");
printf("提示:密码是336699\n");
char password[18];
getPassword:
scanf("%s", password);
if (strcmp(password, "336699") == 0)
{
printf("登录成功!\n");
isAdmin = true;
admin();
} else
{
printf("密码错误\n请重新输入密码:\n");
goto getPassword;
}
}
void admin()
{
printf("=========管理员系统======\n");
showInfo();
adminFlag:
printf("=======请输入序号=========\n"
"1.增加景点\n"
"2.删除景点\n"
"3.增加道路\n"
"4.删除道路\n"
"5.修改景点信息\n"
"6.进入游客系统\n"
"7.退出\n"
"=========================\n");
scanf("%d", &flag);
switch (flag)
{
case 1:
{
addPlace();
break;
}
case 2:
{
delPlace();
break;
}
case 3:
{
addPath();
break;
}
case 4:
{
delPath();
break;
}
case 5:
{
modPlace();
break;
}
case 6:
{
vistor();
break;
}
case 7:
{
quit();
break;
}
default:
{
printf("输入错误,请重新输入!");
goto adminFlag;
}
}
}
void addPlace()
{
if (hbuMap.placeNum >= 100)
{
printf("空间已满,无法添加!\n");
return;
}
showInfo();
char newName[50];
char newInfo[200];
printf("请输入您要增加的景点名称:\n");
scanf("%s", newName);
printf("请输入%s的景点信息简介\n", newName);
scanf("%s", newInfo);
strcpy(hbuMap.place[hbuMap.placeNum].name, newName);
strcpy(hbuMap.place[hbuMap.placeNum].info, newInfo);
hbuMap.placeNum++;
printf("景点添加成功!\n"
"1.继续添加景点.\n"
"2.返回上一界面.\n");
scanf("%d", &flag);
if (flag == 1)
addPlace();
admin();
}
void addPath()
{
if (hbuMap.placeNum <= 0)
{
printf("地图中无任何景点\n");
admin();
}
if (hbuMap.placeNum == 1)
{
printf("当前系统中只有一个景点,无法添加道路!\n");
admin();
}
showInfo();
printf("请输入要增加道路的两个景点编号:\n");
add:
scanf("%d%d", &a, &b);
if (a < 1 || a > hbuMap.placeNum || b < 1 || b > hbuMap.placeNum || a == b)
{
if (a == b)
printf("请勿输入两个相同编号,重新输入!\n");
else
printf("编号不合法,两个编号都应位于1~%d之间!\n", hbuMap.placeNum);
goto add;
}
if (hbuMap.path[a - 1][b - 1] < INF)
{
printf("%s与%s之间已经含有道路,无法再添加!\n", hbuMap.place[a - 1].name, hbuMap.place[b - 1].name);
admin();
} else
{
int distance;
printf("请输入%s与%s之间道路的长度:\n", hbuMap.place[a - 1].name, hbuMap.place[b - 1].name);
scanf("%d", &distance);
undis:
if (distance <= 0 || distance >= INF)
{
printf("长度不合法,请重新输入!\n");
scanf("%d", &distance);
goto undis;
}
hbuMap.path[a - 1][b - 1] = hbuMap.path[b - 1][a - 1] = distance;
hbuMap.pathNum++;
printf("%s与%s之间道路添加成功!\n", hbuMap.place[a - 1].name, hbuMap.place[b - 1].name);
}
printf("继续添加?【是1/否0】\n");
scanf("%d", &flag);
if (flag == 1)
addPath();
admin();
}
void delPlace()
{
if (hbuMap.placeNum <= 0)
{
printf("地图中无任何景点,无法删除!\n");
return;
}
showInfo();
printf("请输入您要删除的景点编号:\n");
scanf("%d", &a);
while (a > hbuMap.placeNum || a < 1)
{
printf("编号输入有误,编号应位于1~%d之间,重新输入!\n", hbuMap.placeNum);
scanf("%d", &a);
}
printf("您要删除的景点名称为:%s,是否确认删除该景点?确认请输入1 \n", hbuMap.place[a - 1].name);
scanf("%d", &flag);
if (flag == 1)
{
int i, j;
int count = 0;
//数一下有多少条相关的道路
for (i = 0; i < hbuMap.placeNum; i++)
if (hbuMap.path[a - 1][i] != INF)
count++;
//其他景点往前移动
for (i = a - 1; i < hbuMap.placeNum; i++)
hbuMap.place[i] = hbuMap.place[i + 1];
//景点移动后,修改对应道路
//横向
for (i = 0; i < hbuMap.placeNum; i++)
for (j = a - 1; j < hbuMap.placeNum; j++)
hbuMap.path[i][j] = hbuMap.path[i][j + 1];
//纵向
for (i = 0; i < hbuMap.placeNum; i++)
for (j = a - 1; j < hbuMap.placeNum; j++)
hbuMap.path[j][i] = hbuMap.path[j + 1][i];
hbuMap.placeNum--;
hbuMap.pathNum -= count;
} else
return;
printf("景点删除成功!\n");
printf("继续删除?【是1/否0】\n");
scanf("%d", &flag);
if (flag == 1)
delPlace();
showInfo();
admin();
}
void delPath()
{
if (hbuMap.pathNum <= 0)
{
printf("地图中无任何道路!\n");
admin();
}
showInfo();
printf("目前总共有%d条道路\n", hbuMap.pathNum);
printf("请输入要删除道路的两个景点编号:\n");
scanf("%d %d", &a, &b);
while (a < 1 || a > hbuMap.placeNum || b < 1 || b > hbuMap.placeNum || a == b)
{
if (a == b)
printf("请勿输入两个相同编号,重新输入!\n");
if (a < 1 || a > hbuMap.placeNum || b < 1 || b > hbuMap.placeNum)
printf("编号不合法,两个编号都应位于1~%d之间,请重新输入!\n", hbuMap.placeNum);
scanf("%d %d", &a, &b);
}
if (hbuMap.path[a - 1][b - 1] >= INF)
{
printf("%s与%s之间不存在道路!\n", hbuMap.place[a - 1].name, hbuMap.place[b - 1].name);
admin();
} else
{
printf("确认删除%s与%s之间的道路吗【确认1/否认0】 \n", hbuMap.place[a - 1].name, hbuMap.place[b - 1].name);
scanf("%d", &flag);
if (flag == 1)
{
hbuMap.path[a - 1][b - 1] = hbuMap.path[b - 1][a - 1] = INF;
hbuMap.pathNum--;
printf("道路删除成功!\n");
} else
admin();
}
printf("继续删除?【确认1/否认0】\n");
int f;
scanf("%d", &f);
if (f == 1)
delPath();
admin();
}
void modPlace()
{
if (hbuMap.place <= 0)
{
printf("地图中无任何景点,请先添加景点!\n");
return;
}
showInfo();
printf("请输入您要修改信息的景点编号:\n");
scanf("%d", &num);
while (num < 1 || num > hbuMap.placeNum)
{
printf("编号输入有误,编号应位于1~%d之间,重新输入!\n", hbuMap.placeNum);
scanf("%d", &num);
}
char newName[100];
char newInfo[1000];
printf("该景点当前的名字为%s,请输入此景点更改后的名字:\n", hbuMap.place[num - 1].name);
scanf("%s", newName);
printf("该景点当前的信息简介为:\n%s\n请输入此景点更改后的信息简介:\n", hbuMap.place[num - 1].info);
scanf("%s", newInfo);
strcpy(hbuMap.place[num - 1].name, newName);
strcpy(hbuMap.place[num - 1].info, newInfo);
printf("景点信息修改成功!\n");
admin();
}
int main()
{
printf("是否是第一次使用?【是1/否0】\n");
scanf("%d", &flag);
if (flag == 1)
init();
else
readFile();
login();
return 0;
}
到了这里,关于数据结构大作业 校园导航系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!