迷宫求解

1问题

   通过给定的入口和出口,求出迷宫的通路。

2算法

1】若当前位置“可通”,则纳入“当前路径”,并继续朝“下一位置”探索,即切换“下一位置”为“当前位置”,如此重复直至到达出口;

2】若当前位置“不可通”,则应顺着“来向”退回到“前一通道块”,然后朝着除“来向”之外的其他方向继续搜索;

3】若该通道块的四周4个方块均“不可通”,则应从“当前路径”上删除该通道块。

注:

   “下一个位置”指的是“当前位置”四周4个方向(东、南、西、北)上相邻的方块。

3实现

#include <stdio.h>
#include <stdlib.h>

#define OK     0
#define ERROR -1
#define TRUE   1
#define FALSE  0

/*坐标*/
typedef struct
{
    int n;/*行*/
    int m;/*列*/
}pos_t;

/*方向顺时针表示: 东南西北*/
typedef enum 
{
    EAST = 0,
    SOUTH,
    WEST,
    NORTH,

    DIR_MAX,
}dir_t;

/*栈元素*/
typedef struct
{
    int    ord;   /*序号*/
    pos_t seat;   /*坐标位置*/
    dir_t  dir;   /*方向*/
}stack_elem_t;

#define STACK_INIT_SIZE 100
#define STACKINCREMENT   10
/*顺序栈*/
typedef struct
{
    stack_elem_t *base;/*栈底*/
    stack_elem_t *top; /*栈顶指针*/
    int stack_size;    /*栈的初始大小*/
}seq_stack_t;

/*迷宫图*/
#define MAX_LEN 10
typedef struct
{ 
    char maze_map[MAX_LEN][MAX_LEN];
}maze_map_t;

/*初始化栈元素*/
void init_stack_elem(stack_elem_t *elem, int ord, pos_t *pos, dir_t dir)
{
    elem->ord = ord;
    elem->seat = *pos;
    elem->dir = dir;
}

/*栈的初始化*/
int seq_stack_init(seq_stack_t *stack)
{
    stack->base = stack->top = (stack_elem_t *)malloc(STACK_INIT_SIZE * sizeof(stack_elem_t));
    if (stack->base == NULL)
    {
        return ERROR;
    }
    stack->stack_size = STACK_INIT_SIZE;

    return OK;
}

/*进栈操作*/
int push(seq_stack_t *stack, stack_elem_t *elem)
{
    /*栈慢则追加空间*/
    if (stack->top - stack->base >= stack->stack_size)
    {
        stack->base = (stack_elem_t *)realloc(stack->base, (STACK_INIT_SIZE + STACKINCREMENT)*sizeof(stack_elem_t));
        if (stack->base == NULL)
        {
            return ERROR;
        }
        stack->top = stack->base + stack->stack_size;
        stack->stack_size = STACK_INIT_SIZE + STACKINCREMENT;
    }
    /*进栈*/
    *stack->top++ = *elem;

    return OK;
}

/*出栈操作*/
int pop(seq_stack_t *stack, stack_elem_t *elem)
{
    /*栈空则出错*/
    if (stack->base == stack->top)
    {
        return ERROR;
    }

    *elem = *(--stack->top);

    return OK;
}

/*栈空判断*/
int stack_empty(seq_stack_t *stack)
{
    return (stack->base == stack->top);
}

/*栈的销毁*/
void seq_stack_destroy(seq_stack_t *stack)
{
    if (stack->base)
    {
        free(stack->base);
    }
    stack->stack_size = 0;

    return ;
}


/*初始化迷宫*/
void init_maze_wall(maze_map_t *maze)
{
    int i,j;

    /*将迷宫外墙设置为#*/
    for (i = 0; i < MAX_LEN; i++)
    {
        /*迷宫上下围墙*/
        maze->maze_map[0][i] = '#';
        maze->maze_map[MAX_LEN-1][i] = '#';
        /*迷宫左右围墙*/
        maze->maze_map[i][0] = '#';
        maze->maze_map[i][MAX_LEN-1] = '#';
    }

    /*迷宫内部所有通道设置为可通,用'0'表示*/
    for (i = 1; i < MAX_LEN-1; i++)
    {
        for (j = 1; j < MAX_LEN-1;j++)
        {
            maze->maze_map[i][j] = '0';
        } 
    }

    /*在迷宫内设置不可通的通道,用'#表示*/
    maze->maze_map[1][3] = maze->maze_map[1][7] = '#';
    maze->maze_map[2][3] = maze->maze_map[2][7] = '#';
    maze->maze_map[3][5] = maze->maze_map[3][6] = '#';
    maze->maze_map[4][2] = maze->maze_map[4][3] = maze->maze_map[4][4] = '#';
    maze->maze_map[5][4] = '#';
    maze->maze_map[6][2] = maze->maze_map[6][6] = '#';
    maze->maze_map[7][2] = maze->maze_map[7][3] = maze->maze_map[7][4] = maze->maze_map[7][6] = maze->maze_map[7][7]= '#';
    maze->maze_map[8][1] = '#';

    return ;
}

/*打印迷宫图*/
void maze_print(maze_map_t *map)
{
    int i,j;
    
    for (i = 0; i < MAX_LEN; i++)
    {
        for (j = 0; j < MAX_LEN; j++)
        {
            printf("%2c ", map->maze_map[i][j]);
        }
        printf("\n");
    }
}

/*位置是否可通*/
int pos_pass(maze_map_t *map, pos_t *pos)
{
    return map->maze_map[pos->n][pos->m] == '0';
}

/*下一个位置*/
pos_t pos_next(pos_t *pos, dir_t dir)
{
    pos_t tmp = *pos;
    switch(dir)
    {
        case EAST:
            tmp.m += 1;
            break;
        case WEST:
            tmp.m -= 1;
            break;
        case SOUTH:
            tmp.n += 1;
            break;
        case NORTH:
            tmp.n -= 1;
            break;
    }
    return tmp;
}

/*留下足迹'1'表示走过,在四周探索时,该位置即为来向,走不通*/
void foot_print(maze_map_t *map, pos_t *pos)
{
    map->maze_map[pos->n][pos->m] = '1';
}

/*标记为不可通,表示该路径不可通*/
void make_print(maze_map_t *map, pos_t *pos)
{
    map->maze_map[pos->n][pos->m] = '@';
}

/*查找迷宫路径*/
int maze_path_find(maze_map_t *map, pos_t start, pos_t end, seq_stack_t *stack)
{
    stack_elem_t elem;
    pos_t curpos = start;/*当前路径*/
    int  curstep = 1;    /*探索第一步*/
    
    do
    {
        /*当前路径可通*/
        if (pos_pass(map, &curpos))
        {
            foot_print(map, &curpos);/*留下足迹'1',由'1'构成的路径便是通路*/
            init_stack_elem(&elem, curstep, &curpos, EAST);
            push(stack, &elem);/*加入路径*/
            
            if (curpos.n == end.n && curpos.m == end.m)
            {
                return TRUE;/*到达终点*/
            }
            curpos = pos_next(&curpos, EAST);/*下一个位置是当前位置的东临*/
            curstep++;/*探索下一步*/
        }
        else
        {
            if (!stack_empty(stack))
            {
                pop(stack, &elem);
                while (elem.dir == DIR_MAX && !stack_empty(stack))
                {
                    make_print(map, &elem.seat);/*留下不能通过标记*/
                    pop(stack, &elem);          /*退回一步*/
                }
                /*继续向其他方向探索*/
                if (elem.dir < DIR_MAX)
                {
                    elem.dir++;/*向其他三个方向探索,通过pos_pass判断是否可通。来向块已记为'1,自然不可通'*/
                    push(stack, &elem);
                    curpos = pos_next(&elem.seat, elem.dir);
                }
            }
        }
    }while(!stack_empty(stack));

    return FALSE;
}

int main()
{
    int ret;
    maze_map_t map;    /*声明迷宫图*/
    seq_stack_t stack; /*声明栈*/
    pos_t start, end;/*声明迷宫入口和出口*/

    /*初始化栈*/
    seq_stack_init(&stack);
    /*初始化迷宫图*/
    init_maze_wall(&map);
    /*初始化迷宫入口和出口*/
    start.n = start.m = 1;
    end.n = end.m = 8;

    printf("***********迷宫图************\n");
    maze_print(&map);

    /*查找迷宫通路*/
    ret = maze_path_find(&map, start, end, &stack);
    if (ret == TRUE)
    {
        printf("\n*********迷宫图通路**********\n");
        maze_print(&map);
        printf("\n.由1构成的路径便是迷宫图通路.\n");
    }

    /*销毁栈*/
    seq_stack_destroy(&stack);

    return 0;
}

ubuntu $ ./maze 
***********迷宫图************
 #  #  #  #  #  #  #  #  #  # 
 #  0  0  #  0  0  0  #  0  # 
 #  0  0  #  0  0  0  #  0  # 
 #  0  0  0  0  #  #  0  0  # 
 #  0  #  #  #  0  0  0  0  # 
 #  0  0  0  #  0  0  0  0  # 
 #  0  #  0  0  0  #  0  0  # 
 #  0  #  #  #  0  #  #  0  # 
 #  #  0  0  0  0  0  0  0  # 
 #  #  #  #  #  #  #  #  #  # 

*********迷宫图通路**********
 #  #  #  #  #  #  #  #  #  # 
 #  1  1  #  @  @  @  #  0  # 
 #  0  1  #  @  @  @  #  0  # 
 #  1  1  @  @  #  #  0  0  # 
 #  1  #  #  #  0  0  0  0  # 
 #  1  1  1  #  0  0  0  0  # 
 #  0  #  1  1  1  #  0  0  # 
 #  0  #  #  #  1  #  #  0  # 
 #  #  0  0  0  1  1  1  1  # 
 #  #  #  #  #  #  #  #  #  # 

.由1构成的路径便是迷宫图通路.
ubuntu $




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
程序在VC++ 6下顺利编译通过。 一、 实验目的: (1) 熟练掌握链栈的基本操作及应用。 (2) 利用链表作为栈的存储结构,设计实现一个求解迷宫的非递归程序。 二、实验内容: 【问题描述】 以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对信任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。 【基本要求】 首先实现一个链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),……。 【测试数据】 迷宫的测试数据如下:左上角(1,1)为入口,右下角(8,9)为出口。 1 2 3 4 5 6 7 8 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 以方阵形式输出迷宫及其通路。 输出: 请输入迷宫的长和宽:5 5 请输入迷宫内容: 0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 0 0 0 迷宫的路径为 括号内的内容分别表示为(行坐标,列坐标,数字化方向,方向) (1,1,1,↓) (2,1,2,→) (2,2,1,↓) (3,2,1,↓) (4,2,2,→) (4,3,1,↓) (5,3,2,→) (5,4,2,→) (5,5,0,) 迷宫路径探索成功!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值