校园景点导航系统(C with STL)

// 校园导航系统
#include <bits/stdc++.h>
#include <windows.h>
using namespace std;
#define INF 100000 // 无穷
int k;			   // 景点个数

typedef struct
{
	int num;		   // 编号
	char name[10];	   // 名称
	char message[300]; // 信息
} sight;			   // 景点

typedef struct
{
	sight si[101];			  // 景点
	int edges[101][101];	  // 邻接矩阵
	int vertex_num, edge_num; // 点数和边数
} Campus;

void Get_campus(Campus &c);						   // 读取文件信息创建校园图
void Display_menu();							   // 显示主页面
int Select_choice(Campus &c);					   // 选择要实现的功能
void Print_campus();							   // 打印校园地图
int Check_choice(string &s);					   // 判断输入的景点编号是否合法
void Search_sightdata(Campus &c);				   // 校园景点信息查询
void Floyd_shortpath(Campus &c);				   // 求两景点间最短路径
void Achieve_shortpath(Campus &c, int st, int en); // 打印两点间最短路径(无输入)
void Print_shortpath(Campus &c);				   // 打印两景点间最短路径
void DFS_allpath(Campus &c, int st, int en);	   // 求两景点间所有路径
void Print_allpath(Campus &c);					   // 打印两景点间所有路径
void Amount_bestpath(Campus &c);				   // 求多景点间最佳访问路线

void Display_menu()
{
	cout << "\t\t┌──────────────────────── 郑州大学校园景点导航系统 ────────────────────────┐" << endl;
	cout << "\t\t│                                                                          │" << endl;
	cout << "\t\t│                                                                          │" << endl;
	cout << "\t\t│   ┌────────────────────────────┐        ┌────────────────────────────┐   │" << endl;
	cout << "\t\t│   │ 1.校园景点地图一览         │        │ 2.校园景点信息查询         │   │" << endl;
	cout << "\t\t│   └────────────────────────────┘        └────────────────────────────┘   │" << endl;
	cout << "\t\t│                                                                          │" << endl;
	cout << "\t\t│   ┌────────────────────────────┐        ┌────────────────────────────┐   │" << endl;
	cout << "\t\t│   │ 3.两景点间最短路径查询     │        │ 4.两景点间所有路径查询     │   │" << endl;
	cout << "\t\t│   └────────────────────────────┘        └────────────────────────────┘   │" << endl;
	cout << "\t\t│                                                                          │" << endl;
	cout << "\t\t│   ┌────────────────────────────┐        ┌────────────────────────────┐   │" << endl;
	cout << "\t\t│   │ 5.多景点间访问路线查询     │        │  6.退出校园景点导航系统    │   │" << endl;
	cout << "\t\t│   └────────────────────────────┘        └────────────────────────────┘   │" << endl;
	cout << "\t\t│                                                                          │" << endl;
	cout << "\t\t└──────────────────────────────────────────────────────────────────────────┘" << endl
		 << endl;
	cout << "-->请选择下一步你要进行的操作" << endl;
}

int Check_choice(string &s) // 增强程序的健壮性
{
	while (1)
	{
		int choice;
		int num = 0;
		int flag = 1;
		for (int i = 0; i < s.length(); i++) // 将字符串转化为数字
			if (s[i] < '0' && s[i] > '9')
			{
				flag = 0;
				cout << "请输入数字!" << endl;
				break;
			}
			else
			{
				num = num * 10 + s[i] - '0';
			}
		if (flag)
		{
			if (num < 0 || num > k)
			{
				cout << "输入不合法,请选择数字1~" << k << "输入!" << endl;
				cin >> s;
			}
			else
				return num;
		}
	}
}

int Select_choice(Campus &c)
{
	string choice;
	while (1)
	{
		cin >> choice;
		int num = 0;
		int flag = 1;
		for (int i = choice.length() - 1; i >= 0; i--)
			if (choice[i] < '0' && choice[i] > '9')
			{
				flag = 0;
				cout << "请输入正确的操作编号:" << endl;
				break;
			}
			else
			{
				num = num * 10 + choice[i] - '0';
			}

		if (flag)
			switch (num)
			{
			case 1: // 打印校园地图
				system("cls");
				Display_menu();
				Print_campus();
				cout << "-->请选择下一步你要进行的操作" << endl;
				break;
			case 2: // 景点信息查询
				system("cls");
				Display_menu();
				Search_sightdata(c);
				cout << "-->请选择下一步你要进行的操作" << endl;
				break;
			case 3: // 两点间最短路径
				system("cls");
				Display_menu();
				Print_shortpath(c);
				cout << "-->请选择下一步你要进行的操作" << endl;
				break;
			case 4: // 两点间所有路径
				system("cls");
				Display_menu();
				Print_allpath(c);
				cout << "-->请选择下一步你要进行的操作" << endl;
				break;
			case 5: // 多景点间最佳路径
				system("cls");
				Display_menu();
				Amount_bestpath(c);
				cout << "-->请选择下一步你要进行的操作" << endl;
				break;
			case 6: // 退出系统
				system("cls");
				cout << "程序将在5秒内关闭";
				Sleep(5000);
				exit(0);
			default:
				cout << "请输入正确的操作编号:" << endl;
			}
	}
}

void Get_campus(Campus &c)
{
	FILE *f;
	f = fopen("E:\\vscode\\design\\mapabcdefg.txt", "r");
	if (!f)
	{
		cout << "文件无法打开,初始化失败,请检查文件" << endl;
		Sleep(5000);
		exit(1);
	}
	else
	{
		fscanf(f, "%d%d", &c.vertex_num, &c.edge_num); // 读取点数和边数
		k = c.vertex_num;
		for (int i = 1; i <= c.vertex_num; i++)
		{
			fscanf(f, "%d%s%s", &c.si[i].num, &c.si[i].name, &c.si[i].message); // 读取景点信息
			for (int j = 1; j <= c.vertex_num; j++)								// 初始化邻接矩阵
			{
				if (i == j)
					c.edges[i][j] = 0;
				else
					c.edges[i][j] = INF;
			}
		}
		for (int t = 0; t < c.edge_num; t++) // 完善邻接矩阵
		{
			int i, j, len;
			fscanf(f, "%d%d%d", &i, &j, &len);
			c.edges[i][j] = c.edges[j][i] = len;
		}
	}
	fclose(f);
}

void Print_campus()
{
	cout << "\t\t\t  ┌───     北 体  ──────────────────────────────────┐" << endl;
	cout << "\t\t\t  │     1)                                          │" << endl;
	cout << "\t\t\t  │        操 场                                    │" << endl;
	cout << "\t\t\t  │             \\                                   │" << endl;
	cout << "\t\t\t  │              \\                                  │" << endl;
	cout << "\t\t\t  │                 厚                              │" << endl;
	cout << "\t\t\t  │─────────────  3)   ─────────────────────────────│" << endl;
	cout << "\t\t\t  │                 山                              │" << endl;
	cout << "\t\t\t  │                 │                               │" << endl;
	cout << "\t\t\t  │                 │                               │" << endl;
	cout << "\t\t\t  │     本源        眉      钟       图      启 明  │" << endl;
	cout << "\t\t\t  │─  2)    ───  6)   ─  4)   ─  5)  书 ─  10)     ─│" << endl;
	cout << "\t\t\t  │    体育场       湖      楼       馆      广 场  │" << endl;
	cout << "\t\t\t  │                 │                               │" << endl;
	cout << "\t\t\t  │                 │                               │" << endl;
	cout << "\t\t\t  │             7) 松 林                            │" << endl;
	cout << "\t\t\t  │                 │                               │" << endl;
	cout << "\t\t\t  │           8) 樱 花 林                           │" << endl;
	cout << "\t\t\t  │                 │                               │" << endl;
	cout << "\t\t\t  │     ┌───  12) 校 史 馆 ─────────────────────────│" << endl;
	cout << "\t\t\t  │     │           │                               │" << endl;
	cout << "\t\t\t  └─ 9)南 操─── 11)五星广场─────────────────────────┘" << endl;
}

void Search_sightdata(Campus &c)
{
	Print_campus();
	cout << "-->请输入你所要查询景点的编号" << endl;
	string i;
	cin >> i;
	int j;
	j = Check_choice(i);
	cout << "此景点信息如下:" << endl;
	cout << "景点编号:" << c.si[j].num << endl;
	cout << "景点名称:" << c.si[j].name << endl;
	cout << "景点介绍:" << c.si[j].message << endl;
}

int dist[101][101];				// 路径距离
int path[101][101];				// 路径中继点
void Floyd_shortpath(Campus &c) // 利用弗洛伊德算法求出两点间最短路径
{
	for (int i = 1; i <= c.vertex_num; i++)
		for (int j = 1; j <= c.vertex_num; j++)
		{
			dist[i][j] = c.edges[i][j];
			if (i != j && dist[i][j] < INF)
				path[i][j] = i; // 表明i和j相邻
			else
				path[i][j] = -1; // 表明无法直接到达j
		}
	for (int t = 1; t <= c.vertex_num; t++)
		for (int i = 1; i <= c.vertex_num; i++)
			for (int j = 1; j <= c.vertex_num; j++)
			{
				if (dist[i][j] > (dist[i][t] + dist[t][j]))
				{
					dist[i][j] = dist[i][t] + dist[t][j];
					path[i][j] = t; // 表面i可通过t点最短到达j
				}
			}
}

void Achieve_shortpath(Campus &c, int st, int en) // 打印两点间最短路径(无输入)
{
	if (path[st][en] == st)
		return;
	else
	{
		Achieve_shortpath(c, st, path[st][en]);	 // 将中间点作为终点继续打印路径
		cout << c.si[path[st][en]].name << "->"; // 打印中间景点名字
		Achieve_shortpath(c, path[st][en], en);	 // 将中间点作为起点继续打印路径
	}
}

void Print_shortpath(Campus &c) // 打印两点间最短路径(附输入)
{
	Print_campus();
	string st1, en1;
	int st, en;
	cout << "请输入起点编号" << endl;
	cin >> st1;
	st = Check_choice(st1);
	cout << "请输入终点编号" << endl;
	cin >> en1;
	en = Check_choice(en1);
	cout << c.si[st].name << "->";
	Achieve_shortpath(c, st, en);
	cout << c.si[en].name << endl;
	cout << "路径总长度为:" << dist[st][en] << "米" << endl;
}

vector<int> road; // 路径
int num;		  // 路径个数
int visited[101]; // 是否访问
void DFS_allpath(Campus &c, int st, int en)
{
	int kilo = 0;
	road.push_back(st);
	visited[st] = 1;
	for (int i = 1; i <= c.vertex_num; i++) // 遍历所有点
	{
		if (c.edges[st][i] != 0 && c.edges[st][i] != INF && !visited[i]) // 找出可到达且不是本身且未访问过的点
		{
			if (i == en) // 到达终点
			{
				cout << "第" << num << "条路:";
				num++;
				for (int j = 0; j < road.size(); j++)
				{
					cout << c.si[road[j]].name << "->";
					if (j < road.size() - 1)
						kilo += c.edges[road[j]][road[j + 1]];
				}
				kilo += c.edges[road[road.size() - 1]][i];
				cout << c.si[en].name;
				cout << "\t路径总长度为" << kilo << "米" << endl;
			}
			else
			{
				DFS_allpath(c, i, en);
				road.pop_back();
				visited[i] = 0;
			}
		}
	}
}

void Print_allpath(Campus &c)
{
	Print_campus();
	string st1, en1;
	int st, en;
	num = 1;
	road.clear();
	for (int i = 0; i < k + 1; i++)
		visited[i] = 0;
	cout << "请输入起点编号" << endl;
	cin >> st1;
	st = Check_choice(st1);
	cout << "请输入终点编号" << endl;
	cin >> en1;
	en = Check_choice(en1);
	DFS_allpath(c, st, en);
}

void Amount_bestpath(Campus &c)
{
	Print_campus();
	int kilo = 0, temp = 1;
	vector<int> visit;
	do
	{
		cout << "请输入你想游览的第" << temp << "个景点的编号(输入0结束):" << endl;
		string i;
		cin >> i;
		if (i == "0")
			break;
		else
		{
			int j;
			j = Check_choice(i);
			visit.push_back(j);
			temp++;
		}
	} while (1);
	if (temp == 1)
		return;
	cout << "为您挑选的最佳路径如下:" << endl;
	for (int i = 0; i < visit.size() - 1; i++)
	{
		cout << c.si[visit[i]].name << "->";
		Achieve_shortpath(c, visit[i], visit[i + 1]);
		kilo += dist[visit[i]][visit[i + 1]];
	}
	cout << c.si[visit[visit.size() - 1]].name;
	cout << "\t路径总长度为" << kilo << "米" << endl;
}

int main()
{
	// 初始化系统
	Campus c;
	Get_campus(c);
	Floyd_shortpath(c);
	Display_menu();
	Select_choice(c);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值