数据结构课程设计——景区管理系统
【题目】图的操作和应用之景区信息管理系统
现有一个景区,景区里面有若干个景点,景点之间满足以下条件:
(1) 某些景点之间铺设了道路(相邻)
(2) 这些道路都是可以双向行驶的(无向图)
(3) 从任意一个景点出发都可以游览整个景区(连通图)
开发景区信息管理系统,对景区的信息进行管理。使用图的数据结构来保存景区景点信息,为用户提供创建图、查询景点信息、旅游景点导航、搜索最短路径、铺设电路规划等功能。
(1) 景点信息:景点编号、名字和介绍
编号 |
名字 |
介绍 |
0 |
A区 |
…… |
1 |
B区 |
…… |
2 |
C区 |
…… |
3 |
D区 |
…… |
4 |
E区 |
…… |
5 |
F区 |
…… |
6 |
G区 |
…… |
(2) 道路信息:景点1,景点2、两个景点之间的距离。
景点1 |
景点2 |
距离(m) |
A |
C |
700 |
A |
E |
1000 |
A |
F |
600 |
B |
C |
1000 |
B |
G |
1000 |
C |
D |
400 |
D |
E |
300 |
D |
G |
400 |
E |
F |
600 |
F |
G |
500 |
(1) 读文件创建图
输入:从Vex.txt文件中读取景点信息,从Edge.txt文件中读取道路信息。
处理:根据读取的景区信息创建景区景点图。
(2) 查询景点
输入:想要查询的景点的编号。
处理:根据输入的景点编号,查询该景点及相邻景点的信息。
输出:
① 景点名字
② 景点介绍
③ 相邻景区的名字
④ 到达相邻景区的路径长度
(3) 旅游景点导航
输入:起始景点的编号。
处理:使用深度优先搜索(DFS)算法,查询以该景点为起点,无回路游览整个景区的路线。
输出:所有符合要求的导航路线。
(4) 搜索最短路径
输入:
① 起始景点的编号
② 终点的编号。
处理:使用迪杰斯特拉(Dijkstra)算法,求得从起始景点到终点之间的最短路径,计算路径总长度。
输出:
① 最短路线
② 路径总长度
(5) 铺设电路规划
处理:根据景区景点图使用普里姆(Prim)算法构造最小生成树,设计出一套铺设线路最短,但能满足每个景点都能通电的方案。
输出:
① 需要铺设电路的道路
② 每条道路铺设电路的长度
③ 铺设电路的总长度
(6) 修改图保存文件
插入、删除、修改顶点、边的信息,注意顶点和边的关系,之后保存文件,重新读取文件建立图的存储结构并显示。
重点注意顶点和边的关系,考虑边是否重复?顶点是否存在?……
代码:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
const int MAX = 100;
typedef struct node
{int number;string name;string detel;}Node;//景点信息
typedef struct road
{int x;int y;int high;
}Road;//边节点
void creatmap(node *Nt, road *Tr, int &n, int &m, int map[MAX][MAX])//创建图
{ifstream myfile;myfile.open("Vex.txt", ios::in);//读取景点信息if (!myfile.is_open()){cout << "can not open this file" << endl;}myfile >> n;//景点个数for (int i = 1; i <= n; i++){myfile >> Nt[i].number;myfile >> Nt[i].name;myfile >> Nt[i].detel;}for (int i = 1; i < n + 1; i++){for (int j = 1; j < n + 1; j++){if (i == j)map[i][j] = 0;map[i][j] = 99999;}}//初始化邻接矩阵ifstream myfil;myfil.open("Edge.txt", ios::in);//读取景区图if (!myfil.is_open()){cout << "can not open this file" << endl;}myfil >> m;//边的个数for (int i = 1; i <= m; i++){myfil >> Tr[i].x;myfil >> Tr[i].y;myfil >> Tr[i].high;map[Tr[i].x][Tr[i].y] = Tr[i].high;map[Tr[i].y][Tr[i].x] = Tr[i].high;//储存图}myfile.close();myfil.close();for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){cout << map[i][j] << " ";}cout << endl;//输出图}
}
void search(string NAME, node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int j;for (int i = 0; i < n; i++){if (Nt[i].name == NAME){j = Nt[i].number;cout << Nt[i].number << endl;cout << Nt[i].name << endl;cout << Nt[i].detel << endl;}}//遍历景点数组找到对应信息for (int i = 1; i <= n; i++){if (map[j][i] < 99999 && map[j][i]>0){cout << "相邻的景点为:" << endl; cout << Nt[i].name << endl;cout << Nt[i].detel << endl;cout << "相距:" << map[j][i] << endl;}}//遍历邻接矩阵找到相邻景点}
void DFS(Node *Nt, int i, string path, int c[10], int j, int n, int h, int map[MAX][MAX])//深度优先搜索
{j--;if (j == 0){cout << "第" << h << "条路线:";cout << path << endl;h=h+1;return;}for (int b = 0; b<n; b++){string path1;path1.append(path);int d[10];int e = j;for (int x = 0; x<n; x++)d[x] = c[x];if (map[i][b]<10000 && d[b] == 0){d[b] = 1;path1.append("->");path1.append(Nt[b].name);DFS(Nt, b, path1, d, e, n, h, map);}}
}
void navigation(Node *Nt, int map[MAX][MAX], int n)
{string path;int i;cout << "请输入起始景点的编号:";cin >> i;int j = n;path.append(Nt[i].name);int b[10];//标记数组for (int a =0; a<n; a++)b[a] = 0;//初始化数组b[i] = 1;//标记int h;h = 1;DFS(Nt, i, path, b, j, n, h, map);
}void Dijkstra(int n, int map[MAX][MAX])
{int NUM1; int NUM2;cout << "请输入起点编号:";cin >> NUM1;cout << "请输入终点编号:";cin >> NUM2;int i, k;int min;int u;int dis[MAX];int mark[MAX];//标记数组for (i = 1; i <= n; i++){dis[i] = map[NUM1][i];mark[i] = 0;}mark[NUM1] = 1;for (k = 1; k <= n; k++){min = 99999;for (i = 1; i <= n; i++){if (mark[i] == 0 && min>dis[i]){min = dis[i];u = i;}}mark[u] = 1;for (i = 1; i <= n; i++){if (!mark[i] && dis[i]>dis[u] + map[u][i]){dis[i] = dis[u] + map[u][i];}}}cout << dis[NUM2];
}int MIN(int min1, int min2, int min3, int min4)
{if (min1 <= min2&&min1 <= min3&&min1 <= min4){return 1;}else if (min2 <= min1&&min2 <= min3&&min2 <= min4){return 2;}else if (min3 <= min1&&min3 <= min2&&min3 <= min4){return 3;}else if (min4 <= min1&&min4 <= min2&&min4 <= min3){return 4;}
}
void Prim(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int h, k, l;int mark[MAX];int min = 99999;int min1, min2, min3, min4;int way = 0;for (int i = 1; i <= m; i++){mark[i] = 0;}for (int i = 1; i <= m; i++){if (Tr[i].high < min){min = Tr[i].high;way = min;k = Tr[i].x;h = Tr[i].y;l = i;}}int l1, l2, l3, l4;mark[l] = 1;cout << k << "->" << h << endl;for (int j = 2; j <n; j++){ min1 = 99999;min2 = 99999;min3 = 99999;min4 = 99999;for (int i = 1; i <= m; i++){if (Tr[i].x == k&&mark[i] == 0){if (Tr[i].high < min1){min1 = Tr[i].high;l1 = i;}}if (Tr[i].y == k&&mark[i] == 0){if (Tr[i].high < min2){min2 = Tr[i].high;l2 = i;}}if (Tr[i].x == h&&mark[i] == 0){if (Tr[i].high < min3){min3 = Tr[i].high;l3 = i;}}if (Tr[i].y == h&&mark[i] == 0){if (Tr[i].high < min){min4 = Tr[i].high;l4 = i;}}}int q = MIN(min1, min2, min3, min4);if (q == 1){cout << k;way = way + min1;k = Tr[l1].y;mark[l1] = 1;cout << "->" << k << endl;}else if (q == 2){cout << k;way = way + min2;k = Tr[l2].x;mark[l2] = 1;cout << "->" << k << endl;}else if (q == 3){cout << h;way = way + min3;h = Tr[l3].y;mark[l3] = 1;cout << "->" << h << endl;}else if (q == 4){cout << h;way = way + min4;h = Tr[l4].x;mark[l4] = 1;cout << "->" << h << endl;}}cout << "总长度为:" << way << endl;
}void revisenode(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a;cout << "请输入要修改的景区编号" << endl;cin >> a;while (a > n || a < 1){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a;}cout << "请输入修改后景点的信息" << endl;cout << "请输入修改后的名字:";cin >> Nt[a].name;cout << "请输入修改后的描述";cin >> Nt[a].detel;ofstream outfile;outfile.open("Vex.txt", ios::trunc);outfile << n << endl;for (int i = 1; i <= n; i++){outfile << Nt[i].number << endl;outfile << Nt[i].name << endl;outfile << Nt[i].detel << endl;}outfile.close();cout << "修改完毕";
}
void reviseroad(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a, b, c;cout << "请输入对应边的两个景点:";cin >> a >> b;while ((a > n || a < 1) && (b > n || b < 1)){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a >> b;}cout << "修改后请输入边的长度";cin >> c;map[a][b] = c;map[b][a] = c;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if (map[i][j]<99999 && map[i][j]>0){for (int k = 1; k <= m; k++){if (Tr[k].x == i&&Tr[k].y == j){Tr[k].high = map[i][j];}}}}}ofstream outfile;outfile.open("Edge.txt", ios::trunc);outfile << m << endl;for (int i = 1; i <= m; i++){outfile << Tr[i].x << " " << Tr[i].y << " " << Tr[i].high << endl;}outfile.close();cout << "修改完毕";}
void revise(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a;cout << " 1:修改景点 " << endl;cout << " 2:修改边 " << endl;cout << "功能选择";cin >> a;while (a > 2 || a < 1){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a;}switch (a){case 1:{revisenode(Nt, Tr, n, m, map);break;}case 2:{reviseroad(Nt, Tr, n, m, map);break;}}}void delnode(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a, b;b = 1;cout << "请输入要删除景点的编号" << endl;cin >> a;while (a > n || a < 1){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a;}for (int i = a; i < n; i++){Nt[i].name = Nt[i + 1].name;Nt[i].detel = Nt[i + 1].detel;}n = n - 1;for (int i = 1; i < a; i++){for (int j = a; j <= n; j++){map[i][j] = map[i][j + 1];map[j][i] = map[j + 1][i];}}for (int i = a; i <= n; i++){for (int j = a; j <= n; j++){map[i][j] = map[i + 1][j + 1];}}for (int i = 1; i <= n + 1; i++){map[n + 1][i] = 99999;map[i][n + 1] = 99999;}for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if (map[i][j]<99999 && map[i][j]>0 && i < j){Tr[b].x = i;Tr[b].y = j;Tr[b].high = map[i][j];b++;}}}m = b - 1;ofstream outfile;outfile.open("Vex.txt", ios::trunc);outfile << n << endl;for (int i = 1; i <= n; i++){outfile << Nt[i].number << endl;outfile << Nt[i].name << endl;outfile << Nt[i].detel << endl;}ofstream outfil;outfil.open("Edge.txt", ios::trunc);outfil << m << endl;for (int i = 1; i <= m; i++){outfil << Tr[i].x << " " << Tr[i].y << " " << Tr[i].high << endl;}outfile.close();outfil.close();cout << "删除完毕";
}
void delroad(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a, b, q;int k = 0;int h = 0;q = 1;cout << "请输入对应边的两个景点";cin >> a >> b;while ((a > n || a < 1) && (b > n || b < 1)){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a >> b;}map[a][b] = 99999;map[b][a] = 99999;for (int i = 1; i <= n; i++){if (map[a][i] < 99999 && map[a][i]>0)k++;}if (k == 0){n = n - 1;for (int i = 1; i < a; i++){for (int j = a; j <= n; j++){map[i][j] = map[i][j + 1];map[j][i] = map[j + 1][i];}}for (int i = a; i <= n; i++){for (int j = a; j <= n; j++){map[i][j] = map[i + 1][j + 1];}}}for (int i = 1; i <= n; i++){if (map[b][i] < 99999 && map[b][i]>0)h++;}if (h == 0){n = n - 1;for (int i = 1; i < b; i++){for (int j = b; j <= n; j++){map[i][j] = map[i][j + 1];map[j][i] = map[j + 1][i];}}for (int i = b; i <= n; i++){for (int j = b; j <= n; j++){map[i][j] = map[i + 1][j + 1];}}}for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if (map[i][j]<99999 && map[i][j]>0 && i<j){Tr[q].x = i;Tr[q].y = j;Tr[q].high = map[i][j];q++;}}}m = q - 1;ofstream outfile;outfile.open("Vex.txt", ios::trunc);outfile << n << endl;for (int i = 1; i <= n; i++){outfile << Nt[i].number << endl;outfile << Nt[i].name << endl;outfile << Nt[i].detel << endl;}ofstream outfil;outfil.open("Edge.txt", ios::trunc);outfil << m << endl;for (int i = 1; i <= m; i++){outfil << Tr[i].x << " " << Tr[i].y << " " << Tr[i].high << endl;}outfile.close();outfil.close();cout << "删除完毕";
}
void del(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a;cout << " 1:删除景点 " << endl;cout << " 2:删除边 " << endl;cout << "功能选择";cin >> a;while (a > 2|| a < 1){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a;}switch (a){case 1:{delnode(Nt, Tr, n, m, map);break;}case 2:{delroad(Nt, Tr, n, m, map);break;}}
}
void insectnode(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a, b, c;int d = 1;n = n + 1;cout << "请输入新加点的名字:";cin >> Nt[n].name;cout << "请输入描述:";cin >> Nt[n].detel;Nt[n].number = n;for (int i = 1; i < n; i++){map[n][i] = 99999;map[i][n] = 99999;}map[n][n] = 0;cout << "请输入与新加景点相邻点的个数:";cin >> c;for (int i = 1; i <= c; i++){cout << "请输入与新加景点相邻的第" << i << "景点的编号,及路径长:";cin >> a >> b;while (a >= n || a < 1){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a >> b;}map[n][a] = b;map[a][n] = b;}for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if (map[i][j]<99999 && map[i][j]>0 && i<j){Tr[d].x = i;Tr[d].y = j;Tr[d].high = map[i][j];d++;}}}m = d - 1;ofstream outfile;outfile.open("Vex.txt", ios::trunc);outfile << n << endl;for (int i = 1; i <= n; i++){outfile << Nt[i].number << endl;outfile << Nt[i].name << endl;outfile << Nt[i].detel << endl;}ofstream outfil;outfil.open("Edge.txt", ios::trunc);outfil << m << endl;for (int i = 1; i <= m; i++){outfil << Tr[i].x << " " << Tr[i].y << " " << Tr[i].high << endl;}outfile.close();outfil.close();cout << "插入完毕";
}
void insectroad(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a, b, c;int d = 1;cout << "请输入两个顶点:";cin >> a >> b;while (map[a][b]<99999 && map[a][b]>0){cout << "错误输入,请重新输入正确的操作:";cin >> a >> b;}cout << "请输入对应边长:";cin >> c;map[a][b] = c;map[b][a] = c;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){if (map[i][j]<99999 && map[i][j]>0 && i<j){Tr[d].x = i;Tr[d].y = j;Tr[d].high = map[i][j];d++;}}}m = d - 1;ofstream outfil;outfil.open("Edge.txt", ios::trunc);outfil << m << endl;for (int i = 1; i <= m; i++){outfil << Tr[i].x << " " << Tr[i].y << " " << Tr[i].high << endl;}outfil.close();cout << "插入完毕";}void insect(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a;cout << " 1:插入景点 " << endl;cout << " 2:插入边 " << endl;cout << "功能选择";cin >> a;while (a > 2 || a < 1){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a;}switch (a){case 1:{insectnode(Nt, Tr, n, m, map);break;}case 2:{insectroad(Nt, Tr, n, m, map);break;}}
}
void reseve(node *Nt, road *Tr, int n, int m, int map[MAX][MAX])
{int a;cout << " 1:修改 " << endl;cout << " 2:删除 " << endl;cout << " 3:添加 " << endl;cout << "功能选择:";cin >> a;while (a > 3 || a < 1){cout << "错误输入,请重新输入正确的操作:" << endl;cin >> a;}switch (a){case 1:{cout << "1" << endl;revise(Nt, Tr, n, m, map);break;}case 2:{cout << "2" << endl;del(Nt, Tr, n, m, map);break;}case 3:{cout << "3" << endl;insect(Nt, Tr, n, m, map);break;}}
}
void welcome(node *Nt, road *Tr, int n, int map[MAX][MAX], int m)
{system("color A");cout << "\t\t\t *********************************************" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t 景区旅游信息管理系统 *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t" << " ☆" << " 1 创建景区景点分布图 ☆ *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t" << " ☆" << " 2 查询景点信息 ☆ *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t" << " ☆" << " 3 旅游景点导航 ☆ *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t" << " ☆" << " 4 搜索最短路径 ☆ *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t" << " ☆" << " 5 输出道路修建规划图 ☆ *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t" << " ☆" << " 6 修改景区信息 ☆ *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *\t" << " ☆" << " 7 退出 ☆ *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t * *" << endl;cout << "\t\t\t *********************************************" << endl;cout << "功能选择 >> : ";int c;do{cin >> c;switch (c){case 1:{creatmap(Nt, Tr, n, m, map);cout << "创建成功";break;}case 2:{string NAME;cout << "请输入查找的景点名:";cin >> NAME;search(NAME, Nt, Tr, n, m, map);cout << "";break; }case 3:{navigation(Nt, map, n);break;}case 4:{Dijkstra(n, map);break;}case 5:{Prim(Nt, Tr, n, m, map);break;}case 6:{reseve(Nt, Tr, n, m, map);break;}case 7:{cout << "谢谢使用"; break; }default:{cout << "错误输入,请重新输入"; break; }}if (c == 7)break;} while (1);
}
int main()
{int n = 0;int m = 0;Node Nt[MAX];Road Tr[MAX];int map[MAX][MAX];welcome(Nt, Tr, n, map, m);system("purse");return 0;
}
数据文件:
运行截图:
删除修改的就不做出截屏了,实在是比较麻烦,要十几张截图,你们可以把代码复制下去运行试试;
****值得注意的是txt文件要和源代码文件放在同一个文件夹内,如图:
数据结构课程设计——景区管理系统相关推荐
- java数据结构通讯录管理系统_数据结构课程设计—通讯录管理系统
浊贤平鲁冠城美华道钉.内急顺美兴华品红缺点清屏!车组悬吊嗉囊沥胆情愿,城东兴荣规划管涌铺板?轻奏便装壳菜蓝坛卵石数据结构课程设计-通讯录管理系统.缪斯朝圣美金放下隆暑路权. 当年绸巾登封轮滑殴伤调理电 ...
- python通讯录管理系统设计_数据结构课程设计-通讯录管理系统(C语言版)
##数据结构课程设计-通讯录管理系统 一,前言 自从上次C语言课设写完后,这次数据结构课设就写的游刃有余了,很快啊,不足三天就写完了它(年轻人不讲武德),如果你认真看过我之前写的C语言课程设计-球队管 ...
- 数据结构课程设计—同学录管理系统(c语言)
数据结构课程设计-同学录管理系统(c语言) 文章目录 前言 一.需求分析 二.总体设计 三.代码实现 四.代码说明 前言 计算机相关专业在学习数据结构这门课程时会有课程设计,我被分配到的是同学录管理系 ...
- c语言数据结构课程设计停车场管理系统,数据结构课程设计报告停车场管理系统...
<数据结构课程设计报告停车场管理系统>由会员分享,可在线阅读,更多相关<数据结构课程设计报告停车场管理系统(8页珍藏版)>请在人人文库网上搜索. 1.数据结构课程设计报告系 别 ...
- 数据结构课程设计-停车场管理系统
利用前面所建立的算法库基础进行的课程设计,名曰停车场管理系统 具体利用顺序栈以及链队等知识 当车辆进入时,输入车辆车牌号码并且自动获取当前系统时间. 具体请运行代码. parking.h: 包含定义顺 ...
- 数据结构课程设计 物流管理系统
1 问题描述 在当今的电子商务时代,全球物流产业有了新的发展趋势.现代物流服务的核心目标是在物流全过程中以最小的综合成本来满足顾客的需求. 在这个"互联网+"的时代,众多的学者研究 ...
- 数据结构课程设计图书管理系统,C语言版。
目录 一.功能描述 二.设计要求 三.实现的功能 四.代码 一.功能描述 设计一个图书管理程序满足图书馆基本业务需求. 二.设计要求 每种书的登记内容包括书号.书名.著作者.现存量和库存量等: 对书号 ...
- 数据结构课程设计--实验室设备管理系统(c语言)
#include <stdio.h> //标准输入输出函数库 #include <stdlib.h> //标准函数库 #include <string.h> //字 ...
- 数据结构课程设计——通讯录管理系统
[问题描述] 建立一个手机通讯录系统.手机通讯录中的联系人的信息既可以存储在手机中,也可以存储在手机卡中,也可以同时存储在两个位置上.存储在手机卡的联系人的信息只包含用户名和电话号码两项信息.存储在手 ...
最新文章
- android 当前置顶的控件,Android利用RecyclerView实现全选、置顶和拖拽功能示例
- python爬虫自学网站_Python爬虫3步曲:5分钟学习用Python解析网页
- Spark算子:RDD基本转换操作–coalesce、repartition
- HTML5新增属性学习笔记
- 海纳威上云 构建数字化透明工厂
- 通过延迟加载和代码拆分提高网站性能
- python 第13章:面向对象编程
- unix操作系统设计高清中文
- 配置管理工具应该具有的一般特性
- angular-Forms patchValue and setValue
- RS485通信与Modbus协议
- Linux系统下,redis集群的搭建
- #榜样的力量#百融云创智能语音防疫公益项目丨数据猿新冠战“疫”公益策划...
- bilibili 弹幕协议分析,golang 还原代码
- 【redis集群:2. 集群伸缩】
- 模电数电单片机综合开发系统实验装置QY-MS535K
- 三款国产操作系统使用初步体验
- python模拟足球_python 足球模拟
- ARM NEON寄存器
- 动态八卦图html,HTML绘制太极八卦图