c语言迷宫如何自动生成,[ C语言 ] 迷宫 迷宫生成器 [ 递归与搜索 ]

【原创】转载请注明出处 【浙江大学 程序设计专题】

【地图求解器】

本题目要求输入一个迷宫地图,输出从起点到终点的路线。

基本思路是从起点(Sx,Sy)每次枚举该格子上下左右四个方向,直到走到终点(Tx,Ty)。

方法一:如果使用递归方法,则可以使用深度优先搜索算法,但此方法不能保证答案步数最优。

方法二: 如果要求答案步数最少,则使用广度优先搜索算法,但此方法通常不使用递归函数实现。

DFS版代码

#include

#include

/*Header which contains the output function*/

#include "prnt_route.h"

int n,m;

int visited[][];

struct PII from[][];

/*Save the route.*/

const int dx[]={-,,,},dy[]={,,,-};

char Map[][];

int Dfs(const int Sx,const int Sy, const int Tx,const int Ty)

{

if(Sx==Tx && Sy==Ty) return ;

int i;

for(i=;i

{

int tx=Sx+dx[i],ty=Sy+dy[i];/*tx,ty refers to the next grid.*/

if(tx>= && ty>= && tx

!visited[tx][ty] && Map[tx][ty]!='#')

/*check if (tx,ty) is reachable*/

{

visited[tx][ty]=;

if(Dfs(tx,ty,Tx,Ty))

{

/*Route is found.*/

from[tx][ty]=make_pair(Sx,Sy);

return ;

}

}

}

return ;

}

int main()

{

freopen("in.txt","r",stdin);

freopen("out.txt","w",stdout);

int i,j,Sx,Sy,Tx,Ty;

scanf("%d%d",&n,&m);

Sx=Sy=,Tx=n-,Ty=m-;

for(i=;i

/*Find the starting and ending points.*/

for(i=;i

for(j=;j

if(Map[i][j]=='S') Sx=i,Sy=j;

else if(Map[i][j]=='T') Tx=i,Ty=j;

/*Dfs will return 1 if a solution is found, 0 otherwise.*/

if(Dfs(Sx,Sy,Tx,Ty)) Print_Ans(Sx,Sy,Tx,Ty);

else printf("No Solution.\n");

return ;

}

BFS版代码

#include

#include

#include

/*Header contains the outout function*/

#include "prnt_route.h"

int n,m;

int visited[][];

struct PII from[][];

/*Save the route*/

char Map[][];

int Bfs(const int Sx,const int Sy, const int Tx,const int Ty)

{

struct PII Q[(n+)*(m+)];/*Queue for Bfs*/

int front=,back=;/*head and tail pointer of the queue*/

memset(visited,,sizeof(visited));

memset(from,,sizeof(from));

Q[back++]=make_pair(Sx,Sy);/*push the starting point*/

visited[Sx][Sy]=;

while(front!=back && !visited[Tx][Ty])

{

struct PII t=Q[front++];/*Pop out*/

/*Search four directions*/

if(t.x> && !visited[t.x-][t.y] && Map[t.x-][t.y]!='#')/*up*/

{

Q[back++]=make_pair(t.x-,t.y);/*push*/

visited[t.x-][t.y]=;

from[t.x-][t.y]=make_pair(t.x,t.y);

}

if(t.x

{

Q[back++]=make_pair(t.x+,t.y);/*push*/

visited[t.x+][t.y]=;

from[t.x+][t.y]=make_pair(t.x,t.y);

}

if(t.y> && !visited[t.x][t.y-] && Map[t.x][t.y-]!='#')/*left*/

{

Q[back++]=make_pair(t.x,t.y-);/*push*/

visited[t.x][t.y-]=;

from[t.x][t.y-]=make_pair(t.x,t.y);

}

if(t.y

{

Q[back++]=make_pair(t.x,t.y+);/*push*/

visited[t.x][t.y+]=;

from[t.x][t.y+]=make_pair(t.x,t.y);

}

}

return visited[Tx][Ty];

}

int main()

{

freopen("in.txt","r",stdin);

freopen("out.txt","w",stdout);

int i,j,Sx,Sy,Tx,Ty;

scanf("%d%d",&n,&m);

Sx=Sy=,Tx=n-,Ty=m-;

for(i=;i

/*Find the starting and ending points*/

for(i=;i

for(j=;j

if(Map[i][j]=='S') Sx=i,Sy=j;

else if(Map[i][j]=='T') Tx=i,Ty=j;

/*Bfs will return 1 if route is found.*/

if(Bfs(Sx,Sy,Tx,Ty)) Print_Ans(Sx,Sy,Tx,Ty);

else printf("No Solution.\n");

return ;

}

print_route.h(两篇代码公用)

/*Output function*/

#include

struct PII { int x,y; };/*coordinate container*/

struct PII make_pair(const int x,const int y)

{ struct PII t; t.x=x,t.y=y; return t; }

extern int n,m;

extern int visited[][];

extern struct PII from[][];

extern char Map[][];

void Print_Ans(const int Sx,const int Sy,const int Tx,const int Ty)

{

int x=Tx,y=Ty,dir=,td,i,j,tempx,tempy;

/*'dir' is the current direction, while 'td' is the last direcion.*/

while(x!=Sx || y!=Sy)

{

/*judge the direction*/

if(from[x][y].y==y && from[x][y].x==x+) Map[x][y]='^',td=;

if(from[x][y].y==y && from[x][y].x==x-) Map[x][y]='V',td=;

if(from[x][y].x==x && from[x][y].y==y+) Map[x][y]='

if(from[x][y].x==x && from[x][y].y==y-) Map[x][y]='>',td=;

/*decide which conner character should be output.*/

if(dir== && td==) Map[x][y]='}';

if(dir== && td==) Map[x][y]='}';

if(dir== && td==) Map[x][y]='{';

if(dir== && td==) Map[x][y]='{';

if(dir== && td==) Map[x][y]=']';

if(dir== && td==) Map[x][y]=']';

if(dir== && td==) Map[x][y]='[';

if(dir== && td==) Map[x][y]='[';

tempx=x,tempy=y; dir=td;

x=from[tempx][tempy].x;

y=from[tempx][tempy].y;

}

Map[Sx][Sy]='S';

Map[Tx][Ty]='T';

for(i=;i

{

for(j=;j

{

/*output with special chars.*/

if(Map[i][j]=='#') printf("█");

else if(Map[i][j]=='.') printf(" ");

else if(Map[i][j]=='^') printf("↑");

else if(Map[i][j]=='V') printf("↓");

else if(Map[i][j]=='

else if(Map[i][j]=='>') printf("→");

else if(Map[i][j]=='+') printf("╋");

else if(Map[i][j]=='[') printf("┏");

else if(Map[i][j]==']') printf("┓");

else if(Map[i][j]=='{') printf("┗");

else if(Map[i][j]=='}') printf("┛");

else printf("☆");

}

printf("\n");

}

return ;

}

标准ascii字符版print_route.h

#include

struct PII { int x,y; };

struct PII make_pair(const int x,const int y)

{ struct PII t; t.x=x,t.y=y; return t; }

extern int n,m;

extern int visited[][];

extern struct PII from[][];

extern char Map[][];

void Print_Ans(const int Sx,const int Sy,const int Tx,const int Ty)

{

int x=Tx,y=Ty,dir=,td,i,tempx,tempy;

while(x!=Sx || y!=Sy)

{

if(from[x][y].y==y && from[x][y].x==x+) Map[x][y]='|',td=;

if(from[x][y].y==y && from[x][y].x==x-) Map[x][y]='|',td=;

if(from[x][y].x==x && from[x][y].y==y+) Map[x][y]='-',td=;

if(from[x][y].x==x && from[x][y].y==y-) Map[x][y]='-',td=;

if(dir== && td==) Map[x][y]='+';

if(dir== && td==) Map[x][y]='+';

if(dir== && td==) Map[x][y]='+';

if(dir== && td==) Map[x][y]='+';

if(dir== && td==) Map[x][y]='+';

if(dir== && td==) Map[x][y]='+';

if(dir== && td==) Map[x][y]='+';

if(dir== && td==) Map[x][y]='+';

tempx=x,tempy=y; dir=td;

x=from[tempx][tempy].x;

y=from[tempx][tempy].y;

}

Map[Sx][Sy]='S';

Map[Tx][Ty]='T';

for(i=;i

return ;

}

【地图生成器】

方法,使用DFS,每次随机一个方向进行扩展。但这样可能导致一条路径过长,岔路过短。

所以加入三个参数:

1.搜索过程中有一定几率保持上一次的方向,称为RATE_KEEP_DIR

2.搜索过程中有一定几率停止当前道路的搜索,直接return,这个参数称为RETURN_RATE

3.每条链有一个最大长度,称为TWIST_RATE

通过修改这三个参数,可以改变地图的性态。

生成器代码使用C++,编译需要加-std=c++11参数,代码如下

//Compile with -std=c++11

#include

using namespace std;

const int RATE_KEEP_DIR=;

const int TWIST_RATE=;

const int RETURN_RATE=;

int n,m,Sx,Sy,Tx,Ty,Max;

char Map[][];

typedef pair PII;

const int dx[]={-,,,},dy[]={,,,-};

const int Dx[]={-,,,},Dy[]={,,,-};

mt19937 RND(time());

//Check if (x,y) has a neighbour can go.

bool Check(const int x,const int y)

{

for(int i=;i

{

int nx=x+dx[i],ny=y+dy[i],Nx=x+Dx[i],Ny=y+Dy[i];

if(Nx>= && Nx= && Ny

} return false;

}

void Dfs(const int x,const int y,const int depth,int Lim,const int last_dir)

{

if(depth>Max)Tx=x,Ty=y,Max=depth;//find a longest route

if(depth>Lim) return ;

Map[x][y]='.';

while(Check(x,y))

{

int t=RND()%;//random direction

if(RND()%

int nx=x+dx[t],ny=y+dy[t],Nx=x+Dx[t],Ny=y+Dy[t];

if(nx< || nx>n- || ny< || ny>m- || Map[nx][ny]!='#')continue;

if(Nx< || Nx>n- || Ny< || Ny>m- || Map[Nx][Ny]!='#')continue;

if(Nx== || Nx==n- || Ny== || Ny==m-) { Map[nx][ny]='.'; continue; }

Map[nx][ny]='.'; Map[Nx][Ny]='.';

Dfs(Nx,Ny,depth+,Lim,t);

//chance of returning directly, without expanding, for more branch roads

if((int)(RND()%)

Lim=depth+max(min(n,m)/TWIST_RATE,);

}

return ;

}

int main()

{

freopen("in.txt","w",stdout);

scanf("%d%d",&n,&m);

printf("%d %d\n",n,m);

for(int i=;i

Sx=Sy=;

// the length limit of each branch road.

Dfs(Sx,Sy,,max(min(n,m)/TWIST_RATE,),);

//set starting and ending points.

Map[Sx][Sy]='S';

Map[Tx][Ty]='T';

for(int i=;i

return ;

}

以下C++代码可以将生成器生成的地图转化为全角符号,便于查看

#include

int n,m;

char Map[][];

using namespace std;

int main()

{

freopen("in.txt","r",stdin);

freopen("view.txt","w",stdout);

scanf("%d%d",&n,&m);

for(int i=;i

scanf("%s",Map[i]);

for(int i=;i

{

for(int j=;j

{

if(Map[i][j]=='#') printf("█");

else if(Map[i][j]=='.') printf(" ");

else printf("☆");

}

printf("\n");

}

return ;

}

AI-随机迷宫&amp&semi;迷宫求解

本文记录了,人工智能中简单的搜索策略中的路径搜索策略中的A*算法,来实现迷宫寻路的问题.(这只是一次本人的课外作业) 完整的程序源码已经发送到我的Git.这里只记录了我的思路和感想以及收获. 产生随机 ...

python 递归深度优先搜索与广度优先搜索算法模拟实现

一.递归原理小案例分析 (1)# 概述 递归:即一个函数调用了自身,即实现了递归 凡是循环能做到的事,递归一般都能做到! (2)# 写递归的过程 1.写出临界条件2.找出这一次和上一次关系3.假设当前 ...

&lbrack;迷宫中的算法实践&rsqb;迷宫生成算法&mdash&semi;&mdash&semi;递归分割算法

Recursive division method        Mazes can be created with recursive division, an algorithm which wo ...

ytu 1980&colon;小鼠迷宫问题(DFS 深度优先搜索)

小鼠迷宫问题 Time Limit: 2 Sec  Memory Limit: 64 MB Submit: 1  Solved: 1 [Submit][Status][Web Board] Desc ...

&lbrack;Swust OJ 409&rsqb;--小鼠迷宫问题&lpar;BFS&plus;记忆化搜索&rpar;

题目链接:http://acm.swust.edu.cn/problem/409/ Time limit(ms): 1000 Memory limit(kb): 65535   Description ...

poj3984《迷宫问题》暑假集训-搜索进阶

K - 迷宫问题 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit ...

BZOJ2246 &lbrack;SDOI2011&rsqb;迷宫探险 【记忆化搜索dp &plus; 概率】

题目 输入格式 输出格式 仅包含一个数字,表示在执行最优策略时,人物活着走出迷宫的概率.四舍五入保留3位小数. 输入样例 4 3 3 2 .$. A#B A#C @@@ 143 37 335 85 9 ...

POJ 3984:迷宫问题 bfs&plus;递归输出路径

迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11844   Accepted: 7094 Description ...

&lbrack;Swust OJ 191&rsqb;--迷宫逃离(打表搜索)

题目链接:http://acm.swust.edu.cn/problem/191/ Time limit(ms): 1000 Memory limit(kb): 65535   江鸟突然想到了一个 ...

随机推荐

20145212 实验四《Andoid开发基础》

20145212 实验四 实验内容 安装Android Studio 运行安卓AVD模拟器 使用Android运行出模拟手机并显示自己的学号 实验过程 一.安装An ...

手机访问pc网站自动跳转手机端网站代码

java中的日志组件-log4j

1.为什么使用日志组件 Log4J是Apache的一个开放源代码项目,它是一个日志操作包,通过使用Log4J,可以指定日志信息输出的目的地,如控制台.文件.CUI组件.NT的事件记录器:还可以控制每一 ...

自定义一个WPF的PathButton

一.背景 做项目时总是少不了Button,但是普通的Button大家都不喜欢用,总是想要自定义的Button,正好项目中用到不要边框的Button,并且是形状也是根据功能不同而变化的,并且窗口程序是会 ...

django-rest-framework 快速开始

搭建项目 # Set up a new project django-admin.py startproject tutorial cd tutorial # Create a virtualenv ...

SQL Server系统数据库备份最佳实践

原文:SQL Server系统数据库备份最佳实践 首先了解主要的系统数据库: 系统数据库 master 包含登录信息和其他数据库的核心信息 msdb 存储作业.操作员.警报.备份还原历史.数据库邮件信 ...

【小白学C&num;】浅谈&period;NET中的IL代码

一.前言 前几天群里有位水友提问:”C#中,当一个方法所传入的参数是一个静态字段的时候,程序是直接到静态字段拿数据还是从复制的函数栈中拿数据“.其实很明显,这和方法参数的传递方式有关,如果是引用传递的 ...

BaseServlet的编写

在BaseServlet之前,需要提及工厂factory去管理dao以及service,以及页面转发或重定向的管理 1.创建一个工厂类,以及一个资源文件,资源文件中以键值对的形式去存储key,以及对应 ...

mem 0908

taglib http://blog.csdn.net/zyujie/article/details/8735730 dozer: Dozer可以在JavaBean到JavaBean之间进行递归数据复 ...

java的同步实现

在java编程中,经常需要用到同步,而同步的实现使用最多的就是synchronized关键字了. synchronized关键字涉及到“锁”的概念,首先先了解一下相关锁的知识. java的内置锁:每个 ...

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值