迷宫问题C语言实现

#include <stdio.h>


//#define DEBUG 1
#include "../lib/debug.h"


#define OK            (0)
#define NOK          (-1)


#define MAZE_SIZE 4


enum Tagderection
{
    RIGHT = 0,
    DOWN,
    LEFT,
    UP,
    END
};


typedef struct TagPosition
{
    int x; 
    int y;
    /* 当前位置是上个位置往哪个方向走得到的,回溯的时候取下个方向 */
    int dire;      
}Position;


typedef struct TagMazePath
{
    Position pos[MAZE_SIZE*MAZE_SIZE];    /* 迷宫最长路径为 MAZE_SIZE*MAZE_SIZE */
    int top;
}MazePath;




/* 初始化迷宫,1表示可以走,0表示不能走 */
void MazeInit(int maze[][MAZE_SIZE])
{
    int i,j;


    for(i = 0; i < MAZE_SIZE; i++)
        for (j = 0; j < MAZE_SIZE; j++)
            maze[i][j] = 0;


   for(i = 0; i < MAZE_SIZE ; i++)
        maze[0][i] = 1;


   for(i = 0; i < MAZE_SIZE ; i++)
        maze[i][MAZE_SIZE-1] = 1;


   for(i = 0; i < MAZE_SIZE; i++)
        maze[i][0] = 1;


   for(i = 0; i < MAZE_SIZE; i++)
        maze[MAZE_SIZE-1][i] = 1;      


   return ;  
}


/*************************************************
打印出迷宫的出路
*************************************************/
void MazeDisplayPath(MazePath my_path)
{
    int i;
    for(i = 0; i <= my_path.top ; i++)
    {
        printf("%d,%d   ",my_path.pos[i].x,my_path.pos[i].y);
    }
    printf("\n");
}


/*************************************************
打印出迷宫,X表示可以走,0表示不能走
*************************************************/
int MazeDisplay(int maze[][MAZE_SIZE])
{
    int i,j;


    for(i = 0; i < MAZE_SIZE; i++)
        for (j = 0; j < MAZE_SIZE; j++)
        {
            if(1 == maze[i][j])
                printf("X");
            else
                printf("0");


            if((MAZE_SIZE-1) == j)
                printf("\n");
        }
   return ;  
}


/*************************************************
迷宫入口入栈
*************************************************/
void MazePathInit(MazePath *my_path)
{
    my_path->top = 0;
    my_path->pos[0].x = 0;
    my_path->pos[0].y = 0;   
    my_path->pos[0].dire = UP;  
}


/*************************************************
判断栈是否为空,为空返回OK,否则返回NOK
*************************************************/
int PathEmpty(MazePath my_path)
{
    if(my_path.top >= 0)
        return NOK;
    else
        return OK;
}


/*************************************************
是否找到迷宫出口,找到则返回OK,否则返回NOK
*************************************************/
int MazeFoundWay(MazePath my_path)
{
    if(my_path.pos[my_path.top].x != (MAZE_SIZE-1) || my_path.pos[my_path.top].y != (MAZE_SIZE-1))
        return NOK;
    else
        return OK;
}


/*************************************************
判断移动是否合法,合法返回OK,否则返回NOK
*************************************************/
int MoveValid(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath my_path,int move_diretion)
{
    int cur_x,cur_y,next_x,next_y;


    cur_x = my_path.pos[my_path.top].x;
    cur_y = my_path.pos[my_path.top].y;


    switch(move_diretion)
    {
        case RIGHT:
            next_x = cur_x;
            next_y = cur_y  + 1;
            break;
        case DOWN:
            next_x = cur_x + 1;
            next_y = cur_y;
            break;
        case LEFT:
            next_x = cur_x;
            next_y = cur_y  - 1;
            break;
        case UP:
            next_x = cur_x - 1;
            next_y = cur_y;
            break;            
         default:
            return NOK;
    }


    if(next_x < 0 || next_x >= MAZE_SIZE || next_y < 0 || next_y >= MAZE_SIZE)
    {
        DB("Meet the wall");
        return NOK;
    }


    if(1 == mark[next_x][next_y])
    {
        DB("Already passes this position");
        return NOK;
    }


    if(0 == maze[next_x][next_y])
    {
        DB("This position is not way");
        return NOK;
    }


    return OK;
}


/*************************************************
向选定的方向前进一步
*************************************************/
void MoveForward(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath *my_path,int move_diretion)
{
    int cur_x,cur_y,next_x,next_y;


    cur_x = my_path->pos[my_path->top].x;
    cur_y = my_path->pos[my_path->top].y;


    switch(move_diretion)
    {
        case RIGHT:
            next_x = cur_x;
            next_y = cur_y  + 1;
            break;
        case DOWN:
            next_x = cur_x + 1;
            next_y = cur_y;
            break;
        case LEFT:
            next_x = cur_x;
            next_y = cur_y  - 1;
            break;
        case UP:
            next_x = cur_x - 1;
            next_y = cur_y;
            break;            
         default:
            exit(1);
    }


    mark[next_x][next_y] = 1;
    
    my_path->top ++;
    my_path->pos[my_path->top].x = next_x;
    my_path->pos[my_path->top].y = next_y;
    my_path->pos[my_path->top].dire = move_diretion;
    return ;
}


/*************************************************
回退到上个位置继续查找路径
*************************************************/
void MoveBack(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath *my_path)
{
    int cur_x,cur_y;


    cur_x = my_path->pos[my_path->top].x;
    cur_y = my_path->pos[my_path->top].y;
    
    mark[cur_x][cur_y] = 0;
    my_path->top --;
}


/*************************************************
迷宫问题解法函数,采用回溯算法
*************************************************/
void MazeFindWayOut(int maze[][MAZE_SIZE])
{
    int i,j;
    int move_diretion;
    int diretion_start = RIGHT;
    MazePath my_path;
    int mark[MAZE_SIZE][MAZE_SIZE] = {0};      /* 标记该位置是否到过 */


    MazePathInit(&my_path);   /* 迷宫入口入栈 */
    mark[0][0] = 1;
    
    while(OK != PathEmpty(my_path))
    {
        if( OK == MazeFoundWay(my_path))
        {
            DB("Find way out");
            MazeDisplayPath(my_path);
#if 0  
            /* 如果是只要找到一条路径,那么在这里退出 */
            return;
#else
            diretion_start = my_path.pos[my_path.top].dire + 1; 
            DB("back");
            MoveBack(maze,mark,&my_path);
            continue;
#endif
        }


        for(move_diretion = diretion_start ; move_diretion < END ; move_diretion++)
        {
            if(OK == MoveValid(maze,mark,my_path,move_diretion))
            {
                MoveForward(maze,mark,&my_path,move_diretion);
                break;
            }
        }


        /* 死路,回溯 */
        if(END == move_diretion)
        {
            /* 本位置是从上个位置的哪个方向移动得到 */
            /* 回溯后则从上个位置的下个方向开始移动 */
            diretion_start = my_path.pos[my_path.top].dire + 1; 
            DB("back");
            MoveBack(maze,mark,&my_path);    
        }
        else
        {
            diretion_start = RIGHT;
        }
    }


}


int main(int argc, char **argv)
{
    int maze[MAZE_SIZE][MAZE_SIZE];
    MazeInit(maze);
    MazeDisplay(maze);
    MazeFindWayOut(maze);
    return;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值