迷宫问题

问题描述

迷宫实验是取自心理学的一个古典实验。在该实验中,把一只老鼠从一个无顶大盒子的门放入,在盒中设置了许多墙,对行进方向形成了多处阻挡。盒子仅有一个出口,在出口处放置一块奶酪,吸引老鼠在迷宫中寻找道路以到达出口。对同一只老鼠重复进行上述实验,一直到老鼠从入口到出口,而不走错一步。老鼠经多次试验终于得到它学习走迷宫的路线。

设计功能要求

迷宫由m行n列的二维数组设置,0表示无障碍,1表示有障碍。设入口为(1,1),出口为(m,n),每次只能从一个无障碍单元移到周围四个方向上任一无障碍单元。编程实现对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。

代码细节:

定义栈

typedef struct Stack
{
    int* base;
    int* top;
    int stacksize;
}Stack;

入栈出栈

void Push(Stack* S, int e) {
    //插入栈顶元素为e,由于一开始对于栈的初始化,不必要考虑爆栈的情况
    *S->top++ = e;
}
void Pop(Stack* S) {
    //若栈不空,则删除S的栈顶元素,用e返回其值
    if (S->top == S->base)
    {
        ;
    }
    else
    {
        S->top--;
    }
}

遍历两个栈,若某一个点的位置坐标刚好处于这两个栈中的同一个位置,那么返回1;否则,返回0。其中count为栈中元素的个数,new_h为新输入的行数,new_l为新输入的列数

int isoverlap(Stack* p, Stack* q, int count, int new_h, int new_l)
{
    int* g = p->top;
    int* h = q->top;
    for (int i = 0; i < count; i++)
    {
        g--;
        h--;
        if ((new_h == *g) && (new_l == *h))
        {
            return 1;
        }
    }
    return 0;
}

访问栈顶元素,count为栈中元素的个数

int visit_top(Stack* p, int count)
{
    int* h = p->top;
    if (p->base != p->top)
    {
        h--;
        return *h;
    }
}

主函数中先输入迷宫矩阵
构造2个栈,并且初始化

 Stack* a = (Stack*)malloc(sizeof(Stack));//储存行数
    if (!a)
    {
        exit(0);
    }
    a->base = (int*)malloc((m * n) * sizeof(int));
    if (!a->base)
    {
        exit(0);
    }
    a->stacksize = m * n;
    a->top = a->base;
    Stack* b = (Stack*)malloc(sizeof(Stack));//储存列数
    if (!b)
    {
        exit(0);
    }
    b->base = (int*)malloc((m * n) * sizeof(int));
    if (!b->base)
    {
        exit(0);
    }
    b->stacksize = m * n;
    b->top = b->base;

具体的迷宫操作,默认入口为(1,1),出口为(m,n)

int x = 0;//即将入栈的行位置
    int y = 0;//即将入栈的列位置
    Push(a, x);
    Push(b, y);
    int temp_num = 1;
    while ((a->base != a->top) && ((x != m - 1) || (y != n - 1)))
    {
        if (((y + 1) < n) && (matrix[x][y + 1] == 0))//右
        {
            if (!isoverlap(a, b, temp_num, x, y + 1))
            {
                Push(a, x);
                Push(b, y + 1);
                x = x;
                y = y + 1;
                temp_num++;
                continue;
            }
        }
        if (((x + 1) < m) && (matrix[x + 1][y] == 0))//下
        {
            if (!isoverlap(a, b, temp_num, x + 1, y))
            {
                Push(a, x + 1);
                Push(b, y);
                x = x + 1;
                y = y;
                temp_num++;
                continue;
            }
        }
        if (((y - 1) >= 0) && (matrix[x][y - 1] == 0))//左
        {
            if (!isoverlap(a, b, temp_num, x, y - 1))
            {
                Push(a, x);
                Push(b, y - 1);
                x = x;
                y = y - 1;
                temp_num++;
                continue;
            }
        }
        if (((x - 1) >= 0) && (matrix[x - 1][y] == 0))//上
        {
            if (!isoverlap(a, b, temp_num, x - 1, y))
            {
                Push(a, x - 1);
                Push(b, y);
                x = x - 1;
                y = y;
                temp_num++;
                continue;
            }
        }

栈顶元素为出口坐标,那么break跳出循环

if ((visit_top(a, temp_num) == m - 1) && (visit_top(b, temp_num) == n - 1))
        {
            break;
        }

无路可走,就开始出栈,与此同时将matrix中相应的位置修改成1,表示此路不通

int s = visit_top(a, temp_num);
        int t = visit_top(b, temp_num);
        Pop(a);
        Pop(b);
        x = visit_top(a, temp_num);
        y = visit_top(b, temp_num);
        matrix[s][t] = 1;
    }
    if ((visit_top(a, temp_num) == m - 1) && (visit_top(b, temp_num) == n - 1))
    {
        printf("从入口到出口存在通路!!!");
        printf("\n");

the last

 int* hang = (int*)malloc(temp_num * sizeof(int));//倒序存储行坐标
        int* lie = (int*)malloc((temp_num) * sizeof(int));//倒序存储列坐标
        int* v = a->top;
        int* u = b->top;
        for (int i = 0; i < temp_num; i++)
        {
            v--;
            u--;
            hang[i] = *v + 1;
            lie[i] = *u + 1;
        }
        printf("出迷宫走的行序号序列为:");
        for (int z = temp_num - 1; z >= 0; z--)
        {
            printf("%d ", hang[z]);
        }
        printf("\n");
        printf("出迷宫走的列序号序列为:");
        for (int z = temp_num - 1; z >= 0; z--)
        {
            printf("%d ", lie[z]);
        }
    }
    else
    {
        printf("从入口到出口不存在通路");
    }
    return 0;
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值