标签:
设位置[i][j]标记为X,它实际是一系列交通路口。X周围有8个前进方向,分别代表8个前进位置。如果某一方向是0值,表示该方向有路可通,否则表示该方向已堵死。为了有效地选择下一位置,可以将从位置[i][j]出发可能的前进方向预先定义在一个表内。
(1)可能的前进方向示意图:
(2)前进方向表move:
Move[q].dir | move[q].a | move[q].b |
---|---|---|
“N” | -1 | 0 |
“NE” | -1 | 1 |
“E” | 0 | 1 |
“SE” | 1 | 1 |
“S” | 1 | 0 |
“SW” | 1 | -1 |
“W” | 0 | -1 |
“NW” | -1 | -1 |
文件:MazeConfig.h
#pragma once
#include <iostream>
#include <windows.h>
using namespace std;
//网格的结构定义
struct GridType
{
int x;//网格的x坐标
int y;//网格的y坐标
};
//位置在直角坐标下的偏移量的结构定义
struct MoveTable
{
int a;//x方向上的偏移
int b;//y方向上的偏移
char *dir;//移动的方向
};
const int m = 14;//迷宫的行数
const int p = 17;//迷宫的列数
const int pathmark = 6;//迷宫通路网格标识值
static int mark[m][p];//访问标记数组
GridType entry = {1, 0};//迷宫入口网格坐标
GridType exitus = {m-2, p-1};//迷宫出口网格坐标
//各个方向的偏移表定义
MoveTable moveTable[8] =
{
{-1, 0, "N"},
{-1, 1, "NE"},
{0, 1, "E"},
{1, 1, "SE"},
{1, 0, "S"},
{1, -1, "SW"},
{0, -1, "W"},
{-1, -1, "NW"}
};
//初始化迷宫
int Maze[m][p] =
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1 },
{ 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1 },
{ 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 },
{ 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 },
{ 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1 },
{ 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
{ 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
//初始化访问标记数组
void init_mark()
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < p; j++)
{
mark[i][j] = 0;
}
}
}
//打印迷宫
void print_maze()
{
cout << "======>MazePath" << endl;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < p; j++)
{
if (Maze[i][j] == pathmark)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
}
cout << Maze[i][j] << " ";
}
cout << endl;
}
}
文件:SeekPath.h
#pragma once
#include "MazeConfig.h"
//从迷宫某一位置[i][j]开始,寻找通向出口的一条路径。
//如果找到,则函数返回1。
//如果没找到,则函数返回0。
int SeekPath(GridType curGrid)
{
if ((curGrid.x == exitus.x) && (curGrid.y == exitus.y))
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
cout << "======>SeekPath Success" << endl;
return 1;//已到达出口,函数返回1。
}
GridType nextGrid;//下一个网格的位置
for (int i = 0; i < 8; i++)//依次按每一个方向寻找通向出口的路径
{
nextGrid.x = curGrid.x + moveTable[i].a;
nextGrid.y = curGrid.y + moveTable[i].b;
if ((Maze[nextGrid.x][nextGrid.y] == 0) && (mark[nextGrid.x][nextGrid.y] == 0))
{
//下一位置可通,试探该方向
mark[nextGrid.x][nextGrid.y] = 1;//标记为已访问过
if (SeekPath(nextGrid) != 0)//从此位置递归试探
{
//cout << "(" << nextGrid.x << "," << nextGrid.y << ")," << "Direction:" << moveTable[i].dir << ", ";
Maze[nextGrid.x][nextGrid.y] = pathmark;
return 1;//试探成功,逆向输出路径坐标
}
}
//回溯,换一个方向再试探通向出口的路径。
}
if ((curGrid.x == entry.x) && (curGrid.y == entry.y))
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
cout << "======>SeekPath Fail" << endl;
}
return 0;//无可通路到出口,函数返回0。
}
文件:main.cpp
#include "SeekPath.h"
int main()
{
print_maze();
init_mark();
if (SeekPath(entry) != 0)
{
//cout << "(" << entry.x << "," << entry.y << ")" << endl;
Maze[entry.x][entry.y] = pathmark;
print_maze();
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
system("pause");
return 0;
}
文件:LinkNode.h
#ifndef LINK_NODE_H_
#define LINK_NODE_H_
#include <iostream>
#include <string>
#include <strstream>
using namespace std;
template <class T>
struct LinkNode //链表结点类的定义
{
T data; //数据域
LinkNode<T> *link; //指针域——后继指针
//仅初始化指针成员的构造函数
LinkNode(LinkNode<T>* ptr = NULL){ link = ptr; }
//初始化数据与指针成员的构造函数
LinkNode(const T& value, LinkNode<T>* ptr = NULL){ data = value; link = ptr; }
};
#endif /* LINK_NODE_H_ */
文件:LinkedStack.h
#ifndef LINKED_STACK_H_
#define LINKED_STACK_H_
#include "LinkNode.h"
#include "Stack.h"
template <class T>
class LinkedStack
{
public:
LinkedStack(); //构造函数
~LinkedStack(); //析构函数
public:
void Push(const T& x) ; //新元素x进栈
bool Pop(T& x); //栈顶元素出栈,并将该元素的值保存至x
LinkNode<T>* getTop() const; //获取栈顶结点
bool IsEmpty() const; //判断栈是否为空
void MakeEmpty(); //清空栈的内容
private:
LinkNode<T> *top; //栈顶指针,即链头指针
};
//构造函数
template <class T>
LinkedStack<T>::LinkedStack()
: top(NULL)
{
cout << "$ 执行构造函数" << endl;
}
//析构函数
template <class T>
LinkedStack<T>::~LinkedStack()
{
cout << "$ 执行析构函数" << endl;
MakeEmpty();
}
//新元素x进栈
template <class T>
void LinkedStack<T>::Push(const T& x)
{
LinkNode<T> *newNode = new LinkNode<T>(x);
newNode->link = top;
top = newNode;
}
//栈顶元素出栈,并将该元素的值保存至x
template <class T>
bool LinkedStack<T>::Pop(T& x)
{
if (true == IsEmpty())
{
return false;
}
LinkNode<T> *curNode = top;
top = top->link;
x = curNode->data;
delete curNode;
return true;
}
//获取栈顶结点
template <class T>
LinkNode<T>* LinkedStack<T>::getTop() const
{
return top;
}
//判断栈是否为空
template <class T>
bool LinkedStack<T>::IsEmpty() const
{
return (NULL == top) ? true : false;
}
//清空栈的内容
template <class T>
void LinkedStack<T>::MakeEmpty()
{
LinkNode<T> *curNode = NULL;
while (NULL != top) //当链表不为空时,删去链表中所有结点
{
curNode = top; //保存被删结点
top = curNode->link; //被删结点的下一个结点成为头结点
delete curNode; //从链表上摘下被删结点
}
}
#endif /* LINKED_STACK_H_ */
文件:MazeConfig.h
#ifndef MAZECONFIG_H_
#define MAZECONFIG_H_
#include <iostream>
#include <windows.h>
using namespace std;
//网格的结构定义
struct GridType
{
int x;//网格的x坐标
int y;//网格的y坐标
};
//位置在直角坐标下的偏移量的结构定义
struct MoveTable
{
int a;//x方向上的偏移
int b;//y方向上的偏移
char *dir;//移动的方向
};
const int m = 14;//迷宫的行数
const int p = 17;//迷宫的列数
const int pathmark = 6;//迷宫通路网格标识值
static int mark[m][p];//访问标记数组
GridType entry = { 1, 0 };//迷宫入口网格坐标
GridType exitus = { m - 2, p - 1 };//迷宫出口网格坐标
//各个方向的偏移表定义
MoveTable moveTable[8] =
{
{ -1, 0, "N" },
{ -1, 1, "NE" },
{ 0, 1, "E" },
{ 1, 1, "SE" },
{ 1, 0, "S" },
{ 1, -1, "SW" },
{ 0, -1, "W" },
{ -1, -1, "NW" }
};
//初始化迷宫
int Maze[m][p] =
{
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1 },
{ 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1 },
{ 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1 },
{ 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 },
{ 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 },
{ 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1 },
{ 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
{ 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
//初始化访问标记数组
void init_mark()
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < p; j++)
{
mark[i][j] = 0;
}
}
}
//打印迷宫
void print_maze()
{
cout << "======>MazePath" << endl;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < p; j++)
{
if (Maze[i][j] == pathmark)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
}
cout << Maze[i][j] << " ";
}
cout << endl;
}
}
#endif /* MAZECONFIG_H_ */
文件:SeekPath.h
#ifndef SEEKPATH_H_
#define SEEKPATH_H_
#include "MazeConfig.h"
#include "LinkedStack.h"
//从迷宫某一位置[i][j]开始,寻找通向出口[m][p]的一条路径。
template <class T>
void SeekPath(LinkedStack<T>* st, GridType curGrid)
{
GridType nextGrid;//下一个网格的位置
st->Push(curGrid);
while (st->IsEmpty() == false)
{
st->Pop(curGrid);
for (int d = 0; d < 8; d++)
{
nextGrid.x = curGrid.x + moveTable[d].a;
nextGrid.y = curGrid.y + moveTable[d].b;
if ((nextGrid.x == exitus.x) && (nextGrid.y == exitus.y))
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
cout << "======>SeekPath Success" << endl;
st->Push(curGrid);
st->Push(nextGrid);
return;
}
if ((Maze[nextGrid.x][nextGrid.y] == 0) && (mark[nextGrid.x][nextGrid.y] == 0))
{
mark[nextGrid.x][nextGrid.y] = 1;//标记为已访问过
st->Push(curGrid);
curGrid = nextGrid;
d = 0;
}
}
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
cout << "======>SeekPath Fail" << endl;
}
template <class T>
void MarkPath(LinkedStack<T>* st)
{
LinkNode<T> *curNode = st->getTop();
while (NULL != curNode)
{
GridType item = curNode->data;
Maze[item.x][item.y] = pathmark;
curNode = curNode->link;
}
}
#endif /* SEEKPATH_H_ */
文件:main.cpp
#include "SeekPath.h"
int main(int argc, char* argv[])
{
print_maze();
init_mark();
LinkedStack<GridType> *linkedStack = new LinkedStack<GridType>;
SeekPath(linkedStack, entry);
MarkPath(linkedStack);
print_maze();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
delete linkedStack;
linkedStack = NULL;
system("pause");
return 0;
}
参考文献:
[1]《数据结构(用面向对象方法与C++语言描述)(第2版)》殷人昆——第三章
[2]?百度搜索关键字:迷宫问题、回溯法、试探法
迷宫问题(MazePath)的求解——利用回溯法(backtracking)
标签:
原文地址:http://blog.csdn.net/cainv89/article/details/51477947