数据结构应用实例#栈#迷宫寻路
2015-09-15 21:11
369 查看
使用数据结构 栈(Stack)来实现一种低级的迷宫寻路的功能。
低级是因为无法判断路径是不是最短的。
这里使用的栈结构如图 (这图我选择死亡...)
注意结构体里DataType的实际含义,是另外一个结构体,用于储存二维位置x,y
地图使用一个10x10的二维数组来表示,数字1表示该点是墙壁,0表示可以行走,2表示已经走过的地方。
我们用栈来储存走过的位置,比如我们从起点(4,0)出发,就把(4,0)压入栈,并把该点数值改为2,意为已经来过了。
如果遇到死路,那就不停地出栈,直到栈顶的这个点周围有路可走为止。
逻辑部分伪代码如下
while(没有到达终点)
{
if(上下左右四个方向有路可走)
{
将可以走的那个位置(不是当前位置!)压入栈
}
else
{
出栈
}
}
[b]///////////以下是老版本////////////[/b]
首先是栈的头文件,注意栈结构体内容的具体定义
然后是定义
寻路的逻辑放在了main函数里,迷宫地图的定义也在这里
最后运行结果如图
有一行多出来的1,因为打印的是走过的路径。
*如果你想自己更改迷宫地图的话,请务必记得更改相应的起点和终点(114行)
低级是因为无法判断路径是不是最短的。
这里使用的栈结构如图 (这图我选择死亡...)
注意结构体里DataType的实际含义,是另外一个结构体,用于储存二维位置x,y
地图使用一个10x10的二维数组来表示,数字1表示该点是墙壁,0表示可以行走,2表示已经走过的地方。
我们用栈来储存走过的位置,比如我们从起点(4,0)出发,就把(4,0)压入栈,并把该点数值改为2,意为已经来过了。
如果遇到死路,那就不停地出栈,直到栈顶的这个点周围有路可走为止。
逻辑部分伪代码如下
while(没有到达终点)
{
if(上下左右四个方向有路可走)
{
将可以走的那个位置(不是当前位置!)压入栈
}
else
{
出栈
}
}
#include <stack> #include <iostream> using std::cout; using std::endl; using std::stack; const int MAZEWIDTH = 10; const int MAZEHEIGHT = 10; //0可走 //1墙 //2走过 //3走过又退回来了 int Maze[MAZEWIDTH][MAZEHEIGHT] = { //0 1 2 3 4 5 6 7 8 9 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,//0 1, 0, 1, 0, 0, 0, 1, 0, 0, 0,//1 1, 0, 0, 0, 1, 0, 1, 0, 0, 1,//2 1, 0, 1, 1, 0, 0, 1, 1, 0, 1,//3 1, 0, 1, 0, 0, 1, 0, 1, 0, 1,//4 0, 0, 1, 1, 0, 1, 0, 0, 0, 1,//5 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,//6 1, 0, 1, 1, 1, 0, 1, 0, 0, 1,//7 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,//8 1, 1, 1, 1, 1, 1, 1, 1, 1, 1//9 }; struct _XY { int x, y; _XY() { x = y = 0; } _XY(int a, int b) : x(a), y(b) { } int operator==(const struct _XY &a) { return (a.x == x) && (a.y == y); } }; typedef _XY XY; class MazeBreaker { private: int MazeMap[MAZEWIDTH][MAZEHEIGHT]; stack<XY> path; XY start, end; void push(XY xy) { path.push(xy); MazeMap[xy.x][xy.y] = 2; } void push(int x, int y) { path.push(XY(x, y)); MazeMap[x][y] = 2; } void pop() { if (!(path.top() == start)) { XY &loc = path.top(); MazeMap[loc.x][loc.y] = 3; path.pop(); } } int End() { return path.top() == end; } void ThereIsAWay() { XY &loc = path.top(); //UP if (MazeMap[loc.x - 1][loc.y] == 0) { push(loc.x - 1, loc.y); return; } //RIGHT if (MazeMap[loc.x][loc.y - 1] == 0) { push(loc.x, loc.y - 1); return; } //DOWN if (MazeMap[loc.x + 1][loc.y] == 0) { push(loc.x + 1, loc.y); return; } //LEFT if (MazeMap[loc.x][loc.y + 1] == 0) { push(loc.x, loc.y + 1); return; } pop(); return; } public: void GenerateMap() { for (int lop = 0; lop < MAZEWIDTH; lop++) { for (int lop2 = 0; lop2 < MAZEHEIGHT; lop2++) { MazeMap[lop][lop2] = Maze[lop][lop2]; } } push(start); } MazeBreaker() { start.x = 5; start.y = 0; end.x = 1; end.y = 9; } void FindPath() { while (!End()) { ThereIsAWay(); } for (int lop = 0; lop < MAZEWIDTH; lop++) { for (int lop2 = 0; lop2 < MAZEHEIGHT; lop2++) { if (MazeMap[lop][lop2] == 2) { cout << "O"; } else if (MazeMap[lop][lop2] == 3) { cout << "X"; } else { cout << " "; } } cout << endl; } } }; int main() { MazeBreaker mb; mb.GenerateMap(); mb.FindPath(); return 0; }
[b]///////////以下是老版本////////////[/b]
首先是栈的头文件,注意栈结构体内容的具体定义
Stack.h
#ifndef _STACK_H_ #define _STACK_H_ #include<stdio.h> #include<stdlib.h> //以下两个数据大小视实际情况而定 //初始栈容量 #define STACK_INIT_SIZE 20 //每次扩容的增量 #define STACKINCREMENT 10 //迷宫地图 int Maze[10][10]; //表示位置 struct xy { int x, y; }; typedef struct xy XY; typedef XY DataType; struct stack { //指向栈最顶上的元素的接下来一个位置 //表示新入栈的值可以放在指向的地方 DataType *Top; //指向栈底部,最里面的元素 DataType *Bottom; //表示了当前栈的容量 int stacksize; }; typedef struct stack STACK; //新建栈 int InitStack(STACK *S); //销毁栈 int DestroyStack(STACK *S); //返回顶层元素 int GetTop(STACK S,int *x,int *y); //Push操作,入栈,压栈 int Push(STACK *S, int x,int y); //Pop操作,出栈 int Pop(STACK *S); #endif
然后是定义
Stack.c
#include"Stack.h" int InitStack(STACK *S) { //创建出设定长度的顺序表,地址赋给bottom指针 S->Bottom = (DataType*)malloc(STACK_INIT_SIZE*sizeof(DataType)); if (!S->Bottom) { return 0; } S->stacksize = STACK_INIT_SIZE; S->Top = S->Bottom; return 1; } int DestroyStack(STACK *S) { S->Top = NULL; free(S->Bottom); S->Bottom = NULL; return 1; } int GetTop(STACK S, int *x, int *y) { if (S.Bottom != S.Top) { //由于top指向的是最顶上元素的下一个位置 //所以取出最顶上元素的时候 //要把top减去1 *x = ((S.Top - 1)->x); *y = ((S.Top - 1)->y); return 1; } return 0; } int Push(STACK *S, int x,int y) { //当超出当前栈的容量时 //这里应该只有等于的情况 //而不会大于 if ((S->Top - S->Bottom) >= S->stacksize) { //realloc函数将开辟指定的储存空间 //并将原来的数据全部移到这个新的储存空间 S->Bottom = (DataType*)realloc(S->Bottom, (S->stacksize + STACKINCREMENT)*sizeof(DataType)); if (!S->Bottom) { return 0; } //由于重新开辟了空间 //需要重新根据bottom指针的位置指定top S->Top = S->Bottom + S->stacksize; //最后增加当前栈容量 S->stacksize += STACKINCREMENT; } //再把入栈的数据存放好 (S->Top)->x = x; (S->Top)->y = y; S->Top++; //在地图上将该点标为2 Maze[x][y] = 2; return 1; } //将该点丢弃 int Pop(STACK *S) { if (S->Bottom == S->Top) { printf("Empty Stack!Can not pop!\n"); return 0; } //top指针先减1再取值 --S->Top; return 1; }
寻路的逻辑放在了main函数里,迷宫地图的定义也在这里
main.c
二维数组Maze存放了迷宫的信息,你也可以自己改改*。#include"Stack.h" #define Up 1 #define Right 2 #define Down 3 #define Left 4 //代表已无路可走 //End of Road #define EOR 5 //迷宫的地图 //墙壁表示为1,可走的地方表示为0,走过的地方表示为2 //入口为(4,0),出口为(0,8) //可自行更改,但请确保有通路 Maze[10][10] = { //0,1,2,3,4,5,6,7,8,9 1,1,1,1,1,1,1,1,0,1, //0 1,0,0,0,0,0,0,1,0,1, //1 1,0,1,0,1,1,1,1,0,1, //2 1,0,1,0,1,0,0,0,0,1, //3 0,0,1,0,1,0,1,0,1,1, //4 1,0,1,0,1,0,1,0,1,1, //5 1,1,0,0,1,0,1,0,1,1, //6 1,0,0,1,1,0,1,0,1,1, //7 1,0,0,0,0,0,1,0,0,1, //8 1,1,1,1,1,1,1,1,1,1 }; //9 //打印结果 int Print() { int lop, lop2; for (lop = 0; lop < 10; lop++) { for (lop2 = 0; lop2 < 10; lop2++) { if (Maze[lop][lop2] == 2) { printf("1"); } else { printf(" "); } } printf("\n"); } return 1; } int GameOver(STACK s, XY *loc,XY End) { GetTop(s, &(loc->x), &(loc->y)); if (loc->x == End.x && loc->y == End.y) { return 1; } else { return 0; } } //1 up.2 right.3 down.4 left //看看当前位置的上下左右还有没有能走的地方 int SearchPath(STACK s, XY loc) { int x, y; x = loc.x; y = loc.y; //Up Available? if (x != 0) { if (!Maze[x - 1][y]) { return Up; } } //Right ? if (y != 9) { if (!Maze[x][y + 1]) { return Right; } } //Down? if (x != 9) { if (!Maze[x + 1][y]) { return Down; } } //Left? if (y != 0) { if (!Maze[x][y - 1]) { return Left; } } return EOR; } int main() { //储存走出迷宫的路径 STACK Path; //储存当前位置 XY loc; //起点终点的位置 XY Start = { 4,0 }, End = { 0,8 }; InitStack(&Path); //将起点入栈 Push(&Path, Start.x, Start.y); //开始 while (!GameOver(Path, &loc, End)) { switch (SearchPath(Path, loc)) { case Up: Push(&Path, loc.x - 1, loc.y); break; case Right: Push(&Path, loc.x, loc.y + 1); break; case Down: Push(&Path, loc.x + 1, loc.y); break; case Left: Push(&Path, loc.x, loc.y - 1); break; case EOR: Pop(&Path); break; default: printf("Shit Happened! Check your code!\n"); break; } } Print(); DestroyStack(&Path); return 0; }
最后运行结果如图
有一行多出来的1,因为打印的是走过的路径。
*如果你想自己更改迷宫地图的话,请务必记得更改相应的起点和终点(114行)
相关文章推荐
- 退役狗回来继续写博客……C++数据结构//我觉得自己深深地被djh老师给欺骗了
- 数据结构-栈
- C++实现数据结构线性表顺序存储结构
- 数据结构与算法分析(c++版) #3 顺序表的实现
- 数据结构_单链表的逆置
- 数据结构(Data Structures)
- Java数据结构与算法之数组(一)
- java数据结构与算法之概述
- [转载] 十五分钟介绍 Redis数据结构
- 推荐一个数据结构网站
- 数据结构之简单四则运算表达式求值8-(栈的实现)
- 浅谈数据结构-交换排序(冒泡、快速)
- cocos基础教程(5)数据结构介绍之cocos2d::Value
- 循环队列-顺序存储结构-数据结构
- cocos基础教程(5)数据结构介绍之cocos2d::Map<K,V>
- 数据结构与算法分析(c++版) #2 初涉线性表
- cocos基础教程(5)数据结构介绍之cocos2d::Vector
- 什么是数据结构?
- 《我眼中的R语言》 ——(1) 【数据结构】
- 数据结构之——归并排序