使用opengl和c++实现迷宫地图的路径搜索和显示(基于DFS)

写在前面,本人计算机专业渣渣,这是我的第一篇博客,代码写的不好,仅作我的学习记录吧。


最近学校编程实验课的一道作业,要求完成迷宫的路径搜索,用c++完成。本渣渣花了几天的时间加上在网上参考大神们的源码,终于基本上完成任务了,现在贴出来做个记录(ps.刚刚基本了解了一下markdown的语法,所以排版请见谅啦)
迷宫的路径搜索算法请示就是一个图的深度优先搜索。本人大二,正在学习数据结构,也是刚刚才接触DFS,虽然基本上了解了DFS的含义,但是第一次编程实现还是有一定困难的,刚开始的话,因为自己对递归调用不熟悉嘛,所以手动用循环实现基本功能(循环实现stack功能,应该是吧),但是只能算完成了50%吧,只能实现寻找一条通路,不能找到全部通路。尴尬!这里就不贴啦(代码已经被我改的乱七八糟,不忍直视了!)
后来查了资料使用递归方法实现了多条路径的搜索
主要问题在于如何判断在找到终点后回退回去重新寻找的过程

我的代码如下:

  //这是stack.h头文件,自己实现的模拟栈操作(自己造轮子哦,但是很惨)//一开始总是无法实现功能,反复查找问题,发现查找路径主体应该没有问题,检查了一下//自己写的stack,结果有基础数据写错了,差个1这样的,这个应该很常见吧,翻车了,正//是个悲伤地故事#include<iostream>
using namespace std;
struct node
{int x;int y;int d;//表示下个节点的方向bool operator== (node t){if (this->x == t.x&&this->y == t.y)return true;elsereturn false;}node(int x, int y){this->x = x;this->y = y;}void set_node(int x, int y){this->x = x;this->y = y;}node() = default;
};
// struct post
// {//  node sites;
//  int num; //路径的第几个节点
// };
class stack
{
private:node* head;int top;int size;
public:stack(int s){size = s;head = new node[s];top = -1;}stack(const stack &other) //拷贝构造函数{top = other.top;size = other.size;head = new node[size];for (int i = 0; i <= top; i++){head[i] = other.head[i];}}bool isempty(){if (top == -1)return true;elsereturn false;}bool isfull(){if (top == size - 1)return true;elsereturn false;}void push_back(node e){if (!isfull()){head[++top] = e;}else{int temsize = 2 * size;node* tem = new node[temsize];for (int i = 1; i < size / 2; i++){tem[i] = head[i];}delete head;head = tem;size = temsize;head[++top] = e;}}bool pop_back(node& e){if (!isempty()){e = head[top--];return true;}else{return false;}}void clear(){top = -1;}void des(){delete head;}node operator[](int i){return head[i];}int getUsedsize(){return top + 1;}
};

下面是查找路径的代码

//find_map.h头文件#include "stack.h"#include<fstream>#include<vector>#include<string>#include<sstream>class find_map
{
private:vector<vector<char>> map;//      char map[10][10] = { //      { '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'},//      { '1', '0', '1', '1', '0', '0', '0', '1', '1', '1'},//      { '1', '0', '0', '0', '0', '1', '0', '1', '1', '1'},//      { '1', '1', '1', '1', '1', '1', '0', '1', '1', '1'},//      { '1', '1', '1', '1', '0', '0', '0', '1', '1', '1'},//      { '1', '1', '1', '1', '0', '0', '1', '1', '1', '1'},//      { '1', '1', '1', '0', '0', '1', '1', '1', '1', '1'},//      { '1', '1', '1', '0', '1', '1', '1', '1', '1', '1'},//      { '1', '1', '1', '0', '0', '1', '1', '1', '1', '1'},//      { '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'}//  };//迷宫数据,开始测试用的,完成后可以从文件读取数据(1为墙,0位空)int rows = 10;int columns = 10;node start;node end;vector<stack> sta;//存储路径
public:find_map(){rows = 0;columns = 0;cout << "请输入要读取的文件路径:" << endl;string filepath;cin >> filepath;ifstream readmap(filepath);if (readmap){string aLine;while (getline(readmap, aLine)){istringstream Line(aLine);char tem;vector<char> temline;while (Line >> tem){temline.push_back(tem);}map.push_back(temline);}rows = map.size() - 2;columns = map[0].size();start.set_node(map[rows][0] - 48, map[rows][1] - 48); //char to intend.set_node(map[rows + 1][0] - 48, map[rows + 1][1] - 48);}else{cout << "打开文件失败!";exit(-1);}}void pf(){for (int i = 0; i < rows; i++){for (int j = 0; j < columns; j++){cout << map[i][j] << ' ';}cout << endl;}//      cout << (int)map[rows][0]-48 << endl;//      cout << rows << endl;//      cout << columns << endl;//      cout << start.x << ' ' << start.y << endl;//      cout << end.x << ' ' << end.y << endl;}bool isgo(node nownode){if (map[nownode.x][nownode.y] == '0')return true;elsereturn false;}void recovrey(){for (auto &i : map){for (auto &j : i){if (j == '@')j = '0';}}}void setpass(node tem) //表示可以通过{map[tem.x][tem.y] = '*';}node nextnode(node tem, int i) //1,2,3,4表示要走的方向{node next;next.x = tem.x;next.y = tem.y;switch (i){case 1:next.y = next.y + 1; break; //向右走case 2:next.x = next.x + 1; break; //向下走case 3:next.y = next.y - 1; break; //向左走case 4:next.x = next.x - 1; break; //向上走}return next;}void setNotPass(node tem) //表示走过但无法通过{map[tem.x][tem.y] = '@';}void setRecover(node tem) //表示走过但无法通过{map[tem.x][tem.y] = '0';}//核心代码 寻找路径bool find_path(){bool statu = false;stack path(rows*columns);node nownode; //现在位置int temnum = 1; //节点在路径的位置int nextfoot = 1; //下一步方向nownode = start;nownode.d = nextfoot;do{if (isgo(nownode)){setpass(nownode); //留下足迹if (nownode.x == end.x&&nownode.y == end.y) //查找成功{nownode.d = 4;path.push_back(nownode);statu = true;sta.push_back(path);//压入栈中temnum++;//                  if (temnum == 3)//                  {//                  return true;//                  }}else{nextfoot = 1;nownode.d = nextfoot;path.push_back(nownode);nownode = nextnode(nownode, nextfoot); //寻找下一个步//nownode.d = nextfoot;//nextfoot++;}}else //当前位置不通{if (!path.isempty()){path.pop_back(nownode);nextfoot = nownode.d;//cout<<'(' << nownode.x <<','<< nownode.y<<')' << endl;map[nownode.x][nownode.y] = '0';while (nownode.d == 4 && !path.isempty()){//setNotPass(e.sites);//setRecover(e.sites);path.pop_back(nownode);nextfoot = nownode.d;map[nownode.x][nownode.y] = '0';}if (nownode.d < 4){nextfoot++; //转换方向//nownode = nextnode(nownode, nextfoot);nownode.d = nextfoot;path.push_back(nownode);setpass(nownode);nownode = nextnode(nownode, nextfoot);}}}} while (!path.isempty());//path.des(); //销毁栈return statu;}//存储迷宫数据到文件void storage_map(){ofstream out("结果.txt");for (auto i : map){for (auto j : i)out << j << ' ';out << endl;}int num = 1;for (auto i : sta){out << "第" << num << "条路径为:" << endl;out << "start" << "->";for (int j = 0; j < i.getUsedsize(); j++){out << "(" << i[j].x << ',' << i[j].y << ')' << "->";}out << "end" << endl;num++;}}void seeout(){for (auto i : map){for (auto j : i)cout << j << ' ';cout << endl;}int num = 1;cout << sta.size()<<endl;for (int i = 0; i < sta.size(); i++){cout << "第" << num << "条路径为:" << endl;cout << "start" << "->";for (int j = 0; j < sta[i].getUsedsize(); j++){cout << "(" << sta[i][j].x << ',' << sta[i][j].y << ')' << "->";}cout << "end" << endl;num++;}}
};

主函数(没什么功能,哈哈~~~)

int main()
{find_map t;cout << "读入地图数据:" << endl;t.pf();cout << endl;vector<stack> a; //储存路径if (t.find_path()){cout << "找到路径:" << endl;t.pf();//t.storage_map();t.seeout();}elsecout << "未找到路径!";
}

赶着去上课,OpenGL图形界面的实现晚上回来再贴喽(悲伤脸)


好啦,上课回来啦
接着写
其实迷宫的图形化实现也是作业的要求啦,不过是选做啦,正巧,选修了计算机图形学,学了点OpenGL的语法,所以就想用OpenGL实现以下迷宫的二维图形化,其实也挺简单的,就是调用OpenGL的简单画线和画四边形的代码组织一下实现的,代码有点渣渣,高手请指教。本来想
使用上面写好的find_map头文件实现的,但是发现OpenGL绘图要调用类的成员函数有点麻烦
,好吧,我放弃了(就是这么懒,好气哦)

OpenGL绘图实现

#include "stack.h"
#include<fstream>
#include<vector>
#include<string>
#include<sstream>
#include<algorithm>
#include <gl/glut.h>
#include <gl/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>//设置地图大小
#define SCREEN_WIDTH 20
#define SCREEN_HEIGHT 20vector<vector<char>> map; //存储迷宫
int rows = 10;
int columns = 10;
node start; //数组中的开始位置
node mend; //数组中的结束位置
vector<stack> sta;//存储路径
bool ans = false;//OpenGL 数据
float startx , starty ; //OpenGL的开始坐标
float endx , endy ; //OpenGL的结束坐标//定义函数
void find_map()
{rows = 0;columns = 0;cout << "请输入要读取的文件路径:" << endl;string filepath;cin >> filepath;int num = 0;ifstream readmap(filepath);if (readmap){string aLine;while (num < 20&&getline(readmap, aLine)){num++;istringstream Line(aLine);char tem;vector<char> temline;while (Line >> tem){temline.push_back(tem);}map.push_back(temline);}rows = map.size();columns = map[0].size();int temx, temy;readmap >> temx;readmap >> temy;
/*      cout << temx << ' ' << temy << endl;*/start.set_node(temx, temy); //char to intreadmap >> temx;readmap >> temy;mend.set_node(temx, temy);startx = start.y + 0.5;starty = SCREEN_WIDTH - start.x;endx = mend.y + 0.5;//cout << "endx==" << endx << endl;endy = SCREEN_WIDTH - float(mend.x);//cout << "endy==" << endy << endl;}else{cout << "打开文件失败!";exit(-1);}
}void pf()
{for (int i = 0; i < rows; i++){for (int j = 0; j < columns; j++){cout << map[i][j] << ' ';}cout << endl;}//      cout << (int)map[rows][0]-48 << endl;//      cout << rows << endl;//      cout << columns << endl;//      cout << start.x << ' ' << start.y << endl;//      cout << end.x << ' ' << end.y << endl;
}
bool isgo(node nownode)
{if (map[nownode.x][nownode.y] == '0')return true;elsereturn false;
}
void recovrey()
{for (auto &i : map){for (auto &j : i){if (j == '@')j = '0';}}
}
void setpass(node tem) //表示可以通过
{map[tem.x][tem.y] = '*';
}
node nextnode(node tem, int i) //1,2,3,4表示要走的方向
{node next;next.x = tem.x;next.y = tem.y;switch (i){case 1:next.y = next.y + 1; break; //向右走case 2:next.x = next.x + 1; break; //向下走case 3:next.y = next.y - 1; break; //向左走case 4:next.x = next.x - 1; break; //向上走}return next;
}
void setNotPass(node tem) //表示走过但无法通过
{map[tem.x][tem.y] = '@';
}void setRecover(node tem) //表示走过但无法通过
{map[tem.x][tem.y] = '0';
}//核心代码 寻找路径
bool find_path()
{bool statu = false;stack path(rows*columns);node nownode; //现在位置int temnum = 1; //节点在路径的位置int nextfoot = 1; //下一步方向nownode = start;nownode.d = nextfoot;do{if (isgo(nownode)){setpass(nownode); //留下足迹if (nownode.x == mend.x&&nownode.y == mend.y) //查找成功{nownode.d = 4;path.push_back(nownode);statu = true;sta.push_back(path);//压入栈中temnum++;//                  if (temnum == 3)//                  {//                  return true;//                  }}else{nextfoot = 1;nownode.d = nextfoot;path.push_back(nownode);nownode = nextnode(nownode, nextfoot); //寻找下一个步//nownode.d = nextfoot;//nextfoot++;}}else //当前位置不通{if (!path.isempty()){path.pop_back(nownode);nextfoot = nownode.d;//cout<<'(' << nownode.x <<','<< nownode.y<<')' << endl;map[nownode.x][nownode.y] = '0';while (nownode.d == 4 && !path.isempty()){//setNotPass(e.sites);//setRecover(e.sites);path.pop_back(nownode);nextfoot = nownode.d;map[nownode.x][nownode.y] = '0';}if (nownode.d < 4){nextfoot++; //转换方向//nownode = nextnode(nownode, nextfoot);nownode.d = nextfoot;path.push_back(nownode);setpass(nownode);nownode = nextnode(nownode, nextfoot);}}}} while (!path.isempty());//path.des(); //销毁栈return statu;
}//存储迷宫数据到文件
void storage_map()
{ofstream out("结果.txt");for (auto i : map){for (auto j : i)out << j << ' ';out << endl;}int num = 1;for (auto i : sta){out << "第" << num << "条路径为:" << endl;out << "start" << "->";for (int j = 0; j < i.getUsedsize(); j++){out << "(" << i[j].x << ',' << i[j].y << ')' << "->";}out << "end" << endl;num++;}
}
void seeout()
{for (auto i : map){for (auto j : i)cout << j << ' ';cout << endl;}int num = 1;sort(sta.begin(), sta.end());//cout << sta.size();for (int i = 0; i < sta.size(); i++){cout << "第" << num << "条路径为:" << endl;cout << "start" << "->";for (int j = 0; j < sta[i].getUsedsize(); j++){cout << "(" << sta[i][j].x << ',' << sta[i][j].y << ')' << "->";}cout << "end" << endl;num++;}
}
//openGL 部分
void gldisplay()
{glShadeModel(GL_FLAT);glClearColor(0.0, 0.0, 0.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glColor3f(0.32, 0.86, 0.67);glMatrixMode(GL_MODELVIEW);   //设置当前操作的矩阵为“模型视图矩阵”glLoadIdentity();             //把当前矩阵设置为单位矩阵glBegin(GL_QUADS);float x = 0, y = SCREEN_HEIGHT;for (int i = 0; i < SCREEN_WIDTH; ++i){for (int j = 0; j < SCREEN_HEIGHT; ++j){if (map[i][j] == '1'){glVertex2f(x, y);glVertex2f(x, y - 1);glVertex2f(x + 1, y - 1);glVertex2f(x + 1, y);x++;if (j == SCREEN_HEIGHT - 1){y--;x = 0;}}else{x++;if (j == SCREEN_HEIGHT - 1){y--;x = 0;}}}}glEnd();glFlush();//绘制起点glShadeModel(GL_FLAT);glColor3f(1.0, 0.0, 0.0);glBegin(GL_TRIANGLES);glVertex2f(startx, starty);glVertex2f(startx - 0.5, starty - 1);glVertex2f(startx + 0.5, starty - 1);glEnd();glFlush();//绘制终点glShadeModel(GL_FLAT);glColor3ub(255u, 255u, 0u);glBegin(GL_TRIANGLES);glVertex2f(endx, endy);glVertex2f(endx - 0.5, endy - 1);glVertex2f(endx + 0.5, endy - 1);glEnd();glFlush();if (ans == true){glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINE_STRIP);for (int j = 0; j < sta[0].getUsedsize() - 1; j++){/*cout << "(" << sta[0][j].x << ',' << sta[0][j].y << ')' << "->";*/glVertex2f(sta[0][j].y + 0.5, SCREEN_WIDTH - sta[0][j].x - 0.5);glVertex2f(sta[0][j + 1].y + 0.5, SCREEN_WIDTH - sta[0][j + 1].x - 0.5);}glEnd();glFlush();}}void glspecial(int key, int x, int y)
{switch (key){case GLUT_KEY_LEFT:if (map[20 - int(starty)][int(startx) - 1] == '0')startx -= 1;       //向左移动glutPostRedisplay();break;case GLUT_KEY_RIGHT:if (map[20 - int(starty)][int(startx) + 1] == '0')startx += 1;        //向右移动glutPostRedisplay();break;case GLUT_KEY_UP:if (map[20 - (int(starty) + 1)][int(startx)] == '0')starty += 1;      //向上移动glutPostRedisplay();break;case GLUT_KEY_DOWN:if (map[20 - (int(starty) - 1)][int(startx)] == '0')starty -= 1;      //向下移动glutPostRedisplay();break;}
}void glcommon(unsigned char key , int x, int y)
{if (key == 'y'){ans = true;glutPostRedisplay();glColor3f(1.0, 0.0, 0.0);glBegin(GL_LINE_STRIP);for (int j = 0; j < sta[0].getUsedsize() - 1; j++){/*cout << "(" << sta[0][j].x << ',' << sta[0][j].y << ')' << "->";*/glVertex2f(sta[0][j].y + 0.5, SCREEN_WIDTH - sta[0][j].x - 0.5);glVertex2f(sta[0][j + 1].y + 0.5, SCREEN_WIDTH - sta[0][j + 1].x - 0.5);}glEnd();glFlush();}}// void glstart()
// {//  glColor3f(1.0, 0.0, 0.0);
//  glMatrixMode(GL_MODELVIEW);   //设置当前操作的矩阵为“模型视图矩阵”
//  glLoadIdentity();             //把当前矩阵设置为单位矩阵
//  glBegin(GL_TRIANGLES);
//  glColor3f(1.0, 0.0, 0.0);
//  glVertex2f(1.5, 9);
//  glVertex2f(1, 8);
//  glVertex2f(2, 8);
//  glEnd();
//  glFlush();
// }
void glmyReshape(int w, int h) {if (!h) return;glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h) {glOrtho(-20.0, 20.0, -20.0*(GLfloat)h / (GLfloat)w, 20.0*(GLfloat)h / (GLfloat)w, -20.0, 20.0);}else {glOrtho(-20.0*(GLfloat)w / (GLfloat)h, 20.0*(GLfloat)w / (GLfloat)h, -20.0, 20.0, -20.0, 20.0);}
}int main(int argc, char** argv)
{find_map();cout << "读入地图数据:" << endl;pf();cout << endl;vector<stack> a; //储存路径if (find_path()){cout << "找到路径:" << endl;pf();//t.storage_map();seeout();cout << "输入y以显示最佳路径!" << endl;}elsecout << "未找到路径!";glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);glutInitWindowSize(1000, 800);glutInitWindowPosition(0, 0);glutCreateWindow("一个迷宫");glutDisplayFunc(gldisplay);glutReshapeFunc(&glmyReshape);glutSpecialFunc(glspecial);glutKeyboardFunc(glcommon);glutMainLoop();return 0;
}

迷宫数据存储在二维数组里,为了简单起见,我把迷宫画在窗口的第一象限。

使用opengl和c++实现迷宫地图的路径搜索和显示(基于DFS)相关推荐

  1. Rot.js 随机地牢,迷宫地图生成

    js 插件随机地牢,迷宫地图生成 插件git https://github.com/ondras/rot.js/tree/master/dist 使用: 1.我们的游戏是在网页内进行的;一个基本的 H ...

  2. c语言打印输出迷宫地图所有路径

    在 C 语言中打印出迷宫的所有路径可以使用深度优先搜索(DFS)算法.您可以在迷宫数组中从起点开始搜索,并在每个经过的点标记为已走过,以防止重复经过.当到达终点时,打印出找到的路径.如果继续搜索下去不 ...

  3. 设置高德地图在Fragment中显示

    本文来自:fair-jm.iteye.com 转截请注明出处 官网的教程是在Activity下 在Fragment下在高德论坛找到一些方法 试了下可以显示 但是切换后总会有些问题 比如切换后就是新的了 ...

  4. Bing必应地图中国API一显示地图 (转) 做人要厚道

    Bing必应地图中国API一显示地图 2011-05-24 14:27:31|  分类: Bing&Google|字号 订阅 微软必应地图中国地图API发布已经有10天了,考虑到网上现有的SD ...

  5. 测试地图最短路径搜索(二):换个稍微复杂点的路径模板

    工具点此链接. 点击这里看下前面介绍的这种方案的基本原理. 测试地图最短路径搜索(一):把所有的辅助条件都铺到地图上 测试地图最短路径搜索(二):换个稍微复杂点的路径模板 测试地图最短路径搜索(三): ...

  6. echarts 地图九状线显示钓鱼岛系列 (1) 之 3.0 与2.0区别

    由于echarts 3.0 和2.0版本不一样, 下文将分别介绍. (vue项目,可以参考        echarts 地图九状线显示钓鱼岛(续-vue项目) echarts地图需要按数据值大小,显 ...

  7. 百度地图调用加载显示Marker,并添加点击事件

    百度地图调用加载显示Marker,并添加点击事件 注册百度开发者账号,申请应用AK 百度地图开发平台官网 点击右上角控制台,选择创建应用 创建应用,勾选浏览器端,白名单填写* 注:如上线更改为公网IP ...

  8. 2015-03-29-绘图和可视化(3)-绘制地图:图形化显示海地地震危机数据

    --------------------------------------------------------------------------------------- -----(三)绘制地图 ...

  9. MapBox地图怎么去掉地名显示

    MapBox地图怎么去掉地名显示,这个需求我之前也没遇到过,于是今天就尝试了一番,总结一下. 一.  首先尝试查找com.mapbox.mapboxsdk.maps.UiSettings源码 查看后发 ...

  10. arcgis前端(3)----->基础篇--自定义地图优化/隐藏or显示子图层

    arcgis前端(3)----->基础篇–自定义地图优化/隐藏or显示子图层 文章目录 arcgis前端(3)----->基础篇--自定义地图优化/隐藏or显示子图层 前言 实现效果展示 ...

最新文章

  1. Design Pattern - State(C#)
  2. mysql基于init-connect+binlog完成审计功能
  3. git每次操作都要输入账号密码 解决方案
  4. seo黑帽劫持用的php,黑帽seo 论坛:黑帽seo防止网站被k的js劫持跳转代码
  5. Envoy实现.NET架构的网关(五)集成Redis实现限流
  6. 【Android 应用开发】Activity 状态保存 OnSaveInstanceState參数解析
  7. CentOS 7安装Development Tools 失败 报错 group tools does not exist. Maybe run: yum groups mark install
  8. php视频文件设置期限,如何使用PHP检测视频文件持续时间(以分钟为单位)?
  9. curry化 js_前端发动机从 bind 聊到 curry (柯里化)
  10. VScode设置console.log('')快捷键
  11. 机器学习算法-10贝叶斯信念网络、聚类算法、基于密度的方法DBSCAN
  12. 2019.2.18接口2
  13. 算法导论第三版 第29章习题答案
  14. Lodop打印控件介绍
  15. C语言生成负指数分布,泊松分布与负指数分布的关系
  16. 做人与做事的对立与统一
  17. 石头剪刀布程序流程图_“脑王争霸赛”题目简单,选手说像石头剪刀布,王宇轩说谁都能做...
  18. 千手观音背后:最残酷的残疾经历
  19. 埃森哲:技术展望2023
  20. 为让儿子从轮椅上站起来,工程师父亲打造外骨骼装置

热门文章

  1. java与python比较之单引号 双引号用法
  2. 等保测评机构申请难吗?到哪里申请?
  3. 太阳直射点纬度计算公式_高中地理——每日讲1题(欧洲的气候、太阳高度角、日出时间)...
  4. 专访徐小平:AI已进入日常生活 没有泡沫只有彩虹
  5. 焊接工时简便计算工具_复杂工资,简单搞定——管家婆工贸PRO计件工资管理
  6. 计算机打字测试,打字测试
  7. system函数的详细使用
  8. 洛谷 — 旅行商的背包(背包)
  9. Unity3D官方案例--太空射击游戏总结
  10. centos7随机生成密码