如何用C语言编写一个迷宫程序?

如何用C语言编写一个迷宫程序?,第1张

#include \x0d\x0a#include \x0d\x0a#define M 15 \x0d\x0a#define N 15 \x0d\x0astruct mark //定义迷宫内点的坐标类型 \x0d\x0a{ \x0d\x0aint x\x0d\x0aint y\x0d\x0a}\x0d\x0a\x0d\x0astruct Element //"恋"栈元素,嘿嘿。。 \x0d\x0a{ \x0d\x0aint x,y//x行,y列 \x0d\x0aint d//d下一步的方向 \x0d\x0a}\x0d\x0a\x0d\x0atypedef struct LStack //链栈 \x0d\x0a{ \x0d\x0aElement elem\x0d\x0astruct LStack *next\x0d\x0a}*PLStack\x0d\x0a\x0d\x0a/*************栈函数****************/ \x0d\x0a\x0d\x0aint InitStack(PLStack &S)//构造空栈 \x0d\x0a{ \x0d\x0aS=NULL\x0d\x0areturn 1\x0d\x0a} \x0d\x0a\x0d\x0aint StackEmpty(PLStack S)//判断栈是否为空 \x0d\x0a{ \x0d\x0aif(S==NULL) \x0d\x0areturn 1\x0d\x0aelse \x0d\x0areturn 0\x0d\x0a} \x0d\x0a\x0d\x0aint Push(PLStack &S, Element e)//压入新数据元素 \x0d\x0a{ \x0d\x0aPLStack p\x0d\x0ap=(PLStack)malloc(sizeof(LStack))\x0d\x0ap->elem=e\x0d\x0ap->next=S\x0d\x0aS=p\x0d\x0areturn 1\x0d\x0a} \x0d\x0a\x0d\x0aint Pop(PLStack &S,Element &e) //栈顶元素出栈 \x0d\x0a{ \x0d\x0aPLStack p\x0d\x0aif(!StackEmpty(S)) \x0d\x0a{ \x0d\x0ae=S->elem\x0d\x0ap=S\x0d\x0aS=S->next\x0d\x0afree(p)\x0d\x0areturn 1\x0d\x0a} \x0d\x0aelse \x0d\x0areturn 0\x0d\x0a} \x0d\x0a\x0d\x0a/***************求迷宫路径函数***********************/ \x0d\x0avoid MazePath(struct mark start,struct mark end,int maze[M][N],int diradd[4][2]) \x0d\x0a{ \x0d\x0aint i,j,dint a,b\x0d\x0aElement elem,e\x0d\x0aPLStack S1, S2\x0d\x0aInitStack(S1)\x0d\x0aInitStack(S2)\x0d\x0amaze[start.x][start.y]=2//入口点作上标记 \x0d\x0aelem.x=start.x\x0d\x0aelem.y=start.y\x0d\x0aelem.d=-1//开始为-1 \x0d\x0aPush(S1,elem)\x0d\x0awhile(!StackEmpty(S1)) //栈不为空 有路径可走 \x0d\x0a{ \x0d\x0aPop(S1,elem)\x0d\x0ai=elem.x\x0d\x0aj=elem.y\x0d\x0ad=elem.d+1//下一个方向 \x0d\x0awhile(d(%d,%d,%d)",e.x,e.y,e.d)\x0d\x0a} \x0d\x0areturn//跳出两层循环,本来用break,但发现出错,exit又会结束程序,选用return还是不错滴\x0d\x0a} \x0d\x0aif(maze[a][b]==0) //找到可以前进的非出口的点 \x0d\x0a{ \x0d\x0amaze[a][b]=2//标记走过此点 \x0d\x0aelem.x=i\x0d\x0aelem.y=j\x0d\x0aelem.d=d\x0d\x0aPush(S1,elem)//当前位置入栈 \x0d\x0ai=a//下一点转化为当前点 \x0d\x0aj=b\x0d\x0ad=-1\x0d\x0a} \x0d\x0ad++\x0d\x0a} \x0d\x0a} \x0d\x0aprintf("没有找到可以走出此迷宫的路径\n")\x0d\x0a} \x0d\x0a\x0d\x0a/*************建立迷宫*******************/ \x0d\x0avoid initmaze(int maze[M][N]) \x0d\x0a{ \x0d\x0aint i,j\x0d\x0aint m,n//迷宫行,列 [/M] \x0d\x0a\x0d\x0aprintf("请输入迷宫的行数 m=")\x0d\x0ascanf("%d",&m)\x0d\x0aprintf("请输入迷宫的列数 n=")\x0d\x0ascanf("%d",&n)\x0d\x0aprintf("\n请输入迷宫的各行各列:\n用空格隔开,0代表路,1代表墙\n",m,n)\x0d\x0afor(i=1i 回答于 2022-11-16

这里给你提供2个程序

1.用栈实现迷宫问题求解

2.老鼠走迷宫程序实例

1.用栈实现迷宫问题求解

源程序:

//base.h

#include

#include

#include

#define TRUE 1

#define FALSE 0

#define OK 1

#define ERROR 0

#define OVERFLOW -2

typedef int Status

//stack.h

#include "base.h"

#define INIT_SIZE 100 //存储空间初始分配量

#define INCREMENT 10 //存储空间分配增量

typedef struct{ //迷宫中r行c列的位置

int r

int c

}PostType

typedef struct{

int ord //当前位置在路径上的序号

PostType seat//当前坐标

int di //往下一坐标的方向

}SElemType //栈元素类型

typedef struct{

SElemType* base//栈基址,构造前销毁后为空

SElemType* top//栈顶

int stackSize //栈容量

}Stack//栈类型

Status InitStack(Stack &S){ //构造空栈s

S.base=(SElemType*)malloc(INIT_SIZE *sizeof(SElemType))

if(!S.base)

exit(OVERFLOW)//存储分配失败

S.top=S.base

S.stackSize=INIT_SIZE

return OK

}//InitStack

Status StackEmpty(Stack S){

//若s为空返回TRUE,否则返回FALSE

if(S.top==S.base)

return TRUE

return FALSE

}//StackEmpty

Status Push(Stack &S,SElemType e){

//插入元素e为新的栈顶元素

if(S.top-S.base >=S.stackSize){//栈满,加空间

S.base=(SElemType *)realloc(S.base,(S.stackSize+INCREMENT)*sizeof(SElemType))

if(!S.base)

exit(OVERFLOW) //存储分配失败

S.top=S.base+S.stackSize

S.stackSize+=INCREMENT

}

*S.top++=e

return OK

}//push

Status Pop(Stack &S,SElemType &e){//若栈不空删除栈//顶元素用e返回并返回OK,否则返回ERROR

if(S.top==S.base)

return ERROR

e=*--S.top

return OK

}//Pop

Status DestroyStack(Stack &S){//销毁栈S,

free(S.base)

S.top=S.base

return OK

}//DestroyStack

//maze.cpp

#include "stack.h"

#define MAXLEN 10//迷宫包括外墙最大行列数目

typedef struct{

int r

int c

char adr[MAXLEN][MAXLEN]//可取’ ’’*’ ’@’ ’#’

}MazeType //迷宫类型

Status InitMaze(MazeType &maze){

//初始化迷宫若成功返回TRUE,否则返回FALSE

int m,n,i,j

printf("Enter row and column numbers: ")

scanf("%d%d",&maze.r,&maze.c)//迷宫行和列数

for(i=0i<=maze.c+1i++){//迷宫行外墙

maze.adr[0][i]=’#’

maze.adr[maze.r+1][i]=’#’

}//for

for(i=0i<=maze.r+1i++){//迷宫列外墙

maze.adr[i][0]=’#’

maze.adr[i][maze.c+1]=’#’

}

for(i=1i<=maze.ri++)

for(j=1j<=maze.cj++)

maze.adr[i][j]=’ ’//初始化迷宫

printf("Enter block’s coordinate((-1,-1) to end): ")

scanf("%d%d",&m,&n)//接收障碍的坐标

while(m!=-1){

if(m>maze.r || n>maze.c)//越界

exit(ERROR)

maze.adr[m][n]=’#’//迷宫障碍用’#’标记

printf("Enter block’s coordinate((-1,-1) to end): ")

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

}//while

return OK

}//InitMaze

Status Pass(MazeType maze,PostType curpos){

//当前位置可通则返回TURE,否则返回FALSE

if(maze.adr[curpos.r][curpos.c]==’ ’)//可通

return TRUE

else

return FALSE

}//Pass

Status FootPrint(MazeType &maze,PostType curpos){

//若走过并且可通返回TRUE,否则返回FALSE

//在返回之前销毁栈S

maze.adr[curpos.r][curpos.c]=’*’//"*"表示可通

return OK

}//FootPrint

PostType NextPos(PostType &curpos,int i){

//指示并返回下一位置的坐标

PostType cpos

cpos=curpos

switch(i){//1.2.3.4分别表示东,南,西,北方向

case 1 : cpos.c+=1break

case 2 : cpos.r+=1break

case 3 : cpos.c-=1break

case 4 : cpos.r-=1break

default: exit(ERROR)

}

return cpos

}//Nextpos

Status MarkPrint(MazeType &maze,PostType curpos){

//曾走过但不是通路标记并返回OK

maze.adr[curpos.r][curpos.c]=’@’//"@"表示曾走过但不通

return OK

}//MarkPrint

Status MazePath(MazeType &maze,PostType start,PostType end){

//若迷宫maze存在从入口start到end的通道则求得一条存放在栈中

//并返回TRUE,否则返回FALSE

Stack S

PostType curpos

int curstep//当前序号,1.2.3.4分别表示东,南,西,北方向

SElemType e

InitStack(S)

curpos=start//设置"当前位置"为"入口位置"

curstep=1 //探索第一步

do{

if(Pass(maze,curpos)){//当前位置可以通过,

//即是未曾走到过的通道

FootPrint(maze,curpos)//留下足迹

e.ord=curstep

e.seat=curpos

e.di=1

Push(S,e) //加入路径

if(curpos.r==end.r&&curpos.c==end.c)

if(!DestroyStack(S))//销毁失败

exit(OVERFLOW)

else

return TRUE//到达出口

else{

curpos=NextPos(curpos,1)

//下一位置是当前位置的东邻

curstep++ //探索下一步

}//else

}//if

else{//当前位置不通

if(!StackEmpty(S)){

Pop(S,e)

while(e.di==4

&&!StackEmpty(S)){

MarkPrint(maze,e.seat)

Pop(S,e)

//留下不能通过的标记,并退一步

}//while

if(e.di <4){

e.di++//换下一个方向探索

Push(S,e)

curpos=NextPos(e.seat,e.di)//设定当前位置是该

//新方向上的相邻

}//if

}//if

}//else

}while(!StackEmpty(S))

if(!DestroyStack(S))//销毁失败

exit(OVERFLOW)

else

return FALSE

}//MazePath

void PrintMaze(MazeType &maze){

//将标记路径信息的迷宫输出到终端(包括外墙)

int i,j

printf("\nShow maze path(*---pathway):\n\n")

printf(" ")

for(i=0i<=maze.r+1i++)//打印列数名

printf("%4d",i)

printf("\n\n")

for(i=0i<=maze.r+1i++){

printf("%2d",i)//打印行名

for(j=0j<=maze.c+1j++)

printf("%4c",maze.adr[i][j])//输出迷宫//当前位置的标记

printf("\n\n")

}

}//PrintMaze

void main(){ //主函数

MazeType maze

PostType start,end

char cmd

do{

printf("-------FOUND A MAZEPATH--------\n")

if(!InitMaze(maze)){ //初始化并创建迷宫

printf("\nInitialization errors!!!\n")

exit(OVERFLOW)//初始化错误

}

do{ //输入迷宫入口坐标

printf("\nEnter entrance coordinate of the maze: ")

scanf("%d%d",&start.r,&start.c)

if(start.r>maze.r || start.c>maze.c){

printf("\nBeyond the maze!!!\n")

continue

}

}while(start.r>maze.r || start.c>maze.c)

do{ //输入迷宫出口坐标

printf("\nEnter exit coordinate of the maze: ")

scanf("%d%d",&end.r,&end.c)

if(end.r>maze.r || end.c>maze.c){

printf("\nBeyond the maze!!!\n")

continue

}

}while(end.r>maze.r || end.c>maze.c)

if(!MazePath(maze,start,end))//迷宫求解

printf("\nNo path from entrance to exit!\n")

else

PrintMaze(maze)//打印路径

printf("\nContinue?(y/n): ")

scanf("%s",&cmd)

}while(cmd==’y’ || cmd==’Y’)

}//main

2.老鼠走迷宫程序实例

#include "stdafx.h"

#include "iostream.h"

#include "string.h"

#include "stdio.h"

double dMeans=0,dWalkLen=10000//dMeans表示走出迷宫的方法,dWalkLen表示当前走出迷宫最少步数

char Maze[10][52]={

{"###################################################"},

{"% ## #### ### ### # ####"},

{"# ## # ### ### ###### ### ############ # ##"},

{"# ## ## ### ## ## # # ## # # ####"},

{"# ## ## ## ### # # ######### # # # ##"},

{"# # # # ## ########## #### ## ##"},

{"# ## ### ## ## ### #### ##### # ######### #"},

{"# # # ## ## # ## #### # # ######"},

{"#### ## ########## # ### ####@"},

{"###################################################"},

} //迷宫

int MazeFlag[10][51] //迷宫的标志:0表示未走过,i(i=1,2,3,4)表示已经走过了,i表示方向。

int MazeMin[10][51] //路径最小的迷宫的标志

void Walk(int nx,int ny)//走迷宫的函数,nx是列,ny是行

void PrintOut()//打印路径及迷宫的函数,同时比较获取路径较短的行走方法

int Judge(int nx,int ny,int i)//判断在第nx列ny行向第i个方向走是否可以,可以返回1否则返回0。

//i=1表示向右,2表示向下,3表示向左,4表示向上

/*---------------------------------------------------------------------------------------------

//行走迷宫函数: void Walk (int nx,int ny)

//功能:判断是否已经走出迷宫,如果走出则打印路径,如果没有则开始逐个方向判断是否可以行走,

// 如果都不能行走,或已经返回。则退出该位置,即将该位置的标志写为0表明未走过。

//无返回值,形参nx为当前位置的列,ny为当前位置的行。

---------------------------------------------------------------------------------------------*/

void Walk(int nx,int ny)

{

if (Maze[nx][ny]=='@')//判断是否走出迷宫,@是迷宫出口标志

PrintOut() //走出则打印出迷宫及行走路径

else //未走出迷宫

{

for (int i=1i<=4i++)//四个方向逐个行走,i=1向右 2向下 3向左 4向上

{

if (Judge(nx,ny,i)) //如果列为nx行为ny的位置向i方向是否可以行走

{

MazeFlag[nx][ny]=i//将标志位置i表明该位置向i方向可行走

if (i==1) //分散处理,根据不同的i来确定下一步的位置,以便行走。

Walk(nx,ny+1)

else if (i==2)

Walk(nx+1,ny)

else if (i==3)

Walk(nx,ny-1)

else if (i==4)

Walk(nx-1,ny)

}

}

MazeFlag[nx][ny]=0//如果4个方向都走不通,或者回朔则清空该点标志位,置为0表明未走过。

}

}

/*---------------------------------------------------------------------------------------------

//打印函数:void PrintOut()

//功能:打印第dMeans种方法的在迷宫中的行走路径,以及通过比较找出目前行走步数最少的行走方法。

//无返回值,无形参。dMeans表示当前行走方法的种类。dCount是用来计算此种方法用了多少步。

---------------------------------------------------------------------------------------------*/

void PrintOut()

{

int nx,ny

double dCount=0

dMeans++

cout<<"The "<<dMeans<<" ways is: "<<endl

for (nx=0nx<10nx++)

{

for (ny=0ny<51ny++)

{

if (Maze[nx][ny]=='#')//#表示墙

cout<<"#"

else if (MazeFlag[nx][ny]==0)//不是墙但未走过的地方用空格表示

cout<<" "

else //不是墙且走过的地方用*表示

{

cout<<"."

dCount++ //走一步总步数加1

}

}

cout<<endl

}

cout<<"This way used "<<dCount<<" steps"<<endl

if (dCount<dWalkLen)//如果此种方法的步数比以前方法中最少步数还要少,

{ //则将此种方法列为当前最少行走步数

for (nx=0nx<10nx++)

for(ny=0ny<51ny++)

MazeMin[nx][ny]=MazeFlag[nx][ny]

dWalkLen=dCount

}

}

/*--------------------------------------------------------------------------------------------

//判断函数:int Judge(int nx,int ny,int i)

//功能:判断当前位置(nx为列ny为行)向第i方向行走是否可以

//返回值int型 返回1表明可以,0表示不可以

--------------------------------------------------------------------------------------------*/

int Judge(int nx,int ny,int i)

{

if (i==1)//判断向右可否行走

{

if (ny<50&&(Maze[nx][ny+1]==' '||Maze[nx][ny+1]=='@')&&MazeFlag[nx][ny+1]==0)

return 1

else

return 0

}

else if (i==2)//判断向下可否行走

{

if (nx<9&&(Maze[nx+1][ny]==' '||Maze[nx+1][ny]=='@')&&MazeFlag[nx+1][ny]==0)

return 1

else

return 0

}

else if (i==3)//判断向左可否行走

{

if (ny>0&&(Maze[nx][ny-1]==' '||Maze[nx][ny-1]=='@')&&MazeFlag[nx][ny-1]==0)

return 1

else

return 0

}

else if (i==4)//判断向上可否行走

{

if (nx>0&&(Maze[nx-1][ny]==' '||Maze[nx-1][ny]=='@')&&MazeFlag[nx-1][ny]==0)

return 1

else

return 0

}

else

return 0

}

int main(int argc, char* argv[])

{

int nx,ny,ni,nj

cout<<"迷宫游戏: "<<endl

for (ni=0ni<10ni++)//输出迷宫形状,并且找到迷宫的入口,同时将迷宫标志初始化

{

for(nj=0nj<51nj++)

{

cout<<Maze[ni][nj]

MazeFlag[ni][nj]=0//将迷宫标志初始化为0表示未走过

if (Maze[ni][nj]=='%')

{

nx=ni//迷宫入口列坐标

ny=nj//迷宫入口行坐标

}

}

cout<<endl

}

cout<<endl<<"入口坐标:"<<endl<<"nx= "<<nx<<" "<<"ny= "<<ny<<endl

Walk(nx,ny)//调用行走迷宫函数,从入口处开始行走

cout<<endl<<"The MinLen way is: "<<endl

for (nx=0nx<10nx++)//输出最短路径

{

for (ny=0ny<51ny++)

{

if (Maze[nx][ny]=='#')

cout<<"#"

else if (MazeMin[nx][ny]==0)

cout<<" "

else

{

cout<<"."

}

}

cout<<endl

}

cout<<"This Way used "<<dWalkLen<<" steps"<<endl//输出最短路径总行走步数

return 0

}

{迷宫问题:有一个N行M列的棋盘,凡标有1的为不可通行,标有0的为可通行.要从左上角

入口处到达右下角出口处,找出一条通路或给出不可通行信息.

本题中采用堆栈实现深度优先搜索,深度优先搜索可减少搜索步数,但找到的不一定是

最短的路径,且具体路径与坐标增量的顺序有关}

PROGRAM Migong

CONST zlx:ARRAY[1..8]OF integer=(1,0,1, 1,-1, 0,-1,-1){行坐标增量}

zly:ARRAY[1..8]OF integer=(1,1,0,-1, 1,-1, 0,-1){列坐标增量}

TYPE sqtype=RECORD x,y,fx:integerEND

VAR mg:ARRAY[0..25,0..81]OF integer

sq:ARRAY[0..800]OF sqtypedone:boolean

i,j,k,m,n,x,y,fx,top:integer

BEGIN

randomize

write('请输入迷宫的高度(<=22,宽度(<=77)和障碍度(1~10):')readln(n,m,i)

IF (n>22)OR(m>77)THEN BEGIN writeln('超出范围!')exit END

writeln('图例 禁区:+ 探索过:. 通道:',chr(2)){randseed:=i}

fillchar(mg,sizeof(mg),1)done:=false

FOR i:=1 to n DO FOR j:=1 TO m DO mg[i,j]:=ord(random(20)<i)

mg[n,m]:=0sq[1].x:=1sq[1].y:=1sq[1].fx:=0{第一个点入栈}

top:=1mg[1,1]:=-1 {从入口开始探索}

WHILE (top>=1) AND NOT done DO {栈非空时探索}

BEGIN

x:=sq[top].xy:=sq[top].yfx:=sq[top].fx+1{读栈顶,取上一站的下一方向}

REPEAT {向未找过的方向探索}

i:=x+zlx[fx]j:=y+zly[fx]

IF mg[i,j]=0 THEN {i,j位置可到达且未探索过,入栈}

BEGIN

sq[top].fx:=fx {保存原结点已探索过的方向}

inc(top)sq[top].x:=isq[top].y:=jsq[top].fx:=0{新结点入栈}

{write(top:8)}

if top=48 then

write

mg[i,j]:=-1{标记新结点i,j已到过}

IF (i=n)AND(j=m) THEN BEGIN done:=truebreak END {到出口时退出循环}

ELSE BEGIN x:=iy:=jfx:=1 END {否则从新结点开始探索}

END

ELSE fx:=fx+1

UNTIL fx>8

IF NOT done THEN dec(top) {找遍8个方向且不通时才从栈中删除}

END

IF done THEN {找到通道}

BEGIN

dec(mg[1,1])k:=1{计数器}

REPEAT

i:=1inc(k)dec(mg[sq[top].x,sq[top].y]){计数,在通道上作标记}

WHILE (abs(sq[i].x-sq[top].x)>1)OR(abs(sq[i].y-sq[top].y)>1) DO inc(i)

top:=i {找到栈中最前的可达终点的点i,并作为下一次的终点}

UNTIL top=1

END

FOR i:=1 to n DO {输出迷宫情况}

BEGIN

IF i=1 THEN write('=>') ELSE write(' ')

FOR j:=1 TO m DO

BEGIN

CASE mg[i,j] OF

1:write('+')0:write(' ')-1:write('.')-2:write(chr(2))

END

IF m<38 THEN write(' ')

END

IF i<n THEN writeln

ELSE IF done THEN BEGIN writeln('=>')writeln('Steps=',k) END

ELSE BEGIN writelnwriteln('迷宫无出路!')END

END

END.


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/11665248.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-17
下一篇2023-05-17

发表评论

登录后才能评论

评论列表(0条)

    保存