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

使用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;
        else
            return 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;
        else
            return false;
    }
    bool isfull()
    {
        if (top == size - 1)
            return true;
        else
            return 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 int
            end.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;
        else
            return 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();
    }
    else
        cout << "未找到路径!";
}

赶着去上课,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 20

vector<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 int
        readmap >> 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;
    else
        return 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;
    }
    else
        cout << "未找到路径!";
    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;
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值