迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构

这篇具有很好参考价值的文章主要介绍了迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

该程序是一项 “迷宫求解” 类问题,主要功能包含:

        ①25 X 25迷宫的随机生成

        ②迷宫求解的动画演示(DFS)

完整代码附最后 : )

功能演示:

迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构

界面展示:

迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构

 迷宫展示:

迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构

结果展示:

迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构

 


首先是随机迷宫部分:

大概思路就是先初始化一个矩阵,外圈为“通路”,内层为“墙体”。

1.定义vector容器,用于存放墙体坐标,先将起点装入容器

2.在容器中随机选取一个墙体,满足“四周无通路或只有一个通路”条件时,将墙体拆除(改为通路)并从容器中移除,随后将该墙体四周的墙体装入容器

流程图演示:

在此使用较小矩阵用于演示

迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构

 代码部分:

void create_mg()//随机生成迷宫
{
	//初始化迷宫:内部为墙体;外围为通路,当做屏障
	for(int i=0; i<Y; i++)
	{
		mg[0][i]=0;
		mg[X-1][i]=0;
	}
	for(int i=1; i<X-1; i++)
		for(int j=0; j<Y; j++)
		{
			if(j==0||j==Y-1)
				mg[i][j]=0;
			else
				mg[i][j]=1;
		}

	//分别对应着上下左右方向
	int dRow[] = {1, 0, -1, 0};
	int dCol[] = {0, -1, 0, 1};
	//用于存储墙体坐标
	vector<int> QX,QY;
	QX.push_back(start_x);//从起点开始
	QY.push_back(start_y);
	while(QX.size())//拆墙
	{
		//根据当前时间,生成一个随机数种子
		srand((unsigned int)(time(NULL)));
		int index=rand()%(QX.size());//随机生成一个坐标,选取一堵墙
		int x=QX[index];
		int y=QY[index];
		int flag=0;//记录该墙四周通路个数
		int r,c;
		for(int i=0; i<4; i++)
		{
			r=x+dRow[i];
			c=y+dCol[i];
			if(mg[r][c]==0)
				flag++;
		}

		if(flag<=1)//当该墙体四周通路有一条或没有时,则该墙改为道路
		{
			mg[x][y]=0;
			for(int i=0; i<4; i++)
			{
				r=x+dRow[i];
				c=y+dCol[i];
				if(mg[r][c]==1)//将该墙四周的墙加入队列
				{
					QX.push_back(r);
					QY.push_back(c);
				}
			}
		}

		//将当前墙移除队列
		QX.erase(QX.begin()+index);
		QY.erase(QY.begin()+index);
	}
}

其次是迷宫求解部分:

为了方便理解,我设计了box结构体,用于表示路径的坐标与方向

struct box
{
	int x,y;//坐标
	int dir;//方向:右1 下2 左3 上4
};

迷宫求解问题,路径部分当然要用栈来存放啦,方便回溯

思路很简单:

        按照“右下左上”顺时针方向进行摸索,能走通的就走,死路就回溯,即将该点路径出栈,并将已走过的路线做上标记。回溯到起点即代表迷宫无解,到终点就是求解完成。

但为了完成动画效果还是需要下亿点功夫:

        ①每走一步需重新打印一次迷宫,这就少不了清屏功能,使用system("cls")虽然方便,但会出现较为严重的闪屏现象,做过动画演示程序的应该体验过,虽然不影响功能,但视觉体验很糟糕。我也是通过网上学习两个函数来代替system("cls"),解决闪屏。

void gotoxy(int x,int y)//将光标移动到(x,y)位置
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);    //获取标准输出设备句柄
	COORD pos= {x,y};     //坐标位置
	SetConsoleCursorPosition(handle,pos);   //设置控制台光标位置
}
void HideCursor()//隐藏光标
{
	CONSOLE_CURSOR_INFO cursor_info= {1,0}; //0表示隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}

        ②为了有更好的视觉体验,我用了不同颜色区分墙体,路线与已走路线。即打印路线前调用变色函数,打印后恢复原色

HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);//颜色

void cout_green()//绿色
{
	SetConsoleTextAttribute(hout, 2);
}

void cout_red()//红色
{
	SetConsoleTextAttribute(hout, 4);
}

void recover()//白色
{
	SetConsoleTextAttribute(hout, 1|2|4);
}

代码部分:

void play_mg()
{
	//分别对应着上下左右方向
	int dRow[] = {0, 1, 0, -1};
	int dCol[] = {1, 0, -1, 0};

	box start;//起始位置
	start.x=start_x;
	start.y=start_y;
	path.push(start);
	while(!path.empty())
	{
		box temp;
		bool flag=false;//判断该坐标是否有通路
		int x = path.top().x;
		int y = path.top().y;
		mg[x][y]=1;//该坐标已经过,设置为墙
		for(int i=0; i<4; i++) //向四个位置进行试探,方向:右1 下2 左3 上4
		{
			int r=x+dRow[i];
			int c=y+dCol[i];
			if(mg[r][c]==0)
			{
				temp.x=r;
				temp.y=c;
				temp.dir=i+1;
				path.push(temp);
				flag=true;
				break;
			}
		}
		if(x==X-3&&y==Y-3)//到达终点
			break;
		mglx[x][y]=temp.dir+1;//该坐标已经过,右2 下3 左4 上5
		if(!flag)//若该坐标点无通路,则回溯
		{
			box t=path.top();
			mglx[t.x][t.y]=6;//回溯后要把该坐标设为不可走路线
			path.pop();
		}
		HideCursor();
		gotoxy(0,0);
		Sleep(speed);//设置速度
		show_mg();
	}
}

其余部分代码就是一些简单的界面设计与细节处理,很好理解

完整代码附上:文章来源地址https://www.toymoban.com/news/detail-470749.html

#include<iostream>
#include<stack>//栈 
#include<vector>//容器 
#include<time.h>//获取当前时间 
#include <Windows.h>//颜色改变,时停 
#include<stdlib.h>//清屏 

using namespace std;

#define X 27//迷宫大小 
#define Y 27
#define start_x 2//起点
#define start_y 2
#define speed 30//速度 

struct box
{
	int x,y;//坐标
	int dir;//方向:右1 下2 左3 上4
};

int mg[X][Y];//初始迷宫
int mglx[X][Y];//展示迷宫路线,因原迷宫会被打乱

stack<box> path;//路线,包含坐标与方向信息

HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);//颜色

void create_mg();//随机生成迷宫
void copy_mg();//复制迷宫
void play_mg();//完成迷宫路线求解
void show_path();//坐标路线展示 
void show_mg();//迷宫路线展示
void cout_green();//打印绿色
void cout_red();//打印红色
void recover();//恢复白色

//清屏函数,代替system("cls"),防止闪烁,网上学习
void gotoxy(int x,int y);//将光标移动到(x,y)位置
void HideCursor();//隐藏光标



int main()
{
	while(true)
	{
		system("cls");
		char choice;
		cout<<endl<<endl<<"*****\t欢迎来到迷宫求解问题\t*******"<<endl<<endl<<endl;
		cout<<"\t[1] 随机生成迷宫."<<endl;
		cout<<"\t[2] 退出游戏."<<endl<<endl;
		cout<<"\t\t随机生成 "<<X-2<<" X "<<Y-2<<" 的迷宫"<<endl;
		cout<<"\t\t\t\t——QLU"<<endl;
		cout<<"****************************************"<<endl<<endl;
		cout<<"请输入你的选择:";
		cin>>choice;
		if(choice=='1')
		{
			system("cls");
			while(true)
			{
				create_mg();
				if(mg[X-3][Y-3]==0)//若终点是一堵墙,则重新生成迷宫
					break;
			}
			copy_mg();
			show_mg();
			system("pause");
			play_mg();
			show_path();
		}
		else if(choice=='2')
			return 0;
		else
			cout<<"请输入正确的选择!"<<endl;
		system("pause");
	}
}

void create_mg()//随机生成迷宫
{
	//初始化迷宫:内部为墙体;外围为通路,当做屏障
	for(int i=0; i<Y; i++)
	{
		mg[0][i]=0;
		mg[X-1][i]=0;
	}
	for(int i=1; i<X-1; i++)
		for(int j=0; j<Y; j++)
		{
			if(j==0||j==Y-1)
				mg[i][j]=0;
			else
				mg[i][j]=1;
		}

	//分别对应着上下左右方向
	int dRow[] = {1, 0, -1, 0};
	int dCol[] = {0, -1, 0, 1};
	//用于存储墙体坐标
	vector<int> QX,QY;
	QX.push_back(start_x);//从起点开始
	QY.push_back(start_y);
	while(QX.size())//拆墙
	{
		//根据当前时间,生成一个随机数种子
		srand((unsigned int)(time(NULL)));
		int index=rand()%(QX.size());//随机生成一个坐标,选取一堵墙
		int x=QX[index];
		int y=QY[index];
		int flag=0;//记录该墙四周通路个数
		int r,c;
		for(int i=0; i<4; i++)
		{
			r=x+dRow[i];
			c=y+dCol[i];
			if(mg[r][c]==0)
				flag++;
		}

		if(flag<=1)//当该墙体四周通路有一条或没有时,则该墙改为道路
		{
			mg[x][y]=0;
			for(int i=0; i<4; i++)
			{
				r=x+dRow[i];
				c=y+dCol[i];
				if(mg[r][c]==1)//将该墙四周的墙加入队列
				{
					QX.push_back(r);
					QY.push_back(c);
				}
			}
		}

		//将当前墙移除队列
		QX.erase(QX.begin()+index);
		QY.erase(QY.begin()+index);
	}
}

void play_mg()
{
	//分别对应着上下左右方向
	int dRow[] = {0, 1, 0, -1};
	int dCol[] = {1, 0, -1, 0};

	box start;//起始位置
	start.x=start_x;
	start.y=start_y;
	path.push(start);
	while(!path.empty())
	{
		box temp;
		bool flag=false;//判断该坐标是否有通路
		int x = path.top().x;
		int y = path.top().y;
		mg[x][y]=1;//该坐标已经过,设置为墙
		for(int i=0; i<4; i++) //向四个位置进行试探,方向:右1 下2 左3 上4
		{
			int r=x+dRow[i];
			int c=y+dCol[i];
			if(mg[r][c]==0)
			{
				temp.x=r;
				temp.y=c;
				temp.dir=i+1;
				path.push(temp);
				flag=true;
				break;
			}
		}
		if(x==X-3&&y==Y-3)//到达终点
			break;
		mglx[x][y]=temp.dir+1;//该坐标已经过,右2 下3 左4 上5
		if(!flag)//若该坐标点无通路,则回溯
		{
			box t=path.top();
			mglx[t.x][t.y]=6;//回溯后要把该坐标设为不可走路线
			path.pop();
		}
		HideCursor();
		gotoxy(0,0);
		Sleep(speed);//设置速度
		show_mg();
	}
}

void show_path()//展示坐标路线
{
	if(path.empty())
	{
		cout<<"此迷宫无解"<<endl;
		return;
	}
	box temp[100];
	int length=0;
	while(!path.empty())
	{
		temp[length]=path.top();
		length++;
		path.pop();
	}
	cout<<"方向路线:"<<endl;
	cout<<"起点=>";
	for(int i=length-1; i>=0; i--)
	{
		if(temp[i].dir==1)
			cout<<"右=>";
		else if(temp[i].dir==2)
			cout<<"下=>";
		else if(temp[i].dir==3)
			cout<<"左=>";
		else if(temp[i].dir==4)
			cout<<"上=>";
	}
	cout<<"终点"<<endl<<endl;
	cout<<"坐标路线:"<<endl;
	cout<<"起点=>";
	for(int i=length-1; i>=0; i--)
	{
		cout<<"("<<temp[i].x-1<<","<<temp[i].y-1<<")=>";
	}
	cout<<"终点"<<endl;
}

void show_mg()//展示迷宫路线
{
	for(int i=0; i<X; i++)
	{
		for(int j=0; j<Y; j++)
		{
			//墙■路  右2→ 下3↓ 左4← 上5↑ 错×
			if(i==start_x&&j==start_y)
				cout<<"☆";
			else if(i==X-3&&j==Y-3)
				cout<<"★";
			else if(mglx[i][j]==1)
				cout<<"■";
			else if(mglx[i][j]==2)
			{
				cout_green();
				cout<<"→";
				recover();
			}
			else if(mglx[i][j]==3)
			{
				cout_green();
				cout<<"↓";
				recover();
			}
			else if(mglx[i][j]==4)
			{
				cout_green();
				cout<<"←";
				recover();
			}
			else if(mglx[i][j]==5)
			{
				cout_green();
				cout<<"↑";
				recover();
			}
			else if(mglx[i][j]==6)
			{
				cout_red();
				cout<<"×";
				recover();
			}
			else
				cout<<"  ";
		}
		cout<<endl;
	}
}

void copy_mg()//复制迷宫
{
	for(int i=0; i<X; i++)
	{
		for(int j=0; j<Y; j++)
		{
			mglx[i][j]=mg[i][j];
		}
	}
}

void cout_green()//绿色
{
	SetConsoleTextAttribute(hout, 2);
}

void cout_red()//红色
{
	SetConsoleTextAttribute(hout, 4);
}

void recover()//白色
{
	SetConsoleTextAttribute(hout, 1|2|4);
}

void gotoxy(int x,int y)//将光标移动到(x,y)位置
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);    //获取标准输出设备句柄
	COORD pos= {x,y};     //坐标位置
	SetConsoleCursorPosition(handle,pos);   //设置控制台光标位置
}
void HideCursor()//隐藏光标
{
	CONSOLE_CURSOR_INFO cursor_info= {1,0}; //0表示隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}

到了这里,关于迷宫求解(包含随机迷宫、求解动画演示)——C语言 数据结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用栈求解迷宫问题的所有路径及最短路径程序(纯c语言)

    参考了这个博客 学校作业,在各种地方搜了半天,看别人的要么就是有点错,要么就是很复杂用了不少我不知道的库,还要么就是只求了一条路径,还要么就是用了c++没学过。 写了半天,写出了一个应该是比较简单的方法,应该是还能优化,不过作业能跑就行,懒得搞了。

    2023年04月12日
    浏览(40)
  • 【数据结构】迷宫问题DFS非递归(c语言实现)

    本来之前写过一个推箱子,就想着写个迷宫游戏,因为想着推箱子游戏里面也有墙,也有玩家的移动,比推箱子简单的是还不用判断前面是否有箱子的情况,但是自己写的迷宫游戏如果自己随机生成的迷宫地图的话,不一定会有通路,他要学一个什么随机迷宫的生成,刚看完

    2024年02月08日
    浏览(39)
  • C数据结构与算法——队列 应用(C语言纯享版 迷宫)

    实验任务 (1) 掌握顺序循环队列及其C语言的表示; (2) 掌握入队、出队等基本算法的实现; (3) 掌握顺序循环队列的基本应用(求解迷宫通路)。 实验内容 使用C语言实现顺序循环队列的类型定义与算法函数; 编写main()函数并根据需要修改、补充相关的类型定义与函数,以实

    2024年02月15日
    浏览(56)
  • 数据结构与算法大作业:走迷宫程序(C语言,DFS)(代码以及思路)

    好家伙,写大作业,本篇为代码的思路讲解   问题描述: 以一个 m * n 的长方阵表示迷宫, 0和1分别表示迷宫的通路和障碍。 设计一个程序, 对任意设定的迷宫, 求出一条从入口到出口的通路, 或得出没有通路的结论。 基本要求: (1) 实现一个以链表做存储的栈类型,

    2024年02月03日
    浏览(43)
  • DFS求解迷宫问题

       下面来具体分析一下算法的具体实现 首先要进行搜索,对搜索方向的顺序规定为:右--下--左--上   按照搜索顺序从起点开始搜索,在搜索的过程中将已经搜索过的位置设为已访问,这样我们就可以得到如下图所示的一条路线。 在到达终点后要进行回溯,利用 回溯 找到其

    2024年02月11日
    浏览(43)
  • 星辰秘典:解开Python项目的神秘面纱——迷宫之星(迷宫探索与求解)

    ✨博主: 命运之光 🌸专栏: Python星辰秘典 🐳专栏: web开发(html css js) ❤️专栏: Java经典程序设计 ☀️博主的其他文章: 点击进入博主的主页 前言:你好,欢迎来到我的博客。我是一个热爱编程的人,特别喜欢用Python这门语言来创造一些有趣的图形项目。在这篇博客

    2024年02月11日
    浏览(47)
  • A*算法求解迷宫寻路问题实验

    一、实验目标: 熟悉和掌握A*算法实现迷宫寻路功能,要求掌握启发式函数的编写以及各类启发式函数效果的比较。 二、实验内容与完成情况: 寻路问题常见于各类游戏中角色寻路、三维虚拟场景中运动目标的路径规划、机器人寻路等多个应用领域。迷宫寻路问题是在以方

    2024年02月04日
    浏览(39)
  • c++小游戏:随机迷宫

    实现方法: c++游戏小技巧6:rand()+随机迷宫(3写法:BFS,DFS,并查集)_L(\\\'ω\\\')┘脏脏包└(\\\'ω\\\')」的博客-CSDN博客 总而言之,把三种代码生成编到了一起,加上拿手的主页面及优化 1.0版本就做好了 (注意,关于普通模式,请自备心梗的药)  1.0版本支持: 简单模式:DFS生成,岔路小,看

    2024年02月16日
    浏览(43)
  • 【数据结构和算法初阶(C语言)】复杂链表(随机指针,随机链表的复制)题目详解+链表顺序表结尾

    目录  1.随机链表的复制 1.2题目描述  1.3题目分析 1.4解题: 2.顺序表和链表对比 2.1cpu高速缓存利用率 3.结语 一个长度为  n  的链表,每个节点包含一个额外增加的随机指针  random   该指针可以指向链表中的任何节点或空节点。        构造这个链表的  深拷贝 。 深拷贝

    2024年03月10日
    浏览(87)
  • A*算法求解迷宫问题(算法讲解与证明、python实现与可视化)

    目录 一、引入 二、具体细节 1、BFS(Breadth First Search) 2、Dijkstra(Uniform Cost Search) 3、启发式(Heuristic search) 4、A*算法 4.1 算法细节 4.2 A与A*算法 4.3 A*算法证明 4.4 算法过程 三、具体实现 1、实验要求 2、代码实现 四、源代码        当我开始学习该算法时,网上已经有了很

    2023年04月08日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包