一、项目思路
该项目应用于计算机软件课设。该项目主要分成两部分迷宫生成与自动寻路,两部分都采用DFS算法。迷宫生成参考文章:
经验分享:三套简单的迷宫地图生成方案(思路一:主路扭曲型)
实验结果:
20230123_194707
二、代码
Maze_generation.h
#pragma once
#include <graphics.h>
#include <Windows.h>
#include <math.h>
#include <iostream>
#include<utility>
#include<stack>
#define WIDTH 350//分辨率
#define HEIGHT 350
#define BLOCK_XY 10//小方格边长
const int BLOCK_WIDTH = WIDTH / (BLOCK_XY);//小方格x轴数量
const int BLOCK_HEIGHT = HEIGHT / (BLOCK_XY);//小方格y轴数量
#define Road COLORREF RGB(0,0,0)//路 黑色
#define Wall COLORREF RGB(255,255,255)//墙壁 白色
#define ReadBlock COLORREF RGB(235,51,36) //选中的格子
#define Point COLORREF RGB(0,35,245)//起点,重点
#define Path COLORREF RGB(240,134,80) //寻路路径
#define BeginPoint 6
#define EndPoint 7
#define RoadDisplay 9
class Maze_generation
{
private:
int X_index;
int Y_index;
public:
void Initialize();
int IsHaveNeighbour(int X_index, int Y_index);
void Generation(int X_index, int Y_index);
void Drawing(int x, int y, COLORREF RGB);
void Display();
void DispalyPath();
void clearscreen(COLORREF RGB);//清空地图为RGB颜色(带有网格)
void setBeginPoint(int x, int y);
void setEndPoint(int x, int y);
void findPathDFS();
};
Maze_generation.cpp
#include "Maze_generation.h"
using namespace std;
int map[BLOCK_HEIGHT][BLOCK_WIDTH];
const int dirx[4] = { 0,1,0,-1 };
const int diry[4] = { 1,0,-1,0 };
int startx = 1;
int starty = 1;
int endx = BLOCK_HEIGHT - 2;
int endy = BLOCK_WIDTH - 2;
//为DFS服务
struct pathNode {
int dir; //方向
bool isFind; //0为没走过 1为走过
};
pathNode path[BLOCK_HEIGHT][BLOCK_WIDTH] = { 0 };
stack<Maze_generation>DFSpoint;
enum dir { p_up = 0, p_down = 1, p_left = 2, p_right = 3 };
void Maze_generation::Initialize()
{
int i, j;
for (i = 0; i < BLOCK_HEIGHT; i++) //通过后将地图初始化成全0的
for (j = 0; j < BLOCK_WIDTH; j++)//i为行,j为列
map[i][j] = 0;
//将所需地图以外的初始化为空白,其余空地和墙壁间隔
for (i = 0; i < BLOCK_HEIGHT; i++)
{
for (j = 0; j < BLOCK_WIDTH; j++)
{
if (i != 0 && j != 0 && i != BLOCK_HEIGHT - 1 && j != BLOCK_WIDTH -1) //迷宫围墙内
{
if (i % 2 != 0) //i为奇数
if (j % 2 != 0)//j为奇数
map[i][j] = 1;
}
}
}
}
int Maze_generation::IsHaveNeighbour(int X_index, int Y_index)
{
//上 下 左 右
if ((X_index >= 3 && map[X_index - 2][Y_index] == 1) || (X_index < BLOCK_HEIGHT - 3 && map[X_index + 2][Y_index] == 1) || (Y_index >= 3 && map[X_index][Y_index - 2] == 1) || (Y_index < BLOCK_WIDTH - 3 && map[X_index][Y_index + 2] == 1))
return 1;
return 0;
}
void Maze_generation::Generation(int X_index, int Y_index)
{
int rand_position, x, y, flag = 0;
x = X_index;
y = Y_index;
while (1)
{
flag = 0;
flag = IsHaveNeighbour(X_index, Y_index); //是否有邻居
if (flag == 0) //无邻居
{
return;
}
else //有邻居
{
map[X_index][Y_index] = 5;
Drawing(X_index, Y_index, ReadBlock);
FlushBatchDraw();
Display();
x = X_index;
y = Y_index;
while (1)
{
rand_position = rand() % 4; //随机一个方向
if (rand_position == 0 && X_index >= 3 && map[X_index - 2][Y_index] == 1)//上
{
X_index = X_index - 2;
}
else if (rand_position == 1 && X_index < BLOCK_HEIGHT - 3 && map[X_index + 2][Y_index] == 1)//下
{
X_index = X_index + 2;
}
else if (rand_position == 2 && Y_index >= 3 && map[X_index][Y_index - 2] == 1)//左
{
Y_index -= 2;
}
else if (rand_position == 3 && Y_index < BLOCK_WIDTH - 3 && map[X_index][Y_index + 2] == 1)//右
{
Y_index += 2;
}
map[(x + X_index) / 2][(y + Y_index) / 2] = 5;
Drawing(X_index, Y_index,Road);
FlushBatchDraw();
Display();
map[X_index][Y_index] = 5;
Generation(X_index, Y_index); //递归 flag==0 返回到此处
break;
}
}
}
}
void Maze_generation::Drawing(int x, int y, COLORREF RGB)
{
setfillcolor(RGB); setlinecolor(COLORREF RGB(55, 126, 71));
fillrectangle(x * BLOCK_XY, y * BLOCK_XY, BLOCK_XY + x * BLOCK_XY, BLOCK_XY + y * BLOCK_XY);
}
void Maze_generation::Display()
{
for (int y = 0; y < BLOCK_HEIGHT; y++) {
for (int x = 0; x < BLOCK_WIDTH; x++) {
if (map[x][y] == 0) {
Drawing(x, y, Wall);
}
else if (map[x][y] == 5) {
Drawing(x, y, Road);
}
else if (map[x][y] == BeginPoint || map[x][y] == EndPoint) {
Drawing(x, y,Point);
}
}
}
FlushBatchDraw();
}
void Maze_generation::clearscreen(COLORREF RGB)
{
for (int y = 0; y < BLOCK_HEIGHT; y++) {
for (int x = 0; x < BLOCK_WIDTH; x++) {
Drawing(x, y, RGB);
}
}
}
void Maze_generation::setBeginPoint(int x, int y)
{
X_index = x;
Y_index = y;
map[x][y] = BeginPoint;
Drawing(X_index, Y_index, Point);
FlushBatchDraw();
Display();
}
void Maze_generation::setEndPoint(int x, int y)
{
X_index = x;
Y_index = y;
map[x][y] == EndPoint;
Drawing(X_index, Y_index, Point);
FlushBatchDraw();
Display();
}
void Maze_generation::findPathDFS()
{
bool find = false;
Maze_generation start;
start.X_index = startx;
start.Y_index = starty;
path[start.X_index][start.Y_index].dir = 0;
path[start.X_index][start.Y_index].isFind = 1;
path[17][17].isFind = 0;
DFSpoint.push(start);
Maze_generation current;
Maze_generation search;
current = start;
while (1) {
search = current;
switch (path[current.X_index][current.Y_index].dir) {
case p_up:
search.Y_index--;
path[current.X_index][current.Y_index].dir = p_down;
if (path[search.X_index][search.Y_index].isFind == 0 && (map[search.X_index][search.Y_index] == 5 || map[search.X_index][search.Y_index] == EndPoint)) {
current = search;
path[search.X_index][search.Y_index].isFind = 1;
DFSpoint.push(search);
cout << "successs p_up" << '\t' << current.X_index << '\t' << current.Y_index << endl;
}
else {
cout << "faile p_up" << '\t' << current.X_index << '\t' << current.Y_index << endl;
}
break;
case p_down:
search.Y_index++;
path[current.X_index][current.Y_index].dir = p_left;
if (path[search.X_index][search.Y_index].isFind == 0 && (map[search.X_index][search.Y_index] == 5 || map[search.X_index][search.Y_index] == EndPoint)){
current = search;
path[search.X_index][search.Y_index].isFind = 1;
DFSpoint.push(search);
cout << "successs p_down" << '\t' << current.X_index << '\t' << current.Y_index << endl;
}
else {
cout << "faile p_down" << '\t' << current.X_index << '\t' << current.Y_index << endl;
}
break;
case p_left:
search.X_index--;
path[current.X_index][current.Y_index].dir = p_right;
if (path[search.X_index][search.Y_index].isFind == 0 && (map[search.X_index][search.Y_index] == 5 || map[search.X_index][search.Y_index] == EndPoint)) {
current = search;
path[search.X_index][search.Y_index].isFind = 1;
DFSpoint.push(search);
cout << "successs p_left" << '\t' << current.X_index << '\t' << current.Y_index << endl;
}
else {
cout << "faile p_left" << '\t' << current.X_index << '\t' << current.Y_index << endl;
}
break;
case p_right:
search.X_index++;
if (path[search.X_index][search.Y_index].isFind == 0 && (map[search.X_index][search.Y_index] == 5 || map[search.X_index][search.Y_index] == EndPoint)) {
current = search;
path[search.X_index][search.Y_index].isFind = 1;
DFSpoint.push(search);
cout << "successs p_right" << '\t' << current.X_index << '\t' << current.Y_index << endl;
}
else {
cout << "死胡同回溯" << '\t' << current.X_index << '\t' << current.Y_index << endl;
DFSpoint.pop();
current = DFSpoint.top();
}
break;
}
if (current.X_index == endx && current.Y_index == endy) {
find = true;
break;
}
if (DFSpoint.empty()) {
break;
}
}
if (find) {
while (!DFSpoint.empty()) {
Maze_generation temp = DFSpoint.top();
Drawing(temp.X_index, temp.Y_index, Path);
FlushBatchDraw();
DFSpoint.pop();
}
}
}
main.cpp
#include"Maze_generation.h"
#include"Stack.h"
#include<iostream>
using namespace std;
int main() {
srand((unsigned)time(NULL)); //随机数种子
initgraph(WIDTH, HEIGHT, EW_SHOWCONSOLE);//创建绘图窗口
BeginBatchDraw();//开始批量绘图
cleardevice();//清空显示
Maze_generation m;
m.Initialize();
m.Generation(1,1);
m.setBeginPoint(1, 1);
m.setEndPoint(BLOCK_WIDTH - 2, BLOCK_HEIGHT - 2);
m.Display();
m.findPathDFS();
system("pause");
/*Stack<int>stack;
for (int i = 0; i < 10; i++)
stack.push(i);
while (!stack.empty()) {
cout << stack.top() << endl;
stack.pop();
}
return 0;*/
}
三、总结
该项目实现难度不大,没有采用较难的算法,BFS寻路以及A*寻路都未实现,留待后续完善。