2022/7/22
今天准备做一个递归dfs的图形展现。
先附上源代码:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <graphics.h>
#include <tchar.h>
#include <Windows.h>
using namespace std;
#define maxsize 10
#define PER_UNIT_LENGTH 64
enum mapVal{map_null, map_block, map_passed};
int realMap[maxsize][maxsize] = {
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,0,0,0,0,0,1},
{1,0,0,0,0,1,0,1,0,1},
{1,1,1,1,1,1,0,1,0,1},
{1,0,0,0,0,0,0,1,0,1},
{1,0,1,1,0,1,0,1,0,1},
{1,0,0,1,0,1,0,1,0,1},
{1,1,1,1,0,1,0,1,1,1},
{1,0,0,0,0,1,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1},
};
struct MyPoint {
int row;
int col;
};
MyPoint startPoint = { 1, 1 }, endPoint = { 8, 8 };
stack<MyPoint> sta_path;
const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, -1, 0, 1 };
IMAGE hb;
void initMap() {
int i, j;
BeginBatchDraw();
loadimage(&hb, "handsome_hb.jpg", PER_UNIT_LENGTH, PER_UNIT_LENGTH);
putimage(startPoint.row * PER_UNIT_LENGTH, startPoint.col * PER_UNIT_LENGTH, &hb);
setfillcolor(GREEN);
for (i = 0; i < maxsize; i++) {
for (j = 0; j < maxsize; j++) {
if(realMap[i][j] == 1)
fillrectangle(j * PER_UNIT_LENGTH, i * PER_UNIT_LENGTH, (j + 1) * PER_UNIT_LENGTH, (i + 1) * PER_UNIT_LENGTH);
}
}
EndBatchDraw();
}
void drawMap() {
int i, j;
BeginBatchDraw();
loadimage(&hb, "handsome_hb.jpg", PER_UNIT_LENGTH, PER_UNIT_LENGTH);
putimage(startPoint.row * PER_UNIT_LENGTH, startPoint.col * PER_UNIT_LENGTH, &hb);
for (i = 0; i < maxsize; i++) {
for (j = 0; j < maxsize; j++) {
//因为是画图,所以只要对realMap不同区域判断并画图就行了
if (realMap[i][j] == map_null) {
setfillcolor(WHITE);
fillrectangle(j * PER_UNIT_LENGTH, i * PER_UNIT_LENGTH, (j + 1) * PER_UNIT_LENGTH, (i + 1) * PER_UNIT_LENGTH);
}
if (realMap[i][j] == map_block) {
setfillcolor(GREEN);
fillrectangle(j * PER_UNIT_LENGTH, i * PER_UNIT_LENGTH, (j + 1) * PER_UNIT_LENGTH, (i + 1) * PER_UNIT_LENGTH);
}
if (realMap[i][j] == map_passed) {
putimage(j * PER_UNIT_LENGTH, i * PER_UNIT_LENGTH, &hb);
}
}
}
EndBatchDraw();
}
bool dfs(MyPoint pos) {
//每次循环暂停10毫秒
Sleep(10);
//判断边界
//墙和走过的地方
//因为是判定能否走到,所以用handMap来判断
if (realMap[pos.row][pos.col] == map_block) { //碰到墙
return false;
}
if (realMap[pos.row][pos.col] == map_passed) { //走到走过的地方
return false;
}
if (pos.row == endPoint.row && pos.col == endPoint.col) {
putimage(pos.col * PER_UNIT_LENGTH, pos.row * PER_UNIT_LENGTH, &hb); //终点并不会绘制到
sta_path.push(pos); //下面一直是在将上一个pos推入路径栈的,所以终点的路径并没有推入栈,我们需要将其推入栈
return true;
}
//到这个地方说明没有碰到障碍物或者走回头路,那么访问该点将赋值为map_passed,变成走过的地方
realMap[pos.row][pos.col] = map_passed;
//循环遍历下一个地方
int i;
MyPoint next_pos;
for (i = 0; i < 4; i++) {
next_pos.row = pos.row + dx[i];
next_pos.col = pos.col + dy[i]; //给下一个地方赋值
BeginBatchDraw();
system("cls");
drawMap();
EndBatchDraw();
if (dfs(next_pos)) { //不断递归
sta_path.push(pos); //下一个能走的话,将上一个插入栈中
return true;
}
}
return false;
}
int main()
{
initgraph(640, 640/*, SHOWCONSOLE*/);
setfillcolor(WHITE);
fillrectangle(0, 0, 640, 640);
initMap();
MyPoint pos = startPoint;
if (dfs(pos) == true) { //能够找到终点
//不用注意,这就是一个路径栈,用来显示路径
while (!sta_path.empty()) {
MyPoint buffer_pos;
buffer_pos = sta_path.top();
sta_path.pop();
cout << "{" << buffer_pos.row << "," << buffer_pos.col << "}" << endl;
}
}
TCHAR str[30];
sprintf(str, "请结束程序!");
MessageBox(NULL, str, "走出迷宫", MB_OK | MB_SYSTEMMODAL);
closegraph();
system("pause");
return 0;
}
“出现的问题”
- DFS 递归的特点就是一直会在递归函数里面执行程序,这导致我这个只会用图形库的初学者不能很好地将底层数组分析功能和外层图形绘画功能给分开,代码看上去很乱。而且对于初学者递归调用整个过程也不是很好理解和检测的,C++面向对象的模式没有很好地做到。
- 本来想实现只把头部绘制出来,但是好像设置的DFS函数没有保存中心点的位置,不管怎么写,中心点都是白色的。
“DFS的理解”
- 现在看到的两种dfs搜索方式主要是递归调用还有栈结构的调用来记录路径。前者可以借助递归而简化代码量,而不好的就是可读性和分析性下降,代码的规范性不高;后者代码量可能会稍多一些,不过高规范性也比递归要容易达到。
“beautiful”
大帅比