DFS 图形展现

这篇博客探讨了如何使用深度优先搜索(DFS)算法来绘制图形化的迷宫路径。作者通过C++实现了一个递归DFS函数,但在代码组织和可读性方面遇到了挑战。文中提到了递归DFS的优缺点,包括简化代码但降低可读性,并讨论了如何通过栈结构来记录路径。尽管尝试只显示路径头部,但作者发现中心点总是显示为白色,未能正确保存路径信息。博客最后总结了DFS的理解,并表达了对提高代码规范性的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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;
}


 “出现的问题”

  1. DFS 递归的特点就是一直会在递归函数里面执行程序,这导致我这个只会用图形库的初学者不能很好地将底层数组分析功能和外层图形绘画功能给分开,代码看上去很乱。而且对于初学者递归调用整个过程也不是很好理解和检测的,C++面向对象的模式没有很好地做到。
  2. 本来想实现只把头部绘制出来,但是好像设置的DFS函数没有保存中心点的位置,不管怎么写,中心点都是白色的。

“DFS的理解”

  1. 现在看到的两种dfs搜索方式主要是递归调用还有栈结构的调用来记录路径。前者可以借助递归而简化代码量,而不好的就是可读性和分析性下降,代码的规范性不高;后者代码量可能会稍多一些,不过高规范性也比递归要容易达到。

“beautiful”

大帅比

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值