校园导游系统(C语言、图、文件存储)

  1. 前言
    这是大二上学期刚学数据结构完成的课设项目,里面的功能还可以进一步的完善,仅供分享、参考、记录使用,加油!
  2. 设计目的
    中国地大物博,文化底蕴颇深,旅游资源更是丰富多彩,也越来越流行“大学打卡热”,中国很多大学校园成为了游客们的打卡的“景区”,为了给来访西安邮电大学的游客更加方便、快捷的提供服务信息,以及为在校学生提供合适的行走路线,因此开发“西安邮电大学校园导航系统”给游客以及在校学生提供更好的服务。
    本次课程设计的主题为校园导航系统,主要目的是使学生学习的理论知识与实际应用相结合,避免学生在“纸上谈兵”。亲历实际应用的设计过程,培养学生独立思考、处理具体问题的能力。理论是单一的,但实际应用问题是多变的,甚至是与理论相冲突的,如何满足实际问题的需求,处理好理论与应用的冲突,是每个学生都应该学会的。
    对于“校园导航系统”的开发者,即学生本人来说,对其能力的提高主要分以下几点:
    ① 深化其脑海中对“图”这种数据的逻辑结构的认知;
    ② 要求学生熟练掌握“图”的邻接矩阵创建、邻接表创建;
    ③ 独立编写代码,提高学生逻辑思维能力;
    ④ 懂得运用几种最基本的“图”操作的算法。
  3. 设计内容
    本系统功能全部划分给管理方和游客两种人群。
    ①游客权限有:显示地图基本信息、查询某个地点的交通路线基本情况、查询两两地之间中转最少的路径、简单路径、最短路径等。
    ②管理方登录后,除了使用用户的所有权限之外,还可以行使地图系统的高级权限,有:添加新顶点、添加新路线、撤销旧路线等。
    下图为校园导航系统的平面图:
    校园导游系统(C语言、图、文件存储)_第1张图片
  4. 功能模块图
    校园导游系统(C语言、图、文件存储)_第2张图片
  5. 各功能函数描述
    1)增加新地点
    ①输入要增加的地点名称和地点信息,并且图的顶点数加1;
    ②修改flag文件中图的顶点数;
    ③可在introduce文件中查看新地点是否增加成功;
    ④实现了校园导航系统管理员增加新地点的功能。
    2)增加新路线
    ①输入要增加路线的起始地点、终止地点和路径的距离并且图的边数加1;
    ②修改flag文件中图的边数;
    ③可在adj文件中查看新路线是否增加成功;
    ④实现了校园导航系统管理员增加新路线的功能。
    3)撤销旧路线
    ①输入要撤销路线的起始地点和终止地点,并让其路径值为无穷,图的边数减1;
    ②修改flag文件中图的边数;
    ③可在adj文件中查看旧路线是否撤销成功;
    ④实现了校园导航系统管理员撤销旧路线的功能。
    4)校园平面图
    ①将校园平面图保存在map文件中;
    ②调用打印地图函数;
    ③实现了校园导航系统管理员和游客对校园平面图的查看。
    5)地点信息查询
    ①分三种查询方式:地点编号查询、地点名称查询、地点编号名称共同查询;
    ②当选择地点编号查询的时候,先打印出各地点名称对应的编号,然后输入要查询的地点的编号,即可显示出所查地点的信息;
    ③当选择地点名称查询的时候,输入需要查询的地点名称,如果有所要查询的地点名称 时,将显示出所查地点的信息;
    ④当选择地点编号名称共通查询的时候,先打印出各地点名称对应的编号,然后输入要查询的地点的编号和地点名称,即可显示出所要查询的地点的信息;
    ⑤实现了校园导航系统管理员和游客对地点信息的查询。
    6)问路查询
    ①分三种路线查询方式:两个地点之间所有的简单路径、两个地点之间中转最少的路径、两个地点之间最短路径;
    ②当查询两个地点之间所有的简单路径时,可以采用深度优先遍历,将所有路线打印出来;
    ③当查询两个地点之间中转最少的路径时,可以采用广度优先遍历,类似于树的按层次遍历,当起点遇到终点时,即为中转最少的路径,也可以采用深度优先遍历,记录中转的地点最少的那条路径输出;
    ④当查询两个地点之间的最短路径时,可以采用Dijkstra算法,借助两个辅助数组dist和path来查询最短路径;
    ⑤实现了校园导航系统管理员和游客对路线的查询。
  6. 各功能函数之间的调用关系
    校园导游系统(C语言、图、文件存储)_第3张图片
  7. 源代码
#include 
#include 
#include 
#include 

#define MAXSIZE 66              //数组长度的最大值 
#define MAXVEX  20             	//最大顶点个数 
#define INFINITY 32767			//表示极大值             	

//以下全局变量用于DFS中 
int count1 = 0;// DFSALL ,路径计数器,全局变量,直接++,如果局部变量,递归到上一层值还是没变 
int way1[MAXSIZE] = {0}; //路径数组 
int count2 = 0;// DFSALL ,层数 
int way2[MAXSIZE] = {0}; //路径数组 
int minc = MAXVEX; //中转最少顶点数最值 
int minway[MAXSIZE] = {0};//路径数组 

//顶点类型的定义
typedef struct{
    char  name[19];		//地点的名称 
	char  info[66];    //地点的介绍 
	int visited;        //访问标志 
}Vextype;

//邻接矩阵的数据类型 
typedef struct{
	int arcs[MAXVEX][MAXVEX]; //边(或弧)信息 
	Vextype vex[MAXVEX];    //顶点信息,顶点类型根据实际情况自行定义 
    int vexnum;		//顶点数目 
	int arcnum;     //边(或弧)数目 
	int visited[MAXVEX];   //访问标志数组,标志是否被访问过 
}AdjMatrix;

//存入地图文件 
void MapFile(AdjMatrix G){
	char filename[30] = "map.txt";
	FILE *fp;
	fp = fopen(filename,"wt");
	if(fp == NULL)
	{
		printf("\n不能打开!");
		exit(1);
	}
   	fprintf(fp,"|------------------------------------------------------------------------------------------------|\n");
    fprintf(fp,"|                                ☆西安邮电大学校园地点一览 ☆                                   |\n");
    fprintf(fp,"|------------------------------------------------------------------------------------------------|\n");
    fprintf(fp,"|                                                                                                |\n"); 
	fprintf(fp,"|                   西区正门                                                                     |\n"); 
	fprintf(fp,"|                      |                                                                         |\n");     
	fprintf(fp,"|                      |                                                                         |\n");
	fprintf(fp,"|                      |                                   东区正门==================逸夫楼      |\n");                          
	fprintf(fp,"|                      |                                                     |         |         |\n");     
	fprintf(fp,"|            |===水煮鸽子                                                    |         |         |\n"); 
	fprintf(fp,"|            |         |                                                     |         |         |\n");     
	fprintf(fp,"|           基础       |                                                     |      安美公寓     |\n");    
	fprintf(fp,"|          教学楼      |                                                     |         |         |\n");    
	fprintf(fp,"|            |         |                                                     |         |         |\n");  
	fprintf(fp,"|            |         |                                                     |      安悦公寓     |\n");  
	fprintf(fp,"|            |         |                                          东升苑 ====|                   |\n");    
	fprintf(fp,"|            |         |                                                     |                   |\n");
	fprintf(fp,"|            |       图书馆                                                  |                   |\n");    
	fprintf(fp,"|       教学实验楼     |                                                     |                   |\n");     
	fprintf(fp,"|            |         |=====================================================|                   |\n");     
	fprintf(fp,"|            |         |                 |||   西邮桥   |||                  |                   |\n");
	fprintf(fp,"|  医务室====|         |=====================================================|                   |\n");
	fprintf(fp,"|                      |                                                                         |\n");    
	fprintf(fp,"|                      |===体育馆                                                                |\n");     
	fprintf(fp,"|                      |                                                                         |\n");    
	fprintf(fp,"|                      |                                                                         |\n");    
	fprintf(fp,"|                    旭日苑                                                                      |\n");     
	fprintf(fp,"|                      |                                                                         |\n");
    fprintf(fp,"|                      |                                                                         |\n");
	fprintf(fp,"|                  西区宿舍楼          	                                                         |\n");      
	fprintf(fp,"|                                                                                                |\n");        
    fprintf(fp,"|------------------------------------------------------------------------------------------------|\n");
	fclose(fp);
}

//打印地图
void MapOutput(){
	printf("|------------------------------------------------------------------------------------------------|\n");
    printf("|                                ☆西安邮电大学校园地点一览 ☆                                   |\n");
    printf("|------------------------------------------------------------------------------------------------|\n");
    printf("|                                                                                                |\n"); 
	printf("|                   西区正门                                                                     |\n"); 
	printf("|                      |                                                                         |\n");     
	printf("|                      |                                                                         |\n");
	printf("|                      |                                   东区正门==================逸夫楼      |\n");                          
	printf("|                      |                                                     |         |         |\n");     
	printf("|            |===水煮鸽子                                                    |         |         |\n"); 
	printf("|            |         |                                                     |         |         |\n");     
	printf("|           基础       |                                                     |      安美公寓     |\n");    
	printf("|          教学楼      |                                                     |         |         |\n");    
	printf("|            |         |                                                     |         |         |\n");  
	printf("|            |         |                                                     |      安悦公寓     |\n");  
	printf("|            |         |                                          东升苑 ====|                   |\n");    
	printf("|            |         |                                                     |                   |\n");
	printf("|            |       图书馆                                                  |                   |\n");    
	printf("|       教学实验楼     |                                                     |                   |\n");     
	printf("|            |         |=====================================================|                   |\n");     
	printf("|            |         |                 |||   西邮桥   |||                  |                   |\n");
	printf("|  医务室====|         |=====================================================|                   |\n");
	printf("|                      |                                                                         |\n");    
	printf("|                      |===体育馆                                                                |\n");     
	printf("|                      |                                                                         |\n");    
	printf("|                      |                                                                         |\n");    
	printf("|                    旭日苑                                                                      |\n");     
	printf("|                      |                                                                         |\n");
    printf("|                      |                                                                         |\n");
	printf("|                  西区宿舍楼          	                                                         |\n");      
	printf("|                                                                                                |\n");        
    printf("|------------------------------------------------------------------------------------------------|\n");    
 } 
 
//创建图,信息从文件中读取 
void Create(AdjMatrix *G){
	int i,j;
	int m,n,weight;
	int vexnum,arcnum;
	char name[19],info[66];
	
	for(i = 1; i <= G->vexnum; i++){   //初始化visited值,刚开始都为0 
		G->vex[i].visited = 0;
    } 
    
	FILE *fp1;
	fp1 = fopen("flag.txt","rt");
	if(fp1 == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	FILE *fp2;
	fp2 = fopen("introduce.txt","rt");
	if(fp2 == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	FILE *fp3;
	fp3 = fopen("adj.txt","rt");
	if(fp3 == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	
	fscanf(fp1,"%d %d",&vexnum,&arcnum);  //从文件中顶点的个数和边的个数 
	G->vexnum = vexnum;
	G->arcnum = arcnum;	
	
	for(i = 1; i <= G->vexnum; i++){
		fscanf(fp2,"%s\n%s",name,info);
		strcpy(G->vex[i].name,name);
		strcpy(G->vex[i].info,info);
	}
	
	for(i = 1; i <= G->vexnum; i++){ 
		for(j = 1;j <= G->vexnum; j++){ 
			G->arcs[i][j] = INFINITY;
		} 
	} 
	
	for(j = 1; j <= G->arcnum; j++){
		fscanf(fp3,"%6d %6d %6d",&m,&n,&weight);
		G->arcs[m][n] = weight;
		G->arcs[n][m] = weight;
	}
	
	fclose(fp1);
	fclose(fp2);
	fclose(fp3);
}

//打印地点列表
void PrintPlace(AdjMatrix *G){ 
	int i;
	for(i = 1; i <= G->vexnum; i++ ){
		printf("\t\t\t\t\t\t%d\t%s\n",i,G->vex[i].name); 
    }
}


void IntroducePlace(AdjMatrix G){  
	int i, num,c;
	int flag = 1;
	char n[30];
	
	while(flag == 1 ){
		system( "cls" );
		printf( "\t\t\t\t\t\t——————地点信息查询——————\n" );
		
		printf("\t\t\t\t\t\t请选择需要查询的方式\n");
		printf("\t\t\t\t\t\t1.地点编号查询\n"); 
		printf("\t\t\t\t\t\t2.地点名称查询\n"); 
		printf("\t\t\t\t\t\t3.地点编号名称共同查询\n"); 
		
		scanf("%d",&c);
		
		if(c == 1){
			
			system("cls");

			PrintPlace(&G);
			
			printf( "\t\t\t\t\t\t请输入需要查找的地点编号:" );
			scanf( "%d", &num );
			
			if(num > 0 && num <= G.vexnum ){
				printf( "\n\n");
				printf( "\t\t\t编号:%d\n",num);
				printf( "\t\t\t名称:%s\n", G.vex[num].name );
				printf( "\t\t\t简介:%s\n\n", G.vex[num].info );
			}
			else{
				printf( "\t\t\t\t\t\t信息输入有误!\n" );
		    }
		    
			printf( "\n\t\t\t\t\t\t是否继续查询地点信息?\n" );
			printf( "\t\t\t\t\t\t1:是\n" );
			printf( "\t\t\t\t\t\t0:返回上级菜单\n" );
			scanf( "%d", &flag );
		}
		else if(c == 2){
			system("cls");
			printf("\t\t\t\t\t\t请输入需要查询的地点名称:");
			scanf("%s",n);
			
			for(i = 1; i <= G.vexnum; i++ ){

				if(strcmp(G.vex[i].name,n) == 0){
					
					printf( "\n\n");
					printf( "\t\t\t编号:%d\n",i);
					printf( "\t\t\t名称:%s\n", G.vex[i].name );
					printf( "\t\t\t简介:%s\n\n", G.vex[i].info );
					break;
				}
   			}

			printf( "\n\t\t\t\t\t\t是否继续查询地点信息?\n" );
			printf( "\t\t\t\t\t\t1:是\n" );
			printf( "\t\t\t\t\t\t0:返回上级菜单\n" );
			scanf( "%d", &flag );			
		}
		else if(c == 3){
			system("cls");
			PrintPlace(&G);
			printf( "\t\t\t\t\t\t请输入需要查找的地点编号:" );
			scanf( "%d", &num );
			printf("\t\t\t\t\t\t请输入需要查询的地点名称:");
			scanf("%s",n);
			if(num > 0 && num <= G.vexnum && strcmp(G.vex[num].name,n) == 0){
				printf( "\n\n");
				printf( "\t\t\t编号:%d\n",num);
				printf( "\t\t\t名称:%s\n", G.vex[num].name );
				printf( "\t\t\t简介:%s\n\n", G.vex[num].info );
			}
			
			printf( "\n\t\t\t\t\t\t是否继续查询地点信息?\n" );
			printf( "\t\t\t\t\t\t1:是\n" );
			printf( "\t\t\t\t\t\t0:返回上级菜单\n" );
			scanf( "%d", &flag );
		}
	}
	system("cls");
}

//地点信息,文件 
void IntroduceFile(AdjMatrix G){
	int i;
	char filename[30] = "introduce.txt";
	
	FILE *fp;
		fp = fopen(filename,"wt");
	if(fp == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	G.vexnum = 15;
	
	strcpy(G.vex[1].name,"西区正门"); 
	strcpy(G.vex[1].info,"西安邮电大学长安校区西区的正门"); 
	strcpy(G.vex[2].name,"西邮桥"); 
	strcpy(G.vex[2].info,"链接西安邮电大学长安校区西区和东区的桥梁,过马路请走西游桥"); 
	strcpy(G.vex[3].name,"东区正门"); 
	strcpy(G.vex[3].info,"西安邮电大学长安校区东区的正门"); 
	strcpy(G.vex[4].name,"水煮鸽子"); 
	strcpy(G.vex[4].info,"西安邮电大学长安校区西区正门口,由鸽子和喷泉组成"); 
	strcpy(G.vex[5].name,"基础教学楼"); 
	strcpy(G.vex[5].info,"西安邮电大学教学楼,有A楼和B楼,是西安邮电大学学生们上课的地方");
	strcpy(G.vex[6].name,"教学实验楼"); 
	strcpy(G.vex[6].info,"西安邮电大学长安校区西区实验楼");  
	strcpy(G.vex[7].name,"逸夫楼"); 
	strcpy(G.vex[7].info,"西安邮电大学教学楼,是学生们上课的地方,很容易迷路哦");   
	strcpy(G.vex[8].name,"图书馆"); 
	strcpy(G.vex[8].info,"西安邮电大学图书馆,可以借阅书籍和自习"); 
	strcpy(G.vex[9].name,"医务室"); 
	strcpy(G.vex[9].info,"西安邮电大学医务室"); 
	strcpy(G.vex[10].name,"旭日苑"); 
	strcpy(G.vex[10].info,"西安邮电大学西区食堂");
	strcpy(G.vex[11].name,"东升苑"); 
	strcpy(G.vex[11].info,"西安邮电大学东区食堂");
	strcpy(G.vex[12].name,"体育馆"); 
	strcpy(G.vex[12].info,"西安邮电大学体育馆,内有运动场地"); 
	strcpy(G.vex[13].name,"西区宿舍"); 
	strcpy(G.vex[13].info,"分为长思公寓和长智公寓"); 
	strcpy(G.vex[14].name,"安美公寓"); 
	strcpy(G.vex[14].info,"分为安美公寓南楼和北楼"); 
	strcpy(G.vex[15].name,"安悦公寓"); 
	strcpy(G.vex[15].info,"分为安悦公寓南楼和北楼");  
	
	//把信息存到文件中
	for(i = 1; i <= G.vexnum; i++){  
		fprintf(fp,"%s\n%s\n",G.vex[i].name,G.vex[i].info); 
	} 
	
	fclose(fp);
}

//邻接矩阵信息,文件 
void AdjFile(AdjMatrix G){
	int i,j;
	char filename[30] = "adj.txt";
	char filename1[30] = "flag.txt";

	FILE *fp;
		fp = fopen(filename,"wt");
	if(fp == NULL){
		printf("\n不能打开!");
		exit(1);
	}
		
	FILE *fp1;
		fp1 = fopen(filename1,"wt");
	if(fp1 == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	
	G.vexnum = 15;
	G.arcnum = 24;   //15个顶点,24个边
	fprintf(fp1,"%d %d\n",G.vexnum,G.arcnum); //存入文件标记
		//初始化矩阵 
	for(i = 0; i <= G.vexnum; i++){   
		for(j = 0; j <= G.vexnum; j++){ 
			G.arcs[i][j] = INFINITY;  //权值全部赋无穷大 
		} 
	}    
	
	//给地点设置权值,即需要走的路程 
	G.arcs[1][3] = G.arcs[3][1] = 800;
	G.arcs[1][4] = G.arcs[4][1] = 120;
	G.arcs[2][3] = G.arcs[3][2] = 300;
	G.arcs[2][8] = G.arcs[8][2] = 450;
	G.arcs[2][9] = G.arcs[9][2] = 600;
	G.arcs[2][11] = G.arcs[11][2] = 100;
	G.arcs[2][12] = G.arcs[12][2] = 500;
	G.arcs[3][7] = G.arcs[7][3] = 150;
	G.arcs[4][5] = G.arcs[5][4] = 140;
	G.arcs[4][8] = G.arcs[8][4] = 200;
	G.arcs[5][6] = G.arcs[6][5] = 111;
	G.arcs[5][8] = G.arcs[8][5] = 222;
	G.arcs[6][8] = G.arcs[8][6] = 300;
	G.arcs[6][9] = G.arcs[9][6] = 417;
	G.arcs[6][10] = G.arcs[10][6] = 360;
	G.arcs[6][12] = G.arcs[12][6] = 250;
	G.arcs[7][14] = G.arcs[14][7] = 120;
	G.arcs[8][12] = G.arcs[12][8] = 345;
	G.arcs[9][10] = G.arcs[10][9] = 404;
	G.arcs[10][12] = G.arcs[12][10] = 200;
	G.arcs[10][13] = G.arcs[13][10] = 100;
	G.arcs[11][15] = G.arcs[15][11] = 150;
	G.arcs[14][15] = G.arcs[15][14] = 50;

	for(i = 1; i <= G.vexnum; ++i){
		for(j = 1; j <= G.vexnum; ++j){
			if(G.arcs[i][j] != INFINITY && i < j){
				fprintf(fp,"%10d %10d %10d\n",i,j,G.arcs[i][j]);
				}
		}
	}
	fclose(fp1);
	fclose(fp);
}

//重置访问数组 
void ClearVisited(AdjMatrix *G) {
	int i;
	for(i = 0; i <= MAXVEX; i++){
		G->vex[i].visited = 0; //全部置0 
	}
}

//深度优先搜索遍历 
void DfsAll(AdjMatrix *G,int s,int e){ 
	int i,j;	
	int shuai = 0;
	G->vex[s].visited = 1;  //置起始点为1 
	way1[count1] = s;    //把起点的序号存在一个数组里,此时count是0 
	
	for(i = 1; i <= G->vexnum; i++){  //遍历顶点		
		if(G->arcs[s][i] != INFINITY && G->vex[i].visited == 0 && i != e){  //权值不等于无穷,而且没有被访问过,并且没有回到起点 
			count1++;  //数组下标递增 
			way1[count1] = i;  //给数组对应的下标附上顶点值 
			DfsAll(G,i,e);  //递归 
			G->vex[i].visited = 0; //递归回来返回到这一层还原这一层现状 
			count1--;
			shuai = 0;  //结束的标志 
			continue;
		}
		if(G->arcs[s][i] != INFINITY && G->vex[i].visited ==0 && i == e && shuai == 0){  //输出 
			count1++;
			way1[count1] = e;
			shuai = 1;
			printf("\n");
			printf("\t%s",G->vex[way1[0]].name);  //起始点 
			for(j = 1;j <= count1; j++){
				printf("-->");
				printf("%s",G->vex[way1[j]].name);		//依次打印 
			}
			count1--;  //让全局变量count变成0,以供其它函数使用 
			return;
		}	
	}		
	return ; 
}

//所有简单路径菜单 
void AllPath(AdjMatrix G,int dist[],int path[][MAXVEX]){  
	int s,e;
	int flag = 1;
	while(flag == 1){
		system("cls");
		printf( "\t\t\t\t\t\t——————所有简单路径查询——————\n" );
		
		PrintPlace(&G);
		
		printf("\n\t\t\t\t\t输入起点编号:");
		scanf("%d",&s);
		printf("\t\t\t\t\t输入终点编号:");
		scanf("%d",&e);
		
		if (s > G.vexnum || s <= 0 || e > G.vexnum || e < 0 || s == e){
			printf( "\t\t\t\t\t\t输入错误!\n\n" );
	    }
		else{
			ClearVisited(&G);  //给标志数组初始化 
			count1=0;
			printf("\n\t\t\t从%s到%s的所有简单路径有:\n", G.vex[s].name, G.vex[e].name);
			
			DfsAll(&G,s,e); //调用函数进行实现功能 
		}
		printf("\n\n\t\t\t\t\t\t是否继续查询所有简单路径?\n" );
		printf("\t\t\t\t\t\t1:是\n" );
		printf("\t\t\t\t\t\t0:返回上级菜单\n" );
		scanf("%d", &flag);
	}
	system("cls");
}

//中转最少 ,也可以用广搜,顶点A到顶点B所含边的数目最少的路线,从A出发广度优先遍历,遇到顶点B就可以停止了 
void DfsLitter(AdjMatrix *G,int start,int end){
	int shuai = 0;
	int i,j;
	G->vex[start].visited = 1;
	way2[count2] = start;
	for(i = 1; i <= G->vexnum; i++){		
		if(G->arcs[start][i] != INFINITY && G->vex[i].visited == 0 && i != end){
			count2++;
			way2[count2] = i;
			DfsLitter(G,i,end); //递归 
			G->vex[i].visited = 0;
			count2--;
			shuai = 0;
			continue;
		}  //此时搜到了所有路径 
		
		
		if(G->arcs[start][i] != INFINITY && G->vex[i].visited == 0 && i == end && shuai == 0){
			count2++;
			way2[count2] = end;
			shuai = 1;
		
			if(count2 < minc){   //如果count2比最大顶点数小 
				minc = count2;   //就赋值 
				for(i = 0; i <= count2; i++){
					minway[i]=way2[i];   //将记录的way2值存到minway中 
			    }
			}
			
			count2--;
			return;
		}	
	}		
}

//中转次数最少简单路径
void LitterPath(AdjMatrix G){
	int i,j,s,e;
	int flag = 1;
	
	while (flag == 1){
		int i;
		system("cls");
		printf("\t\t\t\t\t\t——————中转次数最少路径查询——————\n");
		
		PrintPlace(&G);
		
		printf("\n\t\t\t\t\t输入起点编号:");
		scanf( "%d", &s);
		printf("\t\t\t\t\t输入终点编号:");
		scanf("%d", &e);
		if (s > G.vexnum || s <= 0 || e > G.vexnum || e < 0 || s == e)
			printf("\t\t\t\t\t\t输入错误!\n\n");
	
		else{
			ClearVisited(&G);
		
			minc = MAXVEX;
			
			count2 = 0;
		
			printf("\n\t\t\t从%s到%s的中转最少简单路径为:\n", G.vex[s].name, G.vex[e].name);
			DfsLitter(&G,s,e);  //深搜寻找 
		
			printf("\t\t\t%5s ",G.vex[minway[0]].name);
		
			for(i = 1; i <= minc; i++){    //mic即为count2 
				printf("-->");
				printf("%5s ",G.vex[minway[i]].name);
			}
			printf("\n\n\t\t\t\t\t\t是否继续查询中转最少简单路径?\n");
			printf("\t\t\t\t\t\t1:是\n");
			printf("\t\t\t\t\t\t0:返回上级菜单\n");
			scanf("%d", &flag);
			}
		system( "cls" );
	}
}

//最短路径,dist数组记录各条最短路径长度,path数组记录对应路径上的各顶点 ,依最短路径递增次序求得各条路径 
void Dijkstra(AdjMatrix *G,int s,int e,int dist[MAXVEX],int path[][MAXVEX]){  
	int mindist,i,j,k,t = 1;  //mindist 路径的权值(长度) 
	
	for(i = 1; i <= G->vexnum; i++){  //给dist数组初始化, 
		dist[i] = G->arcs[s][i]; //将邻接数组每一行所对应的列的值填入dist数组中 
		
		if(G->arcs[s][i] != INFINITY){  //如果权值不等于无穷大,则说明有路
			path[i][1] = s;   //将起点记录,path[i]记录从源点到Vi最短路径上的各个顶点
	    } 
	}	
	
	path[s][0] = 1;   //置1标志,说明源点为start 
	
	for(i = 2; i <= G->vexnum; i++){   //寻找各条最短路径 
		
		mindist = INFINITY;  //将最小初值设置为无穷大 
		
		for(j = 1; j <= G->vexnum; j++){//选择最小权值的路径 
		
			if(!path[j][0] && dist[j] < mindist){//j未加入集合S  //path数组记录某定点是否加到S中 
				k = j;  //当前起点到顶点k权值最小
				mindist = dist[j];
			}
	    }
			if(mindist == INFINITY){
				return;             //不存在start到其他顶点的路径 
		    }
		    
			path[k][0] = 1;  // 将顶点k加入到集合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]){  //第k行有路且未被选中过的顶点 &&到k的最小权值+k到j的权值<当前到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;
				}
			 } 	
	}
}

//打印两点间的最短路径
void DijkstraPrint(int start, int end ,AdjMatrix G,int path[][MAXVEX]){
	int i = 2;
	int length = 0;
	printf( "\n\t从%s到%s的最短路径是:", G.vex[start].name, G.vex[end].name );
	printf( "  %s", G.vex[start].name );
	
	while(path[end][i]){   //记录的路径 
		printf("-->%s ",G.vex[path[end][i]].name);
		length += G.arcs[path[end][i-1]][path[end][i]];	
		i++;
	}
	printf( "-->%s", G.vex[end].name );
	length += G.arcs[path[end][i-1]][end];	
	printf( ",长度为%dM", length);
	printf( "\n");
 } 

//分菜单 最短路径 
void ShortPath(AdjMatrix G,int dist[],int path[][MAXVEX]){ 
	int i,j,s,e;
	int flag = 1;
	while (flag == 1){
		system("cls");
		printf("\t\t\t\t\t\t——————最短路径查询——————\n");
		PrintPlace(&G);
		printf("\n\t\t\t\t\t输入起点编号:");
		scanf("%d",&s);
		printf("\t\t\t\t\t输入终点编号:");
		scanf("%d",&e);
		if (s > G.vexnum || s <= 0 || e > G.vexnum || e < 0 || s == e){
			printf("\t\t\t\t\t\t输入错误!\n\n");
	    }
		else{
			ClearVisited(&G);   //菜单 
			
			Dijkstra(&G,s,e,dist,path); //算法 
			DijkstraPrint(s,e,G,path);//打印 
	
		}
		printf("\n\t\t\t\t\t\t是否继续查询最短路径?\n");
		printf("\t\t\t\t\t\t1:是\n");
		printf("\t\t\t\t\t\t0:返回上级菜单\n");
		scanf("%d",&flag);
	}
	system("cls");
}

//路径二级主菜单 
void SearchPath(AdjMatrix G,int dist[],int path[][MAXVEX]){ 
	int x,flag = 1;
	while(flag == 1){  //二级菜单 
		printf("\t\t\t1. 所有简单路径\n");  //各顶点均不重复 
		printf("\t\t\t2. 最短的简单路径(中转最少)\n");
		printf("\t\t\t3. 最佳访问路径(最短路径长度)\n");
		printf("\t\t\t0. 返回主菜单\n");
		printf("\t\t\t请选择您需要的操作:");
		scanf("%d",&x);

		switch(x){
			case 1: system("cls");AllPath(G,dist,path);break;
			case 2: system("cls");LitterPath(G);break;
			case 3: system("cls");ShortPath(G,dist,path);break;
			case 0: flag = 0; break;
			default:printf( "\t\t\t\t\t\t\t输入信息错误,请重新输入!\n" ); break;
		}
	system("cls");
   }
}

//注册信息
void enroll(){
	char a[100];                   //注册用户名
	char b[100];                   //注册密码
	char s[100];                   //再次确定密码
	int  len;
	
	
   	printf("请输入您的用户名:");
	scanf("%s",a);
	
	printf("请设置您的密码:");
			
	reset: scanf("%s",b);     //用到了if goto语句 

	    len = strlen(b);    //读取密码长度 
	   
	    if(len > 9){
		  printf("密码长度过长,请重新设置:");
	      goto reset;    //if goto 语句  
	    }
   	    printf("请再次输入您设置的密码:");
     	scanf("%s",s);
	
	    if(strcmp(b,s) == 0){       //字符串比较函数 
		    FILE *fp;
		
			fp=fopen("register.txt","at");     //选用追加方式,可以存多个信息
		
			if(fp == NULL){
				printf("文件不存在或者请先注册!");
				exit(1);                           
	     	}
		
			fprintf(fp,"%s %s\n",a,b);                    //字符串写入函数进行写入操作
        	system("cls");
	    	printf("\n\t------注册成功------\n");
			fclose(fp);
		}
		else if(strcmp(b,s) != 0){
			printf("您两次输入的密码不一致,请重新设置密码!\n");
			goto reset;          //if goto 语句 
		}
}

//登陆页面
int land(){
	int  i = 0;      //i是为了判断密码长度 并加密 
	char a[10];                 
	char b[10];                   

	char user_name[10];           
	char user_passwords[10];      

	printf("请输入您的用户名:");
	scanf("%s",user_name);

    printf("请输入您的密码:");

	while(i < 9 && (user_passwords[i] = getch()) && user_passwords[i] != '\r'){   //如果输入超限 或者 遇到换行符就跳出循环
		printf("*");   //掩饰密码 
		i++;
	}
	
	user_passwords[i] = 0;   //字符串结束标志 '/0' 
	
	FILE *fp;
	fp=fopen("register.txt","rt");       //又打开文件 
	
	if(fp == NULL){
		printf("文件不存在!");
		exit(1);
	}
	
	while(fscanf(fp,"%s %s",a,b) != EOF){    //读文件判断账号密码是否正确     
		if(strcmp(a,user_name) == 0  &&  strcmp(b,user_passwords) == 0){   //字符串比较函数,看是否正确 
		 	system("cls");
			printf("\n\t\t\t--------登陆成功--------\n");
			return 0;
		 } 
	}
	if(1){
		system("cls");
		printf("\n信息输入错误!(请检查注册文件信息)\n");
	    land();
	}
	fclose(fp);
}

//增加新地点和信息 
void AddPlace(AdjMatrix *G){
	int s,e;
	char filename[30] = "introduce.txt";
	char filename1[30] = "flag.txt";
	
	
	int flag = 1;
	char p[20];
	char i[66];
	
	while (flag == 1){
		//增加地点的地名
		//增加地点的介绍 	
		
		printf("请输入新地点的地名:");
		scanf("%s",p);	
		printf("请输入新地点的简介:");
		scanf("%s",i);	
	
		G->vexnum += 1;  //顶点数加1 
	 
		strcpy(G->vex[G->vexnum].name,p); 
		strcpy(G->vex[G->vexnum].info,i); 	
	
		FILE *fp;
		fp = fopen(filename,"at");
		if(fp == NULL){
			printf("\n不能打开!");
			exit(1);
	}
	
	fprintf(fp,"%s\n%s\n",G->vex[G->vexnum].name,G->vex[G->vexnum].info); 
	fclose(fp);

	FILE *fp1;
	fp1 = fopen(filename1,"wt");
	if(fp1 == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	fprintf(fp1,"%d %d\n",G->vexnum,G->arcnum); 
	fclose(fp1);

	printf("\t\t添加地点成功,可打开\"introduce文件\"查看!");  //转义字符 
	printf( "\n\t\t\t\t\t\t是否继续添加地点?\n" );
	printf( "\t\t\t\t\t\t1:是\n" );
	printf( "\t\t\t\t\t\t0:返回上级菜单\n" );
	scanf( "%d", &flag );
	
	}
	system("cls"); 
}

//增加新路线	
void AddRoad(AdjMatrix *G){
	int s,e,weight;
	char filename[30] = "adj.txt";
	char filename1[30] = "flag.txt";
	int flag = 1;
	
	while(flag == 1){
		PrintPlace(G);  //打印地点的序号 
	
   	    printf("请输入增加路线的起点序号:");
		scanf("%d",&s);
		printf("请输入增加路线的终点序号:");
		scanf("%d",&e);
	
		printf("请输入两条路线之间的距离:");
		scanf("%d",&weight);		
		G->arcs[s][e] = G->arcs[e][s] = weight;
		
		FILE *fp;
		fp = fopen(filename,"at");
		if(fp == NULL){
			printf("\n不能打开!");
			exit(1);
		}
		fprintf(fp,"%10d %10d %10d\n",s,e,G->arcs[s][e]);
		fclose(fp);
		
		FILE *fp1;
		fp1 = fopen(filename1,"at");
		if(fp1 == NULL){
			printf("\n不能打开!");
			exit(1);
		}
		
		G->arcnum += 1; //边数+1
		fprintf(fp1,"%d %d\n",G->vexnum,G->arcnum); 
		fclose(fp1); 

		system("cls");
		printf("\t\t添加路线成功,可打开\"adj文件\"查看!");  //转义字符 
		printf( "\n\t\t\t\t\t\t是否继续添加路线?\n" );
		printf( "\t\t\t\t\t\t1:是\n" );
		printf( "\t\t\t\t\t\t0:返回上级菜单\n" );
		scanf( "%d", &flag );
	}
	system("cls"); 
}
	
//删除路线 
void DelRoad(AdjMatrix *G){
	int s,e,weight,i,j;
	char filename[30] = "adj.txt";
	char filename1[30] = "flag.txt";
	int flag = 1;
	
	FILE *fp;
	fp = fopen(filename,"at");
	if(fp == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	FILE *fp1;
	fp1 = fopen(filename1,"wt");
	if(fp == NULL){
		printf("\n不能打开!");
		exit(1);
	}
	
	while(flag == 1){
	
		PrintPlace(G);
	
		printf("请输入撤销路线的起点序号:");
		scanf("%d",&s);
		printf("请输入撤销路线的终点序号:");
		scanf("%d",&e);
	
		//遍历adj文件,如果遍历到s和e,那么给它的值赋予无穷大		
   		G->arcs[s][e] = G->arcs[e][s] = INFINITY;
  		fprintf(fp,"%10d %10d %10d\n",s,e,G->arcs[s][e]);
  	
	  	G->arcnum -= 1; //边数-1
		fprintf(fp1,"%d %d\n",G->vexnum,G->arcnum); 
  		fclose(fp); 
   		fclose(fp1);
		system("cls");
		printf("\t\t撤销路线成功,可打开\"adj文件\"查看!");  //转义字符 
		printf( "\n\t\t\t\t\t\t是否继续撤销路线?\n" );
		printf( "\t\t\t\t\t\t1:是\n" );
		printf( "\t\t\t\t\t\t0:返回上级菜单\n" );
		scanf( "%d", &flag );   		    
   } 
	system("cls"); 	
} 

//游客
void User(){
	int x;
	int dist[MAXVEX];// 记录各条最短路径长度 
	int	path[MAXVEX][MAXVEX] = {0};//记录对应路径上的各顶点
	AdjMatrix G;   //邻接矩阵   
	Create(&G); 
    while(1){
		printf("\t\t\t1. 校园平面图\n");
		printf("\t\t\t2. 地点信息查询\n");
		printf("\t\t\t3. 问路查询\n");
		printf("\t\t\t0. 退出\n"); 
		printf("\t\t\t请选择您需要的操作:");
		scanf("%d",&x);
	
		switch(x){
		case 1: system("cls"); MapOutput(); break;
		case 2: system("cls"); IntroducePlace(G); break;
		case 3: system("cls"); SearchPath(G,dist,path); break;
		case 0: printf("\n\t\t\t\t\t\t\t"); exit(0); break;
		default: printf("\n———————————————输入信息错误,请重新输入!!!————————————————————\n"); break;
		}
	} 
}

//管理员菜单 
void OwnerMeau(AdjMatrix G){
	int c;
	int x;
	int dist[MAXVEX];// 记录各条最短路径长度 
	int	path[MAXVEX][MAXVEX] = {0};//记录对应路径上的各顶点
    while(1){
		printf("\t\t\t1. 添加新地点\n");
		printf("\t\t\t2. 添加新路线\n");
		printf("\t\t\t3. 撤销旧路线\n");
		printf("\t\t\t4. 校园平面图\n");
		printf("\t\t\t5. 地点信息查询\n");
		printf("\t\t\t6. 问路查询\n");
		printf("\t\t\t0. 退出\n"); 
		printf("\t\t\t请选择您需要的操作:");
		scanf("%d",&c);
		getchar();
	
		switch(c){
			case 1: system("cls"); AddPlace(&G); break;
			case 2: system("cls"); AddRoad(&G); break;
			case 3: system("cls"); DelRoad(&G); break;
			case 4: system("cls"); MapOutput(); break;
			case 5: system("cls"); IntroducePlace(G); break;
			case 6: system("cls"); SearchPath(G,dist,path); break;
			case 0: printf("\n\t\t\t\t\t\t\t"); exit(0);
			default: printf("\n———————————————输入信息错误,请重新输入!!!————————————————————\n"); break;	
    	}
	}
}

//管理员登录 
void Owner(){
	int x;
	int dist[MAXVEX];// 记录各条最短路径长度 
	int	path[MAXVEX][MAXVEX] = {0};//记录对应路径上的各顶点
	AdjMatrix G;   //领接矩阵 
	MapFile(G); 
	IntroduceFile(G);  //向文件中存入介绍信息 
	AdjFile(G);    //向文件中存入邻接矩阵信息 
	Create(&G);
	
	system("cls");
	printf("\t\t1.登陆\t\t\t2.注册并登录\n");
    printf("请选择序号:");
    
    while(1){
		scanf("%d",&x);
		switch(x){
		 	case 1:  land(); OwnerMeau(G); break;
			case 2:  enroll(); land(); OwnerMeau(G); break;
			default: printf( "\n———————————————输入无效,请重新正确输入!!!————————————————————\n"); break;
		}		
	} 
}

//主函数 
int main(){
 	int flag;
	
    printf("——————————————————————————————————————————————\n"); 
    printf("\n\t\t\t欢迎使用西安邮电大学长安校区导游系统 !\n\n");   
    printf("——————————————————————————————————————————————\n");
	printf("\n\n\n"); 
	
	//游客or管理员 
	printf("\t\t1.我是游客\t\t\t2.我是管理员\n");
	printf("请选择序号:");
	
	while(1){
		scanf("%d",&flag);
		switch(flag){
		 	case 1: system("cls"); User(); break;
			case 2: system("cls"); Owner(); break;
			default: printf("\n———————————————输入无效,请重新正确输入!!!————————————————————\n"); break;
		}
	} 
}

你可能感兴趣的:(小项目)