POJ2251:Dungeon Master(三维迷宫)

本文介绍了一个3D迷宫逃脱问题的经典解决方法,通过使用广度优先搜索(BFS)算法来寻找从起点到终点的最短路径。文章详细展示了如何通过C语言实现这一算法,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides. 

Is an escape possible? If yes, how long will it take? 
Input
The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size). 
L is the number of levels making up the dungeon. 
R and C are the number of rows and columns making up the plan of each level. 
Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a '#' and empty cells are represented by a '.'. Your starting position is indicated by 'S' and the exit by the letter 'E'. There's a single blank line after each level. Input is terminated by three zeroes for L, R and C.
Output
Each maze generates one line of output. If it is possible to reach the exit, print a line of the form 
Escaped in x minute(s).

where x is replaced by the shortest time it takes to escape. 
If it is not possible to escape, print the line 
Trapped!
Sample Input
3 4 5
S....
.###.
.##..
###.#

#####
#####
##.##
##...

#####
#####
#.###
####E

1 3 3
S##
#E#
###

0 0 0
Sample Output
Escaped in 11 minute(s).
Trapped!

# include <stdio.h>
# include <string.h>
struct node
{
    int x, y, z, step;
}a[27001];

char map[31][31][31];
int vis[31][31][31], next[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
int v, n, m, result, flag, sx,sy,sz,ex,ey,ez;

void bfs(int x, int y, int z, int step)
{
    int head, tail, mx, my, mz, i;
    head = tail = 0;
    vis[x][y][z] = 1;
    a[head].x = x;
    a[head].y = y;
    a[head].z = z;
    a[head].step = step;
    while(head <= tail)
    {
        for(i=0; i<6; ++i)
        {
            mx = a[head].x + next[i][0];
            my = a[head].y + next[i][1];
            mz = a[head].z + next[i][2];
            if(mx<0||my<0||mz<0||mx>=v||my>=n||mz>=m)
                continue;
            else
            {
                if(!vis[mx][my][mz] && map[mx][my][mz] != '#')
                {
                    ++tail;
                    vis[mx][my][mz] = 1;
                    a[tail].x = mx;
                    a[tail].y = my;
                    a[tail].z = mz;
                    a[tail].step = a[head].step+1;
                    if(map[mx][my][mz] == 'E')
                    {
                        flag = 1;
                        result = a[tail].step;
                        return;
                    }
                }
            }
        }
        ++head;
    }
}
int main()
{
    int i, j, k;
    while(scanf("%d%d%d",&v,&n,&m),v+n+m)
    {
        memset(map, 0, sizeof(map));
        memset(vis, 0, sizeof(vis));
        memset(a, 0, sizeof(a));
        flag = 0;
        for(i=0; i<v; ++i)
            for(j=0; j<n; ++j)
                scanf("%s",map[i][j]);
        for(i=0; i<v; ++i)
            for(j=0; j<n; ++j)
                for(k=0; k<m; ++k)
                if(map[i][j][k]=='S')
                {
                    sx = i;
                    sy = j;
                    sz = k;
                }
                else if(map[i][j][k]=='E')
                {
                    ex = i;
                    ey = j;
                    ez = k;
                }
        bfs(sx, sy, sz, 0);
        if(!flag)
            puts("Trapped!");
        else
            printf("Escaped in %d minute(s).\n",result);
    }
    return 0;
}



前面几日我重新实现了迷宫的自动生成方法,并且添加了迷宫自动寻路方法。有了一个独立于GUI的迷宫库,我开始迫不及待地实现三维迷宫了! 下面是我在开发迷宫程序中遇到的问题。 1、怎样将迷宫类的行和列映射到真实的三维坐标中?迷宫应该用哪个参考系来描述? 其实我在制作的时候为了简化,将二维迷宫的左上角与三维的原点重合,二维迷宫的右对应三维的X轴正方向,迷宫的下对应Z轴的正方向。 2、迷宫的“上、下、左、右”在三维中应该叫做什么? 在确定好迷宫的位置后,我们将迷宫的上对应Z轴的负半轴,下对应Z轴的正半轴,左对应X轴的负半轴,右对应Y轴的正半轴。 3、三维点绘制顺序以及OpenGL裁剪模式造成的一些面不可见问题。 这个问题是我在编写二维迷宫没有想到的。主要是因为二维迷宫中描述墙是用一条直线,而到了三维则是一个面。由于在OpenGL中有裁剪模式可以选择,我使用了 glFrontFace( GL_CW ); // 顺时针的绘制为正面 glEnable( GL_CULL_FACE ); // 剔除不是正面的面 进行设定,也就是说,所有在摄像机看来是逆时针绘制的图形都无法显示。因此我不得不用同样的顶点绘制两个面。下面是相关的函数: void DrawInnerWall( Point3F& p1, Point3F& p2, Point3F& p3, Point3F& p4 ) { glTexCoord2f( 0.0f, 1.0f ); glVertex3fv( p1 ); glTexCoord2f( 1.0f, 1.0f ); glVertex3fv( p2 ); glTexCoord2f( 1.0f, 0.0f ); glVertex3fv( p3 ); glTexCoord2f( 0.0f, 0.0f ); glVertex3fv( p4 ); } void DrawOuterWall( Point3F& p1, Point3F& p2, Point3F& p3, Point3F& p4 ) { glTexCoord2f( 1.0f, 1.0f ); glVertex3fv( p1 ); glTexCoord2f( 0.0f, 1.0f ); glVertex3fv( p2 ); glTexCoord2f( 0.0f, 0.0f ); glVertex3fv( p3 ); glTexCoord2f( 1.0f, 0.0f ); glVertex3fv( p4 ); } 在编写这些函数的时候尤其注意纹理坐标的绘制顺序。可以在纸上绘制一个草图。下面是我调用的代码: if ( Cell_UpWall( cell ) ) { DrawInnerWall( p8, p7, p3, p4 ); DrawOuterWall( p7, p8, p4, p3 ); } 4、怎样设置阻挡? 设置阻挡的基本原则还是先检测后执行。首先我先尝试着执行走一步,再判断这一步是不是出现了越界问题。如果出现了越界问题,那么不执行这一步,否则执行这一步。为了不让我们无限地靠近墙,我设定了一个gap,即摄像机必须与墙保持gap的距离。 下面是我相关的代码: bool View3D::CanGo( Maze& maze, float step ) { static float gap = m_CellSize.w / 8.0f;// 摄像机与墙最近不能超过的间隔 const Point3F& pos = m_Camera.Pos( ); Point3F tryPos; if ( pos.y > 0 && pos.y ( row - 1 ) * m_CellSize.w ); if (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值