c语言程序设计的迷宫

c语言程序设计的迷宫,第1张

这个可行的

/*4.3.3源程序*/

#include <graphics.h>

#include <stdlib.h>

#include <stdio.h>

#include <conio.h>

#include <dos.h>

#define N 20/*迷宫的大小,可改变*/

int oldmap[N][N]/*递归用的数组,用全局变量节约时间*/

int yes=0/*yes是判断是否找到路的标志,1找到,0没找到*/

int way[100][2],wayn=0/*way数组是显示路线用的,wayn是统计走了几个格子*/

void Init(void)/*图形初始化*/

void Close(void)/*图形关闭*/

void DrawPeople(int *x,int *y,int n)/*画人工探索物图*/

void PeopleFind(int (*x)[N])/*人工探索*/

void WayCopy(int (*x)[N],int (*y)[N])/*为了8个方向的递归,把旧迷宫图拷贝给新数组*/

int FindWay(int (*x)[N],int i,int j)/*自动探索函数*/

void MapRand(int (*x)[N])/*随机生成迷宫函数*/

void PrMap(int (*x)[N])/*输出迷宫图函数*/

void Result(void)/*输出结果处理*/

void Find(void)/*成功处理*/

void NotFind(void)/*失败处理*/

void main(void)/*主函数*/

{

int map[N][N]/*迷宫数组*/

char ch

clrscr()

printf("\n Please select hand(1) else auto\n")/*选择探索方式*/

scanf("%c",&ch)

Init() /*初始化*/

MapRand(map)/*生成迷宫*/

PrMap(map)/*显示迷宫图*/

if(ch=='1')

PeopleFind(map)/*人工探索*/

else

FindWay(map,1,1)/*系统自动从下标1,1的地方开始探索*/

Result()/*输出结果*/

Close()

}

void Init(void)/*图形初始化*/

{

int gd=DETECT,gm

initgraph(&gd,&gm,"c:\\tc")

}

void DrawPeople(int *x,int *y,int n)/*画人工控制图*/

{/*如果将以下两句注释掉,则显示人工走过的路径,*/

setfillstyle(SOLID_FILL,WHITE) /*设置白色实体填充样式*/

bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6)

/*恢复原通路*/

switch(n)/*判断x,y的变化,8个方向的变化*/

{

case 1: (*x)--break/*上*/

case 2: (*x)--(*y)++break /*右上*/

case 3: (*y)++break /*右*/

case 4: (*x)++(*y)++break/*右下*/

case 5: (*x)++break /*下*/

case 6: (*x)++(*y)--break/*左下*/

case 7: (*y)--break /*左*/

case 8: (*x)--(*y)--break/*左上*/

}

setfillstyle(SOLID_FILL,RED)/*新位置显示探索物*/

bar(100+(*y)*15-6,50+(*x)*15-6,100+(*y)*15+6,50+(*x)*15+6)

}

void PeopleFind(int (*map)[N])/*人工手动查找*/

{

int x,y

char c=0/*接收按键的变量*/

x=y=1/*人工查找的初始位置*/

setcolor(11)

line(500,200,550,200)

outtextxy(570,197,"d")

line(500,200,450,200)

outtextxy(430,197,"a")

line(500,200,500,150)

outtextxy(497,130,"w")

line(500,200,500,250)

outtextxy(497,270,"x")

line(500,200,450,150)

outtextxy(445,130,"q")

line(500,200,550,150)

outtextxy(550,130,"e")

line(500,200,450,250)

outtextxy(445,270,"z")

line(500,200,550,250)

outtextxy(550,270,"c")/*以上是画8个方向的控制介绍*/

setcolor(YELLOW)

outtextxy(420,290,"Press 'Enter' to end")/*压回车键结束*/

setfillstyle(SOLID_FILL,RED)

bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6)/*入口位置显示*/

while(c!=13)/*如果按下的不是回车键*/

{

c=getch()/*接收字符后开始各个方向的探索*/

if(c=='w'&&map[x-1][y]!=1)

DrawPeople(&x,&y,1)/*上*/

else

if(c=='e'&&map[x-1][y+1]!=1)

DrawPeople(&x,&y,2)/*右上*/

else

if(c=='d'&&map[x][y+1]!=1)

DrawPeople(&x,&y,3)/*右*/

else

if(c=='c'&&map[x+1][y+1]!=1)

DrawPeople(&x,&y,4)/*右下*/

else

if(c=='x'&&map[x+1][y]!=1)

DrawPeople(&x,&y,5)/*下*/

else

if(c=='z'&&map[x+1][y-1]!=1)

DrawPeople(&x,&y,6)/*左下*/

else

if(c=='a'&&map[x][y-1]!=1)

DrawPeople(&x,&y,7)/*左*/

else if(c=='q'&&map[x-1][y-1]!=1)

DrawPeople(&x,&y,8)/*左上*/

}

setfillstyle(SOLID_FILL,WHITE)/*消去红色探索物,恢复原迷宫图*/

bar(100+y*15-6,50+x*15-6,100+y*15+6,50+x*15+6)

if(x==N-2&&y==N-2)/*人工控制找成功的话*/

yes=1/*如果成功标志为1*/

}

void WayCopy(int (*oldmap)[N],int (*map)[N])/*拷贝迷宫数组 */

{

int i,j

for(i=0i<Ni++)

for(j=0j<Nj++)

oldmap[i][j]=map[i][j]

}

int FindWay(int (*map)[N],int i,int j)/*递归找路*/

{

if(i==N-2&&j==N-2)/*走到出口*/

{

yes=1/*标志为1,表示成功*/

return

}

map[i][j]=1/*走过的地方变为1*/

WayCopy(oldmap,map)/*拷贝迷宫图*/

if(oldmap[i+1][j+1]==0&&!yes)/*判断右下方是否可走*/

{

FindWay(oldmap,i+1,j+1)

if(yes)/*如果到达出口了,再把值赋给显示路线的way数组,也正是这个原因,所以具体路线是从最后开始保存*/

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

WayCopy(oldmap,map)

if(oldmap[i+1][j]==0&&!yes)/*判断下方是否可以走,如果标志yes已经是1也不用找下去了*/

{

FindWay(oldmap,i+1,j)

if(yes)

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

WayCopy(oldmap,map)

if(oldmap[i][j+1]==0&&!yes)/*判断右方是否可以走*/

{

FindWay(oldmap,i,j+1)

if(yes)

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

WayCopy(oldmap,map)

if(oldmap[i-1][j]==0&&!yes)/*判断上方是否可以走*/

{

FindWay(oldmap,i-1,j)

if(yes)

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

WayCopy(oldmap,map)

if(oldmap[i-1][j+1]==0&&!yes)/*判断右上方是否可以走*/

{

FindWay(oldmap,i-1,j+1)

if(yes)

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

WayCopy(oldmap,map)

if(oldmap[i+1][j-1]==0&&!yes)/*判断左下方是否可以走*/

{

FindWay(oldmap,i+1,j-1)

if(yes)

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

WayCopy(oldmap,map)

if(oldmap[i][j-1]==0&&!yes)/*判断左方是否可以走*/

{

FindWay(oldmap,i,j-1)

if(yes)

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

WayCopy(oldmap,map)

if(oldmap[i-1][j-1]==0&&!yes)/*判断左上方是否可以走*/

{

FindWay(oldmap,i-1,j-1)

if(yes)

{

way[wayn][0]=i

way[wayn++][1]=j

return

}

}

return

}

void MapRand(int (*map)[N])/*开始的随机迷宫图*/

{

int i,j

cleardevice()/*清屏*/

randomize()/*随机数发生器*/

for(i=0i<Ni++)

{

for(j=0j<Nj++)

{

if(i==0||i==N-1||j==0||j==N-1)/*最外面一圈为墙壁*/

map[i][j]=1

else

if(i==1&&j==1||i==N-2&&j==N-2)/*出发点与终点表示为可走的*/

map[i][j]=0

else

map[i][j]=random(2)/*其它的随机生成0或1*/

}

}

}

void PrMap(int (*map)[N])/*输出迷宫图*/

{

int i,j

for(i=0i<Ni++)

for(j=0j<Nj++)

if(map[i][j]==0)

{

setfillstyle(SOLID_FILL,WHITE)/*白色为可走的路*/

bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6)

}

else

{

setfillstyle(SOLID_FILL,BLUE)/*蓝色为墙壁*/

bar(100+j*15-6,50+i*15-6,100+j*15+6,50+i*15+6)

}

}

void Find(void)/*找到通路*/

{

int i

setfillstyle(SOLID_FILL,RED)/*红色输出走的具体路线*/

wayn--

for(i=wayni>=0i--)

{

bar(100+way[i][1]*15-6,50+way[i][0]*15-6,100+

way[i][1]*15+6,50+way[i][0]*15+6)

sleep(1)/*控制显示时间*/

}

bar(100+(N-2)*15-6,50+(N-2)*15-6,100+

(N-2)*15+6,50+(N-2)*15+6)/*在目标点标红色*/

setcolor(GREEN)

settextstyle(0,0,2)/*设置字体大小*/

outtextxy(130,400,"Find a way!")

}

void NotFind(void)/*没找到通路*/

{

setcolor(GREEN)

settextstyle(0,0,2)/*设置字体大小*/

outtextxy(130,400,"Not find a way!")

}

void Result(void)/*结果处理*/

{

if(yes)/*如果找到*/

Find()

else/*没找到路*/

NotFind()

getch()

}

void Close(void)/*图形关闭*/

{

closegraph()

}

//*********************

//迷宫

//*********************

#include <stdio.h>

#include <stdlib.h>

#include <iostream.h>

char map[5][5] = {{'1','1','1','1','1'},{'0','0','0','1','1'},{'0','0','1','1','0'},{'1','1','1','0','0'},{'1','1','1','1','1'}}

//*************

//生成地图

//**************

void CreateMap()

{

for(int i =0i <5i++)

{

for(int j = 0j <5j++)

{

// printf("%c",map[i][j])

cout <<map[i][j]

}

cout <<endl

}

}

//*************************

//画出迷宫地图

//************************

void draw()

{

for(int i= 0i <5i++)

{

for(int j =0 j <5j++)

{

printf("%c",map[i][j])

}

putchar('\n')

}

}

//*********************

//判断下一步是否走得通

//********************

bool Judgenext(int row, int cloumn)

{

if(map[row][cloumn] == '1')

{

return 1

}

return 0

}

//******************

//离开迷宫

//******************

bool ExitMaze(int row, int cloumn)

{

bool done = 0

if(row == 4 &&cloumn == 4)

{

done = 1

}

else

{

if(Judgenext(row, cloumn) == 1)

{

map[row][cloumn] = 'B'

done = ExitMaze(row+1, cloumn)

if(done == 0)

{

done = ExitMaze(row, cloumn+1)

}

if(done == 0)

{

done = ExitMaze(row-1, cloumn)

}

if(done == 0)

{

done = ExitMaze(row, cloumn-1)

}

if(done == 1)

{

map[row][cloumn] = 'P'

}

}

}

return done

}

//***********************************

//解决问题

//***********************************

void slove()

{

bool done

done = ExitMaze(0,0)

if(done == 1)

{

printf("该迷宫可以走通!具体的步骤如下:\n")

draw()

}

else

{

printf("对不起,该迷宫无法走出!\n")

}

}

int main(void)

{

printf("This is a maze:\n")

CreateMap()

system("pause")

slove()

return 0

}

将C改为C++很简单。。。

本程序的前提是将迷宫保存在一个二维数组里,可走的地方为0,不可走的地方为1。由于采用回朔算法,不使用递归,所以首先应该建立一个栈来保存路径,路径是用一个一个点来表示的,也就是说栈中保存的是一系列点的列表。

栈节点类型说明:

struct StackNode

{

POINT Point

struct StackNode *Next, *Prev//双向链表形式

}

栈结构用一个类(CPointStack)实现,声明如下:

class CPointStack

{

public:

void ClearStack()//清空栈

void InitStack()//初始化栈

bool Pop(POINT &pt)//d出顶端元素,并给出该点的坐标,返回是否d出成功

bool Push(POINT pt)//将pt点的信息压入栈,返回是否压入成功

CPointStack()

virtual ~CPointStack()

protected:

StackNode *m_psnTop//栈顶指针

StackNode m_snBottom//栈底,不保存点信息

}

以下为成员函数实现,都是一些数据结构的 *** 作,应该没什么好说的:

//构造时初始化栈

CPointStack::CPointStack()

{

InitStack()

}

//析构时清空栈

CPointStack::~CPointStack()

{

ClearStack()

}

//将点压入栈(成功返回true,失败返回false)

bool CPointStack::Push(POINT pt)

{

StackNode* NewNode = new StackNode

//是否返回true主要看这里申请内存是否成功

if(!NewNode)

return false

NewNode->Point = pt

NewNode->Prev = m_psnTop

NewNode->Next = NULL

m_psnTop->Next = NewNode

m_psnTop = NewNode

return true

}

//将点d出栈(成功返回true,栈为空则返回false)

bool CPointStack::Pop(POINT &pt)

{

if(m_psnTop == &m_snBottom)//是否返回true主要看这里栈是否为空

return false

StackNode *p

p = m_psnTop

m_psnTop = m_psnTop->Prev

pt = p->Point

delete p

m_psnTop->Next = NULL

return true

}

//初始化栈

void CPointStack::InitStack()

{

m_psnTop = &m_snBottom

m_snBottom.Next = NULL

m_snBottom.Prev = NULL

}

//清空栈

void CPointStack::ClearStack()

{

StackNode *p

while(m_psnTop != &m_snBottom)

{

p = m_psnTop

m_psnTop = m_psnTop->Prev

delete p

}

}

接下来设计怎样走出这个迷宫,也就是迷宫算法的主体部分。再次用一个类实现。

在设计这个类时,我考虑到以下几点:

1、迷宫入口和出口的坐标

2、保存迷宫的2维数组

3、获得路径的函数

但是实际设计时由于没有考虑太多问题,只是以设计迷宫算法和解决一个具体迷宫为目的,所以没有考虑动态大小的迷宫,而是将迷宫大小定为601×401。而且在设计迷宫算法后没有将路径顺序输出而是直接在原图中标识(在保存迷宫数据的表中设置经过的点为2而将死路点设置为3)。

这样迷宫类(CGoMaze)的声明为:

class CGoMaze

{

public:

void Go()//寻找路径的函数

POINT m_ptIn//入口坐标

POINT m_ptOut//出口坐标

BYTE m_btArrMaze[401][601]//保存迷宫的二维表

CGoMaze()

virtual ~CGoMaze()

}

最后让我们来看一下CGoMaze::Go()这个函数:

我们模仿人走迷宫时的思路,设置一个当前点,一个目标点(下一个要走的点)。初始情况下当前点为入口,终止条件为当前点为出口,这样,我们的函数大概结构就出来了。

在从入口到出口的过程中程序对当前点的上、下、左、右四个点依次进行判断,当发现任一个方向是未走过的区域时,就将当前点指向那个点进行尝试,同时将当前点入栈并做标记。而当4个方向都不通或已走过时,则为死路,标记当前点为死路并从栈中d出上一个点继续进行尝试,这时因为当前点已被标记为死路,则d出上一个点时就不会重复这条路,达到寻找正确路径的效果。

Go函数的具体实现如下,其实挺简单的^_^:

void CGoMaze::Go()

{

CPointStack psPath//保存路径的栈

POINT ptCur = m_ptIn, ptNext//设置当前点为入口

while(ptCur.x != m_ptOut.x || ptCur.y != m_ptOut.y)//判断是否已经走出

{

ptNext = ptCur//设置目标点为当前点,便于下面偏移

if(m_btArrMaze[ptCur.y - 1][ptCur.x] == 0)

ptNext.y --//如果上方是空的,则目标点向上偏移

else if(m_btArrMaze[ptCur.y][ptCur.x - 1] == 0)

ptNext.x --//如果左边是空的,则目标点向左偏移

else if(m_btArrMaze[ptCur.y + 1][ptCur.x] == 0)

ptNext.y ++//如果下方是空的,则目标点向下偏移

else if(m_btArrMaze[ptCur.y][ptCur.x + 1] == 0)

ptNext.x ++//如果右边是空的,则目标点向右偏移

else

{//这里是没有路的状态

m_btArrMaze[ptCur.y][ptCur.x] = 3//标记为死路

psPath.Pop(ptCur)//d出上一次的点

continue//继续循环

}

//如果有路的话会执行到这里

m_btArrMaze[ptCur.y][ptCur.x] = 2//标记当前点为路径上的点

psPath.Push(ptCur)//当前点压入栈中

ptCur = ptNext//移动当前点

}

}

其实这个部分可以将栈设置为CGoMaze类的成员,然后在Go函数里加上:

psPath.ClearStack()

这样就可以用Timer来演示走迷宫的过程了


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

原文地址: http://outofmemory.cn/yw/11024148.html

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

发表评论

登录后才能评论

评论列表(0条)

保存