一、深度寻路算法原理
第一步,我们要规定好人物的试探方向 : 即上右下左,上左下右
什么意思呢?就是计算机中的人物要看看自己的四周是空地还是墙,如果是墙就不能走,是空地则可以走。
第二步、 我们要进行实时记录
为什么要实时进行记录,那是因为我们需要确定每个点是否已经走过,走过去之后,如果走到尽头就需要回退,所以每走一步,都需要存储一下当前点的位置(那么最好便是利用栈结构)。
这样,等人物达到尽头,没有找到终点需要回退的时候,出栈,返回当前栈顶元素,让当前点返回到上一个,就和游戏的存档一样,回到了上一步。
而最后到达终点,栈结构就已经存储了从开始到终点的路径,若是想要看路径,既可以在控制台以字符串的形式释放打印,也可以在图形化中用其他图片展示。
二、现在开始代码
这里的栈结构我自己写一个,因为效果是比较简单的,很多功能并不需要。
这里的头文件和cpp文件要一起使用。
头文件:
#pragma once
#include<iostream>
//深度寻路算法需要的功能
//入栈
//出栈
template<class _Ty>
class myStack {
public:
_Ty* pNode;
int len;
int maxLen;
public:
myStack() { pNode = NULL; len = maxLen = 0; }
~myStack()
{
if (pNode)
{
delete[] pNode;
pNode = NULL;
len = maxLen = 0;
}
}
//入栈
void push(const _Ty& data);
//出栈
void pop() { if (len > 0)len--; }
//获取当前栈顶元素 因为不知道创建的是什么类型,所以用_Ty
_Ty getTop() { return pNode[len - 1]; }
//判断栈是否为空
bool isEmpty() { return (len == 0); }
};
//入栈
template<class _Ty>
void myStack<_Ty>::push(const _Ty& data)
{
if (maxLen<=len)
{//判断需要申请的内存 >>右移,等同于/2
maxLen = maxLen + (((maxLen >> 1) > 1) ? (maxLen >> 1) : 1);
}
_Ty* pNew = new _Ty[maxLen];
if (pNode)
{
memcpy(pNew, pNode, sizeof(_Ty) * len);
delete[] pNode;
}
pNode = pNew;
pNew[len++] = data;
}
cpp文件:
#include"testZhang.h"
#include<graphics.h>
using namespace std;
#define ROWS 10
#define COLS 10
//方向枚举
enum direct { p_up, p_right, p_down, p_left };//0,1,2,3
//辅助地图
struct pathNode
{
int dir; //方向
bool isFind; //是否走过,0没走过 ,1走过
};
//点类型
struct MyPoint
{
int row;
int col;
bool operator==(const MyPoint& p1)
{
if (row == p1.row && col == p1.col)
{
return true;
}
return false;
}
};
//正方形宽高
#define SPACE 80
IMAGE ren, road, wall, endpos;
void initGame();
void drawMap(int map[ROWS][COLS], MyPoint pos);
void printMap(int map[ROWS][COLS], MyPoint pos);
int main()
{
initGame();
//地图
int map[ROWS][COLS] = {
{1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,0,1,0,0,0,1},
{1,0,1,0,0,0,0,1,1,1},
{1,0,0,0,1,1,0,0,0,1},
{1,0,1,0,0,0,1,0,1,1},
{1,0,1,1,1,0,0,0,1,1},
{1,0,0,0,1,0,1,0,1,1},
{1,0,1,1,1,0,1,0,1,1},
{1,1,1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
pathNode pathMap[ROWS][COLS] = { 0 };
//回退功能,可以用标准模板库的栈结构,也可以自己写 这里我自己做一个
//准备一个栈
myStack<MyPoint> stack;
//起点 和 终点
MyPoint begPos = { 1,1 };
MyPoint endPos = { 8,3 };
//起点入栈
stack.push(begPos);
//标记起点走过
pathMap[begPos.row][begPos.col].isFind = true;
//当前点
MyPoint currentPos = begPos;
//试探点
MyPoint searchPos;
//是否找到终点
bool isFind = false;
while (1)//循环寻路
{
//找出试探点
searchPos = currentPos;
switch (pathMap[currentPos.row][currentPos.col].dir)//是什么方向
{
case p_up:
searchPos.row--;
//更改当前点的试探方向 通过枚举的++改变方向
pathMap[currentPos.row][currentPos.col].dir++;
//判断能否走
if (map[searchPos.row][searchPos.col] == 0 &&//是路
pathMap[searchPos.row][searchPos.col].isFind == false)
{//能走
//走
currentPos = searchPos;
//标记当前点走过
pathMap[currentPos.row][currentPos.col].isFind = true;
//入栈
stack.push(currentPos);
}
break;
case p_right:
searchPos.col++;
//更改当前点的试探方向 通过枚举的++改变方向
pathMap[currentPos.row][currentPos.col].dir++;
//判断能否走
if (map[searchPos.row][searchPos.col] == 0 &&//是路
pathMap[searchPos.row][searchPos.col].isFind == false)
{//能走
//走
currentPos = searchPos;
//标记当前点走过
pathMap[currentPos.row][currentPos.col].isFind = true;
//入栈
stack.push(currentPos);
}
break;
case p_down:
searchPos.row++;
//更改当前点的试探方向 通过枚举的++改变方向
pathMap[currentPos.row][currentPos.col].dir++;
//判断能否走
if (map[searchPos.row][searchPos.col] == 0 &&//是路
pathMap[searchPos.row][searchPos.col].isFind == false)
{//能走
//走
currentPos = searchPos;
//标记当前点走过
pathMap[currentPos.row][currentPos.col].isFind = true;
//入栈
stack.push(currentPos);
}
break;
case p_left:
searchPos.col--;
//因为往左是最后一个方向,所有可以赋值为0 也可以不搞
//判断能否走
if (map[searchPos.row][searchPos.col] == 0 &&//是路
pathMap[searchPos.row][searchPos.col].isFind == false)
{//能走
//走
currentPos = searchPos;
//标记当前点走过
pathMap[currentPos.row][currentPos.col].isFind = true;
//入栈
stack.push(currentPos);
}
else//死胡同
{
stack.pop();//删除顶元素
currentPos = stack.getTop();//跳到栈顶元素
}
break;
}
//延迟看效果
Sleep(100);
drawMap(map, currentPos);
printMap(map, currentPos);
//判断是否到达终点
if (endPos == currentPos)
{
isFind = true;
break;
}
//判断栈是否为空
if (stack.isEmpty())
{
break;
}
}
int x, y;
if (isFind)
{
cout << "找到终点了";
while (!stack.isEmpty())
{
x = stack.getTop().row;
y = stack.getTop().col;
cout << "[" << x << "," << y << "] ";
putimage(y* SPACE+SPACE/4 , x* SPACE+SPACE/4 , &endpos);//找到终点后显示路径
stack.pop();
}
cout << endl;
}
while (1) {}
return 0;
}
void initGame()
{
initgraph(COLS * SPACE, ROWS * SPACE, SHOWCONSOLE);
loadimage(&ren, "res/pic_ShengDu/ren.bmp", SPACE, SPACE, true);
loadimage(&wall, "res/pic_ShengDu/wall.bmp", SPACE, SPACE, true);
loadimage(&road, "res/pic_ShengDu/road.bmp", SPACE, SPACE, true);
loadimage(&endpos, "res/pic_ShengDu/pos.bmp", SPACE/2, SPACE/2, true);
}
void printMap(int map[ROWS][COLS], MyPoint pos)
{
system("cls");
for (int i = 0; i < ROWS; i++)
{
for (int k = 0; k < COLS; k++)
{
if (i == pos.row && k == pos.col)
{
cout << "人";
}
else if (1 == map[i][k])
{
cout << "墙";
}
else if (0 == map[i][k])
{
cout << " ";
}
}
cout << endl;
}
}
void drawMap(int map[ROWS][COLS], MyPoint pos)
{
system("cls");
for (int i = 0; i < ROWS; i++)
{
for (int k = 0; k < COLS; k++)
{
if (i == pos.row && k == pos.col)
{
putimage(k * SPACE, i * SPACE, &ren);
}
else if (1 == map[i][k])
{
putimage(k * SPACE, i * SPACE, &wall);
}
else if (0 == map[i][k])
{
putimage(k * SPACE, i * SPACE, &road);
}
}
}
}