迷宫求解(栈)

31 篇文章 1 订阅
8 篇文章 0 订阅

这篇博客是借鉴了Always__的博客修改得到了,感谢他的帮助。

采用了以栈为基础,在栈的基础上进行迷宫的求解,用Stack和Maze两个文件来实现功能。


Stack.h的实现如下:

#pragma once

#include <stdio.h>  
#include <malloc.h>  
#include <stdlib.h>  
#include <string.h>
typedef int DirectiveType;        //下一个通道方向  
#define RANGE 100                 //迷宫大小  
#define STACK_INIT_SIZE 100
#define STACKINCREMENT    10
//------------  栈的顺序存储实现  ------------------------------
typedef struct 
{
	int row;                     //迷宫中的行
    int col;                     //迷宫中的列
}PosType;                        //坐标(row,col)

typedef struct
{
    int step;                    //当前位置在路径上的"序号"
    PosType seat;                //当前的坐标位置
    DirectiveType di;            //往下一个坐标位置的方向
}SElemType;                      //栈的元素类型
typedef struct
{
    SElemType *base;
    SElemType *top;
    int stacksize;
}SqStack;

bool InitStack(SqStack &s);          //栈的创建,即构造一个空栈
bool GetTop(SqStack s,SElemType &e); //如栈不为空,用e返回栈顶元素
bool Push(SqStack &s, SElemType e);  //在栈中插入元素
bool Pop(SqStack &s, SElemType &e);  //删除栈顶元素
bool StackEmpty(SqStack s);          //判断栈为不为空
bool DestoryStack(SqStack &s);       //销毁栈

Stack.cpp实现如下:

#include "Stack.h"               
#include "Maze.h"    

bool InitStack(SqStack &s)
{ //栈的初始化
    s.base = (SElemType * ) malloc(STACK_INIT_SIZE * sizeof(SElemType));
    if(!s.base) 
	{
		exit(-2);
	}
    s.top=s.base;
    s.stacksize=STACK_INIT_SIZE;
    return true;
}

bool GetTop(SqStack s, SElemType &e )
{
    if( s.top == s.base) 
	{
		return false;
	}
    e = *(s.top-1);
    return true;
}

bool Push(SqStack &s, SElemType e)
{
    if(s.top-s.base >= s.stacksize)
	{    //栈满,追加存储空间
        s.base = (SElemType *)realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(SElemType));
        if(!s.base) 
		{
			exit(-2);
		}
        s.top = s.base + s.stacksize;
        s.stacksize += STACKINCREMENT;
    }
    *s.top++ = e;
    return true;
}

bool Pop(SqStack &s, SElemType &e)
{
    if(s.top==s.base)
		return false;
    e = * --s.top;
    return true;
}

bool StackEmpty(SqStack s)
{
    return s.base == s.top;
}

bool DestoryStack(SqStack &s)
{
	free(&s);
	return true;
}


Maze.h实现如下:

typedef int DirectiveType;        //下一个通道方向  
#define RANGE 100                 //迷宫大小  
#define ROW 10                    //迷宫的行数
#define COL 10                    //迷宫的列数    
typedef struct
{
    int m,n;
    int arr[RANGE][RANGE];
}MazeType;   
   
bool InitMaze(MazeType &maze, int a[ROW][COL], int row, int col);//初始化迷宫
bool Pass(MazeType maze,PosType curpos);                         //判断能否通过
bool FootPrint(MazeType &maze,PosType curpos);                   //留下足迹
bool MarkPrint(MazeType &maze,PosType curpos);                   //留下不能通过的标记
PosType NextPos(PosType curpos, DirectiveType di);               //curpos当前位置
                                                                 //返回当前节点的下一节点	
bool PosEqual(PosType pos1, PosType pos2);                       //判断两节点是否相等
void PrintMaze(MazeType maze,int row,int col);
bool MazePath(MazeType &maze,PosType start, PosType end);        //求解一条路径

Maze.cpp实现如下:

#include "Stack.h"               
#include "Maze.h"    

bool InitMaze(MazeType &maze, int a[ROW][COL], int row, int col)
{
	int i,j;//设置迷宫maze的初值,包括加上边缘一圈的值
    for(i=1;i<row-1;i++)
	{
        for(j=1;j<col-1;j++)
		{
            maze.arr[i][j] = a[i][j];
        }
    }
    //加上围墙
    for(j=0;j<row;j++)
	{
        maze.arr[0][j] = maze.arr[row-1][j]=1;
    }
    for(i=0;i<col;i++)
	{
        maze.arr[i][0] = maze.arr[i][col-1]=1;
    }
    return true;
}

bool Pass(MazeType maze,PosType curpos)
{ //判断当前节点是否通过
    if(maze.arr[curpos.row][curpos.col] == 0)
	{
		return true;
	}
	else 
	{
		return false;
	}
}

bool FootPrint(MazeType &maze,PosType curpos)
{ //留下足迹
    maze.arr[curpos.row][curpos.col]=2;//走过且走得通
    return true;
}

bool MarkPrint(MazeType &maze,PosType curpos)
{//留下不能通过的标记
    maze.arr[curpos.row][curpos.col]=3;  //走过但走不通
    return true;
}

SElemType CreateSElem(int step, PosType pos, int di)
{   
    SElemType e;
    e.step = step;
    e.seat = pos;
    e.di = di;
    return e;
}

PosType NextPos(PosType curpos, DirectiveType di)//curpos当前位置
{//返回当前节点的下一节点
    PosType pos = curpos;
    switch(di)
    {
    case 1:        //右
        pos.col++;
        break;
    case 2:        //下
        pos.row++;
        break;
    case 3:        //左
        pos.col--;
        break;
    case 4:        //上
        pos.row--;
        break;
    }
    return pos;
}

bool PosEqual(PosType pos1, PosType pos2)
{//判断是不是出口
    if(pos1.row==pos2.row && pos1.col==pos2.col)
	{
		return true;
	}
	else 
	{
		return false;
	}
}

void PrintMaze(MazeType maze,int row,int col)
{//打印路径
	int i,j;
	printf("   ");
	for(i=0;i<col;i++)//打印列数名
	{
		printf("%d ",i);
	}
	printf("\n");
	for(i=0;i<row;i++)
	{
		printf("%d  ",i);//打印行数名
        for(j=0;j<col;j++)
		{
            switch(maze.arr[i][j])
			{
            case 0:
                printf("  ");//没走过,但是通路
                break;
			case 1:
                printf("# ");//障碍
                break;
            case 2:
                printf("* ");//走过且走得通
                break;
            case 3:
                printf("@ ");//走过但走不通
                break;
		    default: 
				break;
			}      
        }
		printf("\n");
    }
}

bool MazePath(MazeType &maze, PosType start, PosType end)
{ //求解迷宫maze中,从入口start到出口end的一条路径
    SqStack s; 
	SElemType e;
    InitStack(s);
    PosType curpos = start;
    int curstep = 1;                              //探索第一步
    do{
        if( Pass(maze,curpos) )
		{    //如果当前位置可以通过,即是未曾走到的通道块
            FootPrint(maze,curpos);               //留下足迹
            e = CreateSElem(curstep,curpos,1);    //创建元素
            Push(s,e);
            if( PosEqual(curpos,end) )   
			{
				return true;
			}
            curpos=NextPos(curpos,1);             //获得下一节点
            curstep++;                            //探索下一步
        }
		else{                                     //当前位置不能通过
            if(!StackEmpty(s))
			{
                Pop(s,e);
				while(e.di==4 && !StackEmpty(s) ) //找寻了四个方向
				{
                    MarkPrint(maze,e.seat);
					Pop(s,e);                     //留下不能通过的标记,并退回一步
                }
				if(e.di<4)
				{
                    e.di++;                       //换一个方向探索
					Push(s,e);            
                    curpos = NextPos(e.seat,e.di); //设定当前位置是该方向上的相邻块
                }

                
            }
        }
    }while(!StackEmpty(s));
    return false;
}


主测试函数如下:

#include "Stack.h"               
#include "Maze.h"  
         
void main()
{ 
	char cmd;//命令
	int i,j;
	PosType start,end;
	MazeType maze;
    int a[ROW][COL] = {
		{1,1,1,1,1,1,1,1,1,1},
		{1,0,1,1,1,1,1,0,0,1},
		{1,0,0,1,1,1,0,0,1,1},
		{1,1,0,0,0,0,0,0,1,1},
		{1,1,0,1,1,1,1,0,1,1},
		{1,1,0,0,1,1,1,0,1,1},
		{1,1,1,0,1,1,1,0,0,1},
		{1,1,1,0,0,1,1,1,1,1},
		{1,0,0,0,0,0,0,0,0,1},
		{1,1,1,1,1,1,1,1,1,1}
	};
	printf("\n----------原始迷宫(加外围围墙)(0 表示通路,1 表示障碍)---------\n");
	for(i=0;i<10;i++)
	{
		for(j=0;j<10;j++)
		{
			printf("%d ",a[i][j]);	
		}
		printf("\n");	
	}
    InitMaze(maze,a,ROW,COL);
	do{
		int flag=0;//是不是越界de标志。0即没越界执行下一步,1即循环再次输入
		do{
			printf("\n输入迷宫入口坐标( <0,0>到<9,9>之间 ): ");
			scanf("%d,%d",&start.row,&start.col);
			if(start.col>COL-1 || start.row>ROW-1 ||start.col<0||start.row<0)
			{
				printf("越界!");
				flag=1;
			}
			else
			{
				flag=0;
			}
		}while(flag);
		do{
			printf("输入迷宫出口坐标( <0,0>到<9,9>之间 ): ");
			scanf("%d,%d",&end.row , &end.col);
			if( end.col>COL-1 || end.row>ROW-1 ||end.col<0||end.row<0)
			{
				printf("越界!\n");
				flag=1;
			}
			else 
			{
				flag=0;
			}
		}while(flag);
		if(MazePath(maze,start,end))//找到一条路径
		{
			printf("\n---------从当前入口到出口有通路 * 组成的路径----------\n");
			PrintMaze(maze,ROW,COL);
		}
		else
		{
			printf("\n---------从入口到出口没有通路!-----\n");
		}
		printf("\n 需要继续吗?: ");
		scanf(" %c",&cmd);
	}while(cmd=='Y'||cmd=='y');
}


测试截图如下:




有什么问题请大家指出,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值