基于深度及广度优先搜索的迷宫问题的演示

1 时间复杂度分析

由于该图采用邻接矩阵存储,整个算法遍历的过程所花费的时间复杂度为该矩阵的N(row*col)。而由于其需要分别访问已经定位,需要进行分别2次操作,如下:

visited = new bool[col*row];//访问标记

for (i=0; i<row; i++)

for (j=0; j<col; j++)

visited[i*col+j] = false;//初始为未访问状态

position = new POSITION[col*row];

for (i=0; i<row; i++)//给每个点定位

for (j=0; j<col; j++)

{

position[i*col+j].x = j*CELL;

position[i*col+j].y = i*CELL;

position[i*col+j].index_x = j;

position[i*col+j].index_y = i;

}

因此在遍历的时候所需要的时间复杂度为N(2*row*col)。

由于深度优先搜索和广度优先搜索都是采用同样的存储方式,并且都是遍历搜索,因此时间复杂度相同,都是N(2*row*col)。

(注:row,col分别表示迷宫的行和列)。

2 空间复杂度分析

5.2.1 深度优先搜索空间复杂度分析

当进行深度优先搜索时,所遍历的最短路径即为单一路径,因此最好的空间复杂度是N(row+col),而最坏情况为N(row*col),即通过了最大的回溯之后才找到终点路径。

5.2.2广度优先搜索空间复杂度分析

当进行广度优先搜索的时候,路径经过所有可能的路径,即最大为row*col,因此,空间复杂度为N(row*col)。

#include<windows.h>
#include<iostream>
#include<ctime>
#include<stdlib.h>
#include<fstream>
#include<stack>
#include<queue>

const int CELL = 25;// 单元像素宽
const int W = 15;   // 迷宫宽度
const int H = 15;   // 迷宫高度

struct POSITION//每一个单元格的左上坐标
{
    int x;//单元格横坐标(单位pixel)
    int y;//单元格纵坐标
    int index_x;//单元格横标
    int index_y;//单元格纵标
};

struct MazeEdge//储存的是原来迷宫所拆的墙,下次生成迷宫和原来一样拆
{
    int x;
    int y;
    int z;
    int w;
};

struct Wall
{
    int wall_r;//右墙数据
    int wall_l;//左墙数据
    int wall_t;//上墙数据
    int wall_b;//下墙数据
};

LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM);//窗口函数
void DrawWhiteGround (HDC hdc);//将整个客户区绘制为白色
void DrawRedBlock (HDC hdc, int l, int t, int r, int b);//绘制迷宫起始点与终止点
void DrawRect (HDC hdc, int l, int t, int r, int b);//绘制单元方格
void DrawCell (HDC hdc, int l, int t, int r, int b);//绘制移动方块
void DrawGamePlace(HDC hdc, int col, int row); //在客户区绘满单元格
void DrawPath(HDC hdc, int w, int h);//迷宫拆墙
bool Adj(int x, int y, bool* visited, int col);//判断该单元格是否有没有被访问的相邻单元格
bool Adj_NoWall(int x, int y, bool* visited, Wall* wall, int col);//判断该单元格是否有没有被访问的相邻单元格并且周围没有墙可以访问
void Replace (HDC hdc, int x, int y, int z, int k);//拆墙(用白色划线替换红色划线)
void WriteDocument (MazeEdge* mazeedge, Wall* wall, int i);//将迷宫拆墙数据写入txt文件中
bool ReadDocument (HDC hdc);//从txt文件中读取迷宫拆墙数据
void DFS (HDC hdc);//深度优先搜索寻找迷宫路径
void BFS (HDC hdc);//广度优先搜索寻找迷宫路径
//---------------------------------------------------------------
int WINAPI WinMain ( HINSTANCE hInstance,
      HINSTANCE hPrevInstance,
      PSTR  szCmdLine,
      int  iCmdShow)

{
 static char AppName[]="ToyBrick";//窗口类名
 HWND  hwnd;
 MSG   msg;                //消息结构
 WNDCLASSEX wndclass;      //窗口类
 int   iScreenWide;        //定义一个整型变量来取得窗口的宽度

 wndclass.cbSize   = sizeof(wndclass);
 wndclass.style   = CS_HREDRAW|CS_VREDRAW;//窗口类型

 wndclass.lpfnWndProc = WndProc;   //窗口处理函数为 WndProc
 wndclass.cbClsExtra  = 0;         //窗口类无扩展
 wndclass.cbWndExtra  = 0;         //窗口实例无扩展
 wndclass.hInstance  = hInstance;                    //当前实例句柄
 wndclass.hIcon   = LoadIcon (NULL, IDI_APPLICATION);//默认图标
 wndclass.hCursor  = LoadCursor (NULL,IDC_ARROW);    //箭头光标
 wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH); //背景为黑色
 wndclass.lpszMenuName = NULL;         //窗口中无菜单
 wndclass.lpszClassName = AppName;     //类名为"ToyBrick"
 wndclass.hIconSm  = LoadIcon (NULL, IDI_INFORMATION);

//----------------------------------窗口类的注册-----------------------------------------
 if(!RegisterClassEx (&wndclass))//如果注册失败则发出警报声音,返回FALSE
 {
  MessageBeep(0);
  return FALSE;
 }

 // 获取显示器分辨率的X值iScreenWide,将程序窗口置于屏幕中央
 iScreenWide=GetSystemMetrics (SM_CXFULLSCREEN);

 hwnd =CreateWindow (
                  AppName,                    //窗口类名
                 "深度、广度优先搜索迷宫",//窗口实例的标题名
      WS_MINIMIZEBOX|WS_SYSMENU , //窗口的风格
      iScreenWide/2-W*CELL/2,     //窗口左上角横坐标(X)
      CELL,                       //窗口左上角纵坐标(Y)
      (W+0.3)*CELL,               //窗口的宽,而不是客户区的宽
      (H+1.2)*CELL,               //窗口的高 ,而不是客户区的高
      NULL,                       //窗口无父窗口
      NULL,                       //窗口无主菜单
      hInstance,                  //创建此窗口的应用程序的当前句柄
      NULL                        //不使用该值
       );
 if(!hwnd) return FALSE;
 MessageBox(NULL,TEXT("主程序:彭俊威"), TEXT("数据结构课程设计"),MB_ICONINFORMATION);
  //显示窗口
 ShowWindow (hwnd,iCmdShow);
 //绘制客户区
 UpdateWindow (hwnd);
 //消息循环
 while (GetMessage (&msg, NULL, 0, 0))
 {
  TranslateMessage (&msg);
  DispatchMessage (&msg);
 }
    //消息循环结束即程序终止时将消息返回系统
 return msg.wParam;
}

//-------------------窗口过程函数WndProc-----------------------------

LRESULT CALLBACK WndProc ( HWND  hwnd,UINT  iMsg,WPARAM wParam,LPARAM lParam )
{
 HDC   hdc;
 PAINTSTRUCT ps;
 //char Buffer[20];
 switch (iMsg)
 {
  //WM_PAINT(窗口第一次生成时执行,WM_PAINT将图从内存拷到屏幕上)
 case WM_PAINT:
  hdc =BeginPaint (hwnd, &ps);//获得设备环境句柄
  DrawGamePlace(hdc, W, H);//在客户区绘满单元格
  if (!ReadDocument(hdc))
  DrawPath(hdc, W, H);//拆墙
  MessageBox (NULL,TEXT("开始深度优先搜索"), TEXT("搜索方式"), NULL);
  DFS (hdc);//深度优先搜索寻找迷宫出口
  DrawWhiteGround (hdc);//将客户区还原为白色背景
  ReadDocument(hdc);//重新绘制迷宫
  MessageBox (NULL,TEXT("开始广度优先搜索"), TEXT("搜索方式"), NULL);
  BFS (hdc);//广度优先搜索寻找迷宫出口
  EndPaint (hwnd, &ps);
  return 0;
  //WM_DESTROY(响应关闭窗口动作)
 case WM_DESTROY:
  PostQuitMessage (0);
  return 0;
 }

 return DefWindowProc (hwnd, iMsg, wParam, lParam);

}

//////////////////////////////////////////////////////////

//将整个客户区绘制为白色
void DrawWhiteGround (HDC hdc)
{
int col, row;
std::ifstream f ("d:\\迷宫拆墙数据.txt");
f>>col>>row;
f.close();
HBRUSH hbrush = CreateSolidBrush(RGB(255,255,255));
SelectObject(hdc, hbrush);
Rectangle(hdc, 0, 0, col*CELL, row*CELL);
DeleteObject(hbrush);
}

//绘制迷宫起始点与终止点
void DrawRedBlock (HDC hdc, int l, int t, int r, int b)
{
HBRUSH hbrush = CreateSolidBrush(RGB(255,0,0));
SelectObject (hdc, hbrush);
Rectangle(hdc, l, t, r, b);
DeleteObject(hbrush);
}

//拆墙(用白色划线替换红色划线)
void Replace (HDC hdc, int x, int y, int z, int k)
{
    HPEN hpen;
    hpen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
    SelectObject(hdc, hpen);
    MoveToEx (hdc,x, y,NULL);
    LineTo (hdc, z, k);
    DeleteObject(hpen);

}

//画单元格,后面四个参数依次为左上坐标和右下坐标
void DrawRect (HDC hdc, int l, int t, int r, int b)
{
 MoveToEx (hdc, l, t, NULL);   //将起始点移动到(l,t)
 LineTo (hdc, r, t);
 LineTo (hdc, r, b);
 LineTo (hdc, l, b);
 LineTo (hdc, l,t);
}

//用绿色画刷画移动目标
void DrawCell (HDC hdc, int l, int t, int r, int b)
{
 HBRUSH hbrush;

 hbrush=CreateSolidBrush(RGB(0,255,0));    // 绿色画刷
 SelectObject(hdc,hbrush);
 Rectangle(hdc,l, t, r, b);
 DeleteObject (hbrush);

}

//在客户区绘满单元格
void DrawGamePlace(HDC hdc, int col, int row)
{
 int i,j;
 HPEN hpen1;
 hpen1=CreatePen(PS_SOLID,1,RGB(255,0,0));

   //绘制游戏区域方格线(红色)
 SelectObject(hdc,hpen1);
 for (i=0; i<row; i++)
  for(j=0; j<col; j++)
   DrawRect (hdc, j*CELL, i*CELL, (j+1)*CELL, (i+1)*CELL);

    DeleteObject(hpen1);

}

//迷宫拆墙
void DrawPath(HDC hdc, int col, int row)
{
    int x, y, temp, i(-1);
    bool* visited;                // 访问标记
    POSITION* position;//储存每个单元格的坐标
    POSITION w;
    std::stack<POSITION>Stack;
    MazeEdge *mazeedge;
    Wall* wall;//储存每个单元格的墙的情况

    wall = new Wall[col*row];//申请col*row个单元格
    for (x=0; x<row; x++)//请所有单元格的四面墙初始化为都有状态
        for (y=0; y<col; y++)
        {
            wall[x*col+y].wall_l = 1;
            wall[x*col+y].wall_t = 1;
            wall[x*col+y].wall_r = 1;
            wall[x*col+y].wall_b = 1;
        }

    visited = new bool[col*row];//访问标记
    for (x=0; x<row; x++)
        for (y=0; y<col; y++)
            visited[x*col+y] = false;//初始为未访问状态
        position = new POSITION[col*row];

    for (x=0; x<row; x++)//给每个点定位
        for (y=0; y<col; y++)
        {
            position[x*col+y].x = y*CELL;
            position[x*col+y].y = x*CELL;
            position[x*col+y].index_x = y;
            position[x*col+y].index_y = x;
        }

   mazeedge = new MazeEdge[col*row-1];//一棵树有顶点数-1条边
   MessageBox(NULL, TEXT("现在开始拆墙"), TEXT("消息"), NULL);
   srand (time(NULL));//系统时间作随机种子
   x = rand()%col;//随机产生起始点
   y = rand()%row;
   Stack.push(position[y*col+x]);//迷宫入口进栈
   visited[y*col+x] = true;//标记已经访问过
   while (!Stack.empty())
   {
   w = Stack.top();
   while (Adj(w.index_x, w.index_y, visited, col))//如果该单元格有没有被访问过的单元格
   {
       temp = rand()%4;
   if (temp==0&&(w.index_x+1<col)&&!visited[w.index_y*col+w.index_x+1])//右移
   {

       Sleep(50);
       i++;
       mazeedge[i].x = w.x+CELL;/*记录迷宫的拆墙数据*/
       mazeedge[i].y = w.y;
       mazeedge[i].z = w.x+CELL;
       mazeedge[i].w = w.y+CELL;
       /////////////////////////                 /*记录每个单元格四面墙的数据
       wall[w.index_y*col+w.index_x].wall_r = 0;//单元格(w.index_x,w.index_y)的右墙被拆除
       wall[w.index_y*col+w.index_x+1].wall_l = 0;//单元格(w.index_x+1,w.index_y)的左墙被拆除
       ////////////////////////
       Replace (hdc, w.x+CELL, w.y, w.x+CELL, w.y+CELL);//拆右竖墙
       visited[w.index_y*col+w.index_x+1] = true;//标记已经访问 过的单元格
       Stack.push(position[w.index_y*col+w.index_x+1]);//符合条件的相邻单元格进栈
       w = Stack.top();
   }

   if (temp==1&&(w.index_x-1>-1)&&!visited[w.index_y*col+w.index_x-1])//左移
   {

       Sleep(50);
       i++;
       mazeedge[i].x = w.x;/*记录迷宫的拆墙数据*/
       mazeedge[i].y = w.y;
       mazeedge[i].z = w.x;
       mazeedge[i].w = w.y+CELL;
        /////////////////////////                 /*记录每个单元格四面墙的数据
       wall[w.index_y*col+w.index_x].wall_l = 0;//单元格(w.index_x,w.index_y)的左墙被拆除
       wall[w.index_y*col+w.index_x-1].wall_r = 0;//单元格(w.index_x-1,w.index_y)的右墙被拆除
       ////////////////////////
       Replace (hdc, w.x, w.y, w.x, w.y+CELL);//拆左竖墙,左拆与右拆不一样
       visited[w.index_y*col+w.index_x-1] = true;//标记已经访问过的单元格
       Stack.push(position[w.index_y*col+w.index_x-1]);//符合条件的相邻单元格进栈
       w = Stack.top();

   }

   if (temp==2&&(w.index_y-1>-1)&&!visited[(w.index_y-1)*col+w.index_x])//上移
   {
       Sleep(50);
       i++;
       mazeedge[i].x = w.x;/*记录迷宫的拆墙数据*/
       mazeedge[i].y = w.y;
       mazeedge[i].z = w.x+CELL;
       mazeedge[i].w = w.y;
        /////////////////////////                 /*记录每个单元格四面墙的数据
       wall[w.index_y*col+w.index_x].wall_t = 0;//单元格(w.index_x,w.index_y)的上墙被拆除
       wall[(w.index_y-1)*col+w.index_x].wall_b = 0;//单元格(w.index_x,w.index_y-1)的下墙被拆除
       ////////////////////////
       Replace (hdc, w.x, w.y, w.x+CELL, w.y);//拆横墙
       visited[(w.index_y-1)*col+w.index_x] = true;//标记已经访问过的单元格
       Stack.push(position[(w.index_y-1)*col+w.index_x]);//符合条件的相邻单元格进栈
       w = Stack.top();
   }

   if (temp==3&&(w.index_y+1<row)&&!visited[(w.index_y+1)*col+w.index_x])//下移
   {
       Sleep(50);
       i++;
       mazeedge[i].x = w.x;/*记录迷宫的拆墙数据*/
       mazeedge[i].y = w.y+CELL;
       mazeedge[i].z = w.x+CELL;
       mazeedge[i].w = w.y+CELL;
        /////////////////////////                 /*记录每个单元格四面墙的数据
       wall[w.index_y*col+w.index_x].wall_b = 0;//单元格(w.index_x,w.index_y)的下墙被拆除
       wall[(w.index_y+1)*col+w.index_x].wall_t = 0;//单元格(w.index_x,w.index_y+1)的上墙被拆除
       ////////////////////////
       Replace (hdc, w.x, w.y+CELL, w.x+CELL, w.y+CELL);//拆横墙
       visited[(w.index_y+1)*col+w.index_x] = true;//标记已经访问过的单元格
       Stack.push(position[(w.index_y+1)*col+w.index_x]);//符合条件的相邻单元格进栈
       w = Stack.top();
   }
   }
   Stack.pop();//回溯

}
   WriteDocument(mazeedge, wall, i);//将迷宫拆墙数据写入txt文件
}

//深度优先搜索寻找迷宫路径
void DFS (HDC hdc)
{
    int col, row, entrance, exit, i, j;
    bool* visited = NULL;//访问标示
    bool status(false);//走迷宫状态
    POSITION* position = NULL;//记录各个单元的坐标
    POSITION w;//临时中间变量
    Wall* wall = NULL;//储存单元格四面墙的信息
    std::stack<POSITION> Stack;

    std::ifstream f("d:\\迷宫拆墙数据.txt");      /*读迷宫规模数据*/
    f>>col>>row;//从txt文件中获取原来迷宫的规模
    f.close();

    wall = new Wall[col*row];
    std::ifstream f1("d:\\每个单元格四面墙的数据.txt"); /*读迷宫墙的信息*/
    for (i=0; i<col*row; i++)//从txt文档中读入每个单元格四面墙数据
        f1>>wall[i].wall_l>>wall[i].wall_t>>wall[i].wall_r>>wall[i].wall_b;
    f1.close();

    srand(time(NULL));//系统时间作随机种子
    entrance = rand()%col;//随机在迷宫第一行和最后一行分别产生入口与出口
    exit = rand()%col;
    visited = new bool[col*row];//访问标记
    for (i=0; i<row; i++)
    for (j=0; j<col; j++)
    visited[i*col+j] = false;//初始为未访问状态
    position = new POSITION[col*row];

    for (i=0; i<row; i++)//给每个点定位
    for (j=0; j<col; j++)
    {
    position[i*col+j].x = j*CELL;
    position[i*col+j].y = i*CELL;
    position[i*col+j].index_x = j;
    position[i*col+j].index_y = i;
    }
    Stack.push(position[entrance]);//迷宫入口进栈
    visited[entrance] = true;
    DrawRedBlock (hdc, entrance*CELL+6, 6, (entrance+1)*CELL-6, CELL-6);//绘制迷宫入口
    DrawRedBlock (hdc, exit*CELL+6, (row-1)*CELL+6, (exit+1)*CELL-6, row*CELL-6);//绘制迷宫出口

    while (!Stack.empty()&&!status)
    {
     w = Stack.top();
     while (Adj_NoWall (w.index_x, w.index_y, visited, wall, col))//如果有还没有被访问的相邻单元格并且可以访问
     {

       if (wall[w.index_y*col+w.index_x].wall_b == 0&&!visited[(w.index_y+1)*col+w.index_x])//如果下墙已经被拆除而且下边单元格没有被访问过,目标下移
      {
          Sleep(200);
      DrawCell (hdc, w.x+6, w.y+CELL+6, w.x+CELL-6, w.y+2*CELL-6);//使移动目标小于单元格大小
      visited[(w.index_y+1)*col+w.index_x] = true;
      Stack.push(position[(w.index_y+1)*col+w.index_x]);//入栈
      w = Stack.top();
      }

      else if (wall[w.index_y*col+w.index_x].wall_r == 0&&!visited[(w.index_y)*col+w.index_x+1])//如果右墙已经被拆除而且右边单元格没有被访问过,目标右移
      {
          Sleep(200);
      DrawCell (hdc, w.x+CELL+6, w.y+6, w.x+2*CELL-6, w.y+CELL-6);//使移动目标小于单元格大小
      visited[w.index_y*col+w.index_x+1] = true;
      Stack.push(position[w.index_y*col+w.index_x+1]);//入栈
      w = Stack.top();
      }

      else if (wall[w.index_y*col+w.index_x].wall_l == 0&&!visited[w.index_y*col+w.index_x-1])//如果左墙已经被拆除而且左边单元格没有被访问过,目标左移
      {
          Sleep(200);
      DrawCell (hdc, w.x-CELL+6, w.y+6, w.x-6, w.y+CELL-6);//使移动目标小于单元格大小
      visited[w.index_y*col+w.index_x-1] = true;
      Stack.push(position[w.index_y*col+w.index_x-1]);//入栈
      w = Stack.top();
      }
     else if (wall[w.index_y*col+w.index_x].wall_t == 0&&!visited[(w.index_y-1)*col+w.index_x])//如果上墙已经被拆除而且上边单元格没有被访问过,目标上移
      {
          Sleep(200);
      DrawCell (hdc, w.x+6, w.y-CELL+6, w.x+CELL-6, w.y-6);//使移动目标小于单元格大小
      visited[(w.index_y-1)*col+w.index_x] = true;
      Stack.push(position[(w.index_y-1)*col+w.index_x]);//入栈
      w = Stack.top();
      }

      if (w.index_y==row-1&&w.index_x==exit)//如果到达迷宫出口则停止搜索
      {
          DrawRedBlock (hdc, exit*CELL+6, (row-1)*CELL+6, (exit+1)*CELL-6, row*CELL-6);//绘制迷宫出口
          MessageBox(NULL,TEXT("成功走出迷宫!"), TEXT("Congratunations"),MB_ICONINFORMATION);
          status = true;
          break;
      }
     }

Stack.pop();//回溯
}

}

//广度优先搜索寻找迷宫路径
void BFS (HDC hdc)
{

    int col, row, entrance, exit, i, j;
    bool* visited = NULL;//访问标示
    bool status(false);//走迷宫状态
    POSITION* position = NULL;//记录各个单元的坐标
    POSITION u;//临时中间变量
    Wall* wall = NULL;//储存单元格四面墙的信息
    std::queue<POSITION> Queue;
    char Buffer[20];

    std::ifstream f("d:\\迷宫拆墙数据.txt");      /*读迷宫规模数据*/
    f>>col>>row;//从txt文件中获取原来迷宫的规模
    f.close();

    wall = new Wall[col*row];
    std::ifstream f1("d:\\每个单元格四面墙的数据.txt"); /*读迷宫墙的信息*/
    for (i=0; i<col*row; i++)//从txt文档中读入每个单元格四面墙数据
        f1>>wall[i].wall_l>>wall[i].wall_t>>wall[i].wall_r>>wall[i].wall_b;
    f1.close();

    srand(time(NULL));//系统时间作随机种子
    entrance = rand()%col;//随机在迷宫第一行和最后一行分别产生入口与出口
    exit = rand()%col;
    visited = new bool[col*row];//访问标记
    for (i=0; i<row; i++)
    for (j=0; j<col; j++)
    visited[i*col+j] = false;//初始为未访问状态
    position = new POSITION[col*row];

    for (i=0; i<row; i++)//给每个点定位
    for (j=0; j<col; j++)
    {
    position[i*col+j].x = j*CELL;
    position[i*col+j].y = i*CELL;
    position[i*col+j].index_x = j;
    position[i*col+j].index_y = i;
    }
    Queue.push(position[entrance]);//迷宫入口进队列
    visited[entrance] = true;
    DrawRedBlock (hdc, entrance*CELL+6, 6, (entrance+1)*CELL-6, CELL-6);//绘制迷宫入口
    DrawRedBlock (hdc, exit*CELL+6, (row-1)*CELL+6, (exit+1)*CELL-6, row*CELL-6);//绘制迷宫出口
    while (!Queue.empty())
    {
     u = Queue.front();
     Queue.pop();
     if (Adj_NoWall (u.index_x, u.index_y, visited, wall, col))//如果有还没有被访问的相邻单元格并且可以访问
     {
      if ((u.index_y+1<row)&&!visited[(u.index_y+1)*col+u.index_x]&&wall[u.index_y*col+u.index_x].wall_b==0)//如果作相邻单元格没有被访问过,并且可以被访问
      {
          Sleep (100);
       DrawCell (hdc, u.x+6, u.y+CELL+6, u.x+CELL-6, u.y+2*CELL-6);//画下单元格
       visited[(u.index_y+1)*col+u.index_x] = true;
       Queue.push (position[(u.index_y+1)*col+u.index_x]);//下单元格进队列
      }

      if ((u.index_x-1>-1)&&!visited[u.index_y*col+u.index_x-1]&&wall[u.index_y*col+u.index_x].wall_l==0)//如果作相邻单元格没有被访问过,并且可以被访问
      {
           Sleep (100);
       DrawCell (hdc, u.x-CELL+6, u.y+6, u.x-6, u.y+CELL-6);//画左单元格
       visited[u.index_y*col+u.index_x-1] = true;
       Queue.push (position[u.index_y*col+u.index_x-1]);//左单元格进队列
      }

      if ((u.index_x+1<col)&&!visited[u.index_y*col+u.index_x+1]&&wall[u.index_y*col+u.index_x].wall_r==0)//如果作相邻单元格没有被访问过,并且可以被访问
      {
           Sleep (100);
      DrawCell (hdc, u.x+CELL+6, u.y+6, u.x+2*CELL-6, u.y+CELL-6);//画右单元格
      visited[u.index_y*col+u.index_x+1] = true;
      Queue.push (position[u.index_y*col+u.index_x+1]);//右单元格进队列
      }

      if ((u.index_y-1>-1)&&!visited[(u.index_y-1)*col+u.index_x]&&wall[u.index_y*col+u.index_x].wall_t==0)
      {
           Sleep (100);
      DrawCell (hdc, u.x+6, u.y+CELL+6, u.x+CELL-6, u.y+2*CELL-6);//画上单元格
      visited[(u.index_y-1)*col+u.index_x] = true;
      Queue.push (position[(u.index_y-1)*col+u.index_x]);//上单元格进队列
      }
       if (u.index_y==row-1&&u.index_x==exit)//如果到达迷宫出口则停止搜索
      {
          DrawRedBlock (hdc, exit*CELL+6, (row-1)*CELL+6, (exit+1)*CELL-6, row*CELL-6);//绘制迷宫出口
          MessageBox(NULL,TEXT("成功走出迷宫!"), TEXT("Congratunations"),MB_ICONINFORMATION);
          break;
      }
     }
    }

}

//判断该单元格是否有没有被访问的相邻单元格
bool Adj(int x, int y, bool* visited, int col)
{
 if((x-1>-1)&&!visited[y*col+x-1]||(x+1<W)&&!visited[y*col+x+1]||     y-1>-1&&!visited[(y-1)*col+x]||y+1<H&&!visited[(y+1)*col+x])
       return true;
   return false;
}

//判断该单元格是否有没有被访问的相邻单元格并且周围没有墙可以访问
bool Adj_NoWall(int x, int y, bool* visited, Wall* wall, int col)
{
 if((x-1>-1)&&!visited[y*col+x-1]&&wall[y*col+x].wall_l==0||(x+1<W)&&!visited[y*col+x+1]&&wall[y*col+x].wall_r==0||     y-1>-1&&!visited[(y-1)*col+x]&&wall[y*col+x].wall_t==0||y+1<H&&!visited[(y+1)*col+x]&&wall[y*col+x].wall_b==0)
       return true;
   return false;
}

//将迷宫拆墙数据写入txt文件中
void WriteDocument (MazeEdge* mazeedge, Wall* wall, int i)
{
int j;
std::ofstream f("d:\\迷宫拆墙数据.txt");
f<<W<<" "<<H<<std::endl;//写入拆墙数据
for (j=0; j<i+1; j++)
f<<mazeedge[j].x<<" "<<mazeedge[j].y<<" "<<mazeedge[j].z<<" "<<mazeedge[j].w<<std::endl;
f.close();
std::ofstream f1("d:\\每个单元格四面墙的数据.txt");//写入每个单元格四面墙的数据
for (j=0; j<i+2; j++)
f1<<wall[j].wall_l<<" "<<wall[j].wall_t<<" "<<wall[j].wall_r<<" "<<wall[j].wall_b<<std::endl;
f1.close();
}

//从txt文件中读取迷宫拆墙数据
bool ReadDocument (HDC hdc)
{
int col, row, i;
MazeEdge *mazeedge;
std::ifstream f ("d:\\迷宫拆墙数据.txt");
if (f.fail())//打开文件失败
return false;
else
{
f>>col>>row;
f.close();
}

DrawGamePlace(hdc, col, row);//在客户区绘满红色单元格

mazeedge = new MazeEdge[col*row-1];
f.open("d:\\迷宫拆墙数据.txt");
f>>col>>row;
for (i=0; i<col*row-1; i++)//从txt文档中读入数据
f>>mazeedge[i].x>>mazeedge[i].y>>mazeedge[i].z>>mazeedge[i].w;
f.close();
for (i=0; i<col*row-1; i++)//拆墙
Replace(hdc, mazeedge[i].x, mazeedge[i].y, mazeedge[i].z, mazeedge[i].w);

return true;
}

程序非原创,在开源中国有类似的。

基于c++win32编程。

基于深度及广度优先搜索的迷宫问题的演示,布布扣,bubuko.com

时间: 2024-10-03 23:29:43

基于深度及广度优先搜索的迷宫问题的演示的相关文章

SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Description 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) Input 输入第一行为整数n(0< n <100),表示数据的组数.对于每组数据,第一行是三个整数k,m,t(0<

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) 输入 输入第一行为整数n(0< n <100),表示数据的组数. 对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,

数据结构之 图论---基于邻接矩阵的广度优先搜索遍历(输出bfs遍历序列)

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory limit: 65536K 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) 输入 输入第一行为整数n(0< n <100),表示数据的组数. 对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,0< t<k),

深度和广度优先搜索

我们知道,算法是作用于具体数据结构之上的,深度优先搜索算法和广度优先搜索算法都是基于“图”这种数据结构的.这是因为,图这种数据结构的表达能力很强,大部分涉及搜索的场景都可以抽象成“图”. 无向图的代码实现 public class Graph { // 无向图 private int v; // 顶点的个数 private LinkedList<Integer> adj[]; // 邻接表 public Graph(int v) { this.v = v; adj = new LinkedLi

ybt 1252 广度优先搜索 走迷宫(二维、最小步数)

1252:走迷宫 时间限制: 1000 ms         内存限制: 65536 KB提交数: 7272     通过数: 3241 [题目描述] 一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走:有的格子是空地,可以走. 给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到).只能在水平方向或垂直方向走,不能斜着走. [输入] 第一行是两个整数,R和C,代表迷宫的长和宽.( 1≤ R,C ≤ 40) 接下来是R行,每行C个字符,代表整个迷宫. 空地格子用‘.’表示,

SDUT OJ 2413 数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

#include<iostream> #include<memory.h> using namespace std; int p[1010][1010]; int visit[110]; int c[1010]; int a=0; int b=1; int k; int t; void bfs(int n) { a++; for(int i=0;i<k;i++) { if(p[n][i]==1&&visit[i]==0) { c[b++]=i; visit[i

广度优先搜索[再解迷宫]

上一节讲过深度优先搜索解决迷宫,http://blog.csdn.net/wtyvhreal/article/details/43268115 这一节讲解广度优先搜索解决迷宫. 广度优先搜索(Breadth First Search,BFS),也称为宽度优先搜索. 还是二维数组存储,开始小哼在(1,1)处,在深搜里我们先让小哼往右边走,然后一直尝试下去,直到走不通的时候再回到这里.这样是深搜,可以通过函数递归实现.广搜的方法:通过一层一层扩展的方法找到小哈.扩张的时候每发现一个点就将这个点加入到

广度优先搜索(bfs)

学了将近半年的信息了,昨天猛地间发现我好像不会搜索.... 这就意味着我在noip的时候连暴力都不会打...为了避免这种事情的发生,我决定一定要好好学搜索.. 好了,废话不多说了,下面开始我们的正式话题:广度优先搜索 1.前言 广度优先搜索其实是一种用来遍历连通图的一种算法,它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名.                       貌似有的东西就真的跟徐大佬说的一样:说不清楚,只能靠自己去做题才能真正理解. 所以,如果我说的你不是很明白

迷宫问题解决方法:分别基于深度搜索和广度搜索的思想来实现

本文针对迷宫问题,探讨解决思路并给出实现代码.在本文中,采用的图的深度优先搜索和广度优先搜索两种方法分别对迷宫的路径进行了求解. 首先来看迷宫问题的描述,可以参考此处,简而言之就是,通过一个二维数组(int型)来表示迷宫,迷宫中0表示可行,1表示不可行.在本文的实现中,可以输入给定迷宫,定义迷宫入口和出口,并查找迷宫路径. 总体的描述:在本文中,定义了结构体Node,用于存放节点信息,而Node内只有两个变量,标识节点的行坐标与列坐标.定义了迷宫类maze,并分别定义了相应的get.set函数,