• 数据结构应用实例#栈#迷宫寻路


    使用数据结构 栈(Stack)来实现一种低级的迷宫寻路的功能。
    低级是因为无法判断路径是不是最短的。

    这里使用的栈结构如图 (这图我选择死亡...)


    注意结构体里DataType的实际含义,是另外一个结构体,用于储存二维位置x,y


    地图使用一个10x10的二维数组来表示,数字1表示该点是墙壁,0表示可以行走,2表示已经走过的地方。

    我们用栈来储存走过的位置,比如我们从起点(4,0)出发,就把(4,0)压入栈,并把该点数值改为2,意为已经来过了。
    如果遇到死路,那就不停地出栈,直到栈顶的这个点周围有路可走为止。

    逻辑部分伪代码如下

    while(没有到达终点)
    {
      if(上下左右四个方向有路可走)
      {
        将可以走的那个位置(不是当前位置!)压入栈
      }
      else
      {
        出栈
      }
    }

      1 #include <stack>
      2 #include <iostream>
      3 
      4 using std::cout;
      5 using std::endl;
      6 using std::stack;
      7 
      8 const int MAZEWIDTH = 10;
      9 const int MAZEHEIGHT = 10;
     10 
     11 //0可走
     12 //1墙
     13 //2走过
     14 //3走过又退回来了
     15 int Maze[MAZEWIDTH][MAZEHEIGHT] = {
     16         //0  1  2  3  4  5  6  7  8  9
     17         1, 1, 1, 1, 1, 1, 1, 1, 1, 1,//0
     18         1, 0, 1, 0, 0, 0, 1, 0, 0, 0,//1
     19         1, 0, 0, 0, 1, 0, 1, 0, 0, 1,//2
     20         1, 0, 1, 1, 0, 0, 1, 1, 0, 1,//3
     21         1, 0, 1, 0, 0, 1, 0, 1, 0, 1,//4
     22         0, 0, 1, 1, 0, 1, 0, 0, 0, 1,//5
     23         1, 1, 0, 0, 0, 0, 1, 0, 1, 1,//6
     24         1, 0, 1, 1, 1, 0, 1, 0, 0, 1,//7
     25         1, 0, 0, 0, 0, 0, 0, 0, 0, 1,//8
     26         1, 1, 1, 1, 1, 1, 1, 1, 1, 1//9
     27 };
     28 
     29 struct _XY {
     30     int x, y;
     31 
     32     _XY() {
     33         x = y = 0;
     34     }
     35 
     36     _XY(int a, int b) : x(a), y(b) { }
     37 
     38     int operator==(const struct _XY &a) {
     39         return (a.x == x) && (a.y == y);
     40     }
     41 };
     42 
     43 typedef _XY XY;
     44 
     45 class MazeBreaker {
     46 private:
     47     int MazeMap[MAZEWIDTH][MAZEHEIGHT];
     48     stack<XY> path;
     49     XY start, end;
     50 
     51 
     52     void push(XY xy) {
     53         path.push(xy);
     54         MazeMap[xy.x][xy.y] = 2;
     55     }
     56 
     57     void push(int x, int y) {
     58         path.push(XY(x, y));
     59         MazeMap[x][y] = 2;
     60     }
     61 
     62     void pop() {
     63         if (!(path.top() == start)) {
     64             XY &loc = path.top();
     65             MazeMap[loc.x][loc.y] = 3;
     66             path.pop();
     67         }
     68     }
     69 
     70     int End() {
     71         return path.top() == end;
     72     }
     73 
     74     void ThereIsAWay() {
     75         XY &loc = path.top();
     76         //UP
     77         if (MazeMap[loc.x - 1][loc.y] == 0) {
     78             push(loc.x - 1, loc.y);
     79             return;
     80         }
     81         //RIGHT
     82         if (MazeMap[loc.x][loc.y - 1] == 0) {
     83             push(loc.x, loc.y - 1);
     84             return;
     85         }
     86         //DOWN
     87         if (MazeMap[loc.x + 1][loc.y] == 0) {
     88             push(loc.x + 1, loc.y);
     89             return;
     90         }
     91         //LEFT
     92         if (MazeMap[loc.x][loc.y + 1] == 0) {
     93             push(loc.x, loc.y + 1);
     94             return;
     95         }
     96         pop();
     97         return;
     98     }
     99 
    100 public:
    101 
    102     void GenerateMap() {
    103         for (int lop = 0; lop < MAZEWIDTH; lop++) {
    104             for (int lop2 = 0; lop2 < MAZEHEIGHT; lop2++) {
    105                 MazeMap[lop][lop2] = Maze[lop][lop2];
    106             }
    107         }
    108         push(start);
    109     }
    110 
    111     MazeBreaker() {
    112         start.x = 5;
    113         start.y = 0;
    114         end.x = 1;
    115         end.y = 9;
    116     }
    117 
    118     void FindPath() {
    119         while (!End()) {
    120             ThereIsAWay();
    121         }
    122 
    123         for (int lop = 0; lop < MAZEWIDTH; lop++) {
    124             for (int lop2 = 0; lop2 < MAZEHEIGHT; lop2++) {
    125                 if (MazeMap[lop][lop2] == 2) {
    126                     cout << "O";
    127                 } else if (MazeMap[lop][lop2] == 3) {
    128                     cout << "X";
    129                 } else {
    130                     cout << " ";
    131                 }
    132             }
    133             cout << endl;
    134         }
    135     }
    136 
    137 };
    138 
    139 int main() {
    140     MazeBreaker mb;
    141     mb.GenerateMap();
    142     mb.FindPath();
    143     return 0;
    144 }

    ///////////以下是老版本////////////

    首先是栈的头文件,注意栈结构体内容的具体定义

    Stack.h

     1 #ifndef _STACK_H_
     2 #define _STACK_H_
     3 
     4 #include<stdio.h>
     5 #include<stdlib.h>
     6 
     7 //以下两个数据大小视实际情况而定
     8 //初始栈容量
     9 #define STACK_INIT_SIZE 20
    10 //每次扩容的增量
    11 #define STACKINCREMENT 10
    12 
    13 //迷宫地图
    14 int Maze[10][10];
    15 
    16 //表示位置
    17 struct xy
    18 {
    19     int x, y;
    20 };
    21 typedef struct xy XY;
    22 typedef  XY DataType;
    23 
    24 struct stack
    25 {
    26     //指向栈最顶上的元素的接下来一个位置
    27     //表示新入栈的值可以放在指向的地方
    28     DataType *Top;
    29     //指向栈底部,最里面的元素
    30     DataType *Bottom;
    31     //表示了当前栈的容量
    32     int stacksize;
    33 };
    34 typedef struct stack STACK;
    35 
    36 //新建栈
    37 int InitStack(STACK *S);
    38 
    39 //销毁栈
    40 int DestroyStack(STACK *S);
    41 
    42 //返回顶层元素
    43 int GetTop(STACK S,int *x,int *y);
    44 
    45 //Push操作,入栈,压栈
    46 int Push(STACK *S, int x,int y);
    47 
    48 //Pop操作,出栈
    49 int Pop(STACK *S);
    50 
    51 #endif

    然后是定义

    Stack.c

     1 #include"Stack.h"
     2 
     3 int InitStack(STACK *S)
     4 {
     5     //创建出设定长度的顺序表,地址赋给bottom指针
     6     S->Bottom = (DataType*)malloc(STACK_INIT_SIZE*sizeof(DataType));
     7     if (!S->Bottom)
     8     {
     9         return 0;
    10     }
    11     S->stacksize = STACK_INIT_SIZE;
    12     S->Top = S->Bottom;
    13     return 1;
    14 }
    15 
    16 int DestroyStack(STACK *S)
    17 {
    18     S->Top = NULL;
    19     free(S->Bottom);
    20     S->Bottom = NULL;
    21     return 1;
    22 }
    23 
    24 int GetTop(STACK S, int *x, int *y)
    25 {
    26     if (S.Bottom != S.Top)
    27     {
    28         //由于top指向的是最顶上元素的下一个位置
    29         //所以取出最顶上元素的时候
    30         //要把top减去1
    31         *x = ((S.Top - 1)->x);
    32         *y = ((S.Top - 1)->y);
    33         return 1;
    34     }
    35     return 0;
    36 }
    37 
    38 int Push(STACK *S, int x,int y)
    39 {
    40     //当超出当前栈的容量时
    41     //这里应该只有等于的情况
    42     //而不会大于
    43     if ((S->Top - S->Bottom) >= S->stacksize)
    44     {
    45         //realloc函数将开辟指定的储存空间
    46         //并将原来的数据全部移到这个新的储存空间
    47         S->Bottom = (DataType*)realloc(S->Bottom, (S->stacksize + STACKINCREMENT)*sizeof(DataType));
    48         if (!S->Bottom)
    49         {
    50             return 0;
    51         }
    52         //由于重新开辟了空间
    53         //需要重新根据bottom指针的位置指定top
    54         S->Top = S->Bottom + S->stacksize;
    55         //最后增加当前栈容量
    56         S->stacksize += STACKINCREMENT;
    57     }
    58     //再把入栈的数据存放好
    59     (S->Top)->x = x;
    60     (S->Top)->y = y;
    61     S->Top++;
    62 
    63     //在地图上将该点标为2
    64     Maze[x][y] = 2;
    65     return 1;
    66 }
    67 
    68 //将该点丢弃
    69 int Pop(STACK *S)
    70 {
    71     if (S->Bottom == S->Top)
    72     {
    73         printf("Empty Stack!Can not pop!
    ");
    74         return 0;
    75     }
    76     //top指针先减1再取值
    77     --S->Top;
    78     return 1;
    79 }

    寻路的逻辑放在了main函数里,迷宫地图的定义也在这里

    main.c

    二维数组Maze存放了迷宫的信息,你也可以自己改改*。

      1 #include"Stack.h"
      2 
      3 #define Up 1
      4 #define Right 2
      5 #define Down 3
      6 #define Left 4
      7 //代表已无路可走
      8 //End of Road
      9 #define EOR 5
     10 
     11 //迷宫的地图
     12 //墙壁表示为1,可走的地方表示为0,走过的地方表示为2
     13 //入口为(4,0),出口为(0,8)
     14 //可自行更改,但请确保有通路
     15 
     16 Maze[10][10] = { 
     17 //0,1,2,3,4,5,6,7,8,9
     18 1,1,1,1,1,1,1,1,0,1,     //0
     19 1,0,0,0,0,0,0,1,0,1,     //1
     20 1,0,1,0,1,1,1,1,0,1,     //2
     21 1,0,1,0,1,0,0,0,0,1,     //3
     22 0,0,1,0,1,0,1,0,1,1,     //4
     23 1,0,1,0,1,0,1,0,1,1,     //5
     24 1,1,0,0,1,0,1,0,1,1,     //6
     25 1,0,0,1,1,0,1,0,1,1,     //7
     26 1,0,0,0,0,0,1,0,0,1,     //8
     27 1,1,1,1,1,1,1,1,1,1 };  //9
     28 
     29 //打印结果
     30 int Print()
     31 {
     32     int lop, lop2;
     33     for (lop = 0; lop < 10; lop++)
     34     {
     35         for (lop2 = 0; lop2 < 10; lop2++)
     36         {
     37             if (Maze[lop][lop2] == 2)
     38             {
     39                 printf("1");
     40             }
     41             else
     42             {
     43                 printf(" ");
     44             }
     45         }
     46         printf("
    ");
     47     }
     48     return 1;
     49 }
     50 
     51 int GameOver(STACK s, XY *loc,XY End)
     52 {
     53     GetTop(s, &(loc->x), &(loc->y));
     54     if (loc->x == End.x && loc->y == End.y)
     55     {
     56         return 1;
     57     }
     58     else
     59     {
     60         return 0;
     61     }
     62 }
     63 
     64 //1 up.2 right.3 down.4 left
     65 //看看当前位置的上下左右还有没有能走的地方
     66 int SearchPath(STACK s, XY loc)
     67 {
     68     int x, y;
     69     x = loc.x;
     70     y = loc.y;
     71 
     72     //Up Available?
     73     if (x != 0)
     74     {
     75         if (!Maze[x - 1][y])
     76         {
     77             return Up;
     78         }
     79     }
     80     //Right ?
     81     if (y != 9)
     82     {
     83         if (!Maze[x][y + 1])
     84         {
     85             return Right;
     86         }
     87     }
     88     //Down?
     89     if (x != 9)
     90     {
     91         if (!Maze[x + 1][y])
     92         {
     93             return Down;
     94         }
     95     }
     96     //Left?
     97     if (y != 0)
     98     {
     99         if (!Maze[x][y - 1])
    100         {
    101             return Left;
    102         }
    103     }
    104     return EOR;
    105 }
    106 
    107 int main()
    108 {
    109     //储存走出迷宫的路径
    110     STACK Path;
    111     //储存当前位置
    112     XY loc;
    113     //起点终点的位置
    114     XY Start = { 4,0 }, End = { 0,8 };
    115 
    116     InitStack(&Path);
    117     //将起点入栈
    118     Push(&Path, Start.x, Start.y);
    119 
    120     //开始
    121     while (!GameOver(Path, &loc, End))
    122     {
    123         switch (SearchPath(Path, loc))
    124         {
    125         case Up:
    126             Push(&Path, loc.x - 1, loc.y);
    127             break;
    128         case Right:
    129             Push(&Path, loc.x, loc.y + 1);
    130             break;
    131         case Down:
    132             Push(&Path, loc.x + 1, loc.y);
    133             break;
    134         case Left:
    135             Push(&Path, loc.x, loc.y - 1);
    136             break;
    137         case EOR:
    138             Pop(&Path);
    139             break;
    140         default:
    141             printf("Shit Happened! Check your code!
    ");
    142             break;
    143         }
    144     }
    145     Print();
    146     DestroyStack(&Path);
    147     return 0;
    148 }

    最后运行结果如图

    有一行多出来的1,因为打印的是走过的路径。

    *如果你想自己更改迷宫地图的话,请务必记得更改相应的起点和终点(114行)

  • 相关阅读:
    Django 路由层
    HTTP协议
    Python并发编程之协程
    Django配置KindEditor
    Django Form
    pymysql模块
    javascript获取URL参数代码(网络摘抄)
    javascript 实现飘动的广告(网络收藏,转)
    游标的使用
    javascript 一个很好用的日历控件(网络收藏,转)
  • 原文地址:https://www.cnblogs.com/makejeffer/p/4811500.html
Copyright © 2020-2023  润新知