编程练习:迷宫求路

来源:互联网 发布:新疆为什么网络管制 编辑:程序博客网 时间:2024/05/18 01:30
/*=========================================================================
#    FileName: Maze.c# Description: 迷宫求路#      author: shuizhonglin#  LastChange: 2012-05-31 20:31:42=========================================================================*/#include <stdio.h>#include <stdlib.h>/* C语言没有bool类型,自己定义一个 */typedef int bool;#define TRUE  1#define FALSE 0#define OK    1#define FAIL  0#define INIT_STACK_SIZE 100  //堆栈初始大小 #define INCREASE_SIZE   10  //堆栈每次空间不足时新增的空间大小 /* 记录迷宫每个位置的信息 */typedef struct {   int x;   //横坐标    int y;   //纵坐标    int di;  //di=0表示东南西北四条路都未走过 //di=1表示要走南路,其他三路未走过//di=2表示要走西路,南路已走过且不通,其他两路未走过//di=3表示要走北路,西、南路已走过且不通,东路未走过//di=4表示要走东路,其他三路已走过且不通}SElem;/* 堆栈结构体,堆栈存储指向SElem结构体的指针 */typedef struct {   SElem **base;   SElem **top;    int stacksize;}SqStack; /* 用数组画迷宫图样 */char Maze[10][10] = {     {'#','#','#','#','#','#','#','#','#','#'},    {'#',' ',' ','#',' ',' ',' ','#',' ','#'},    {'#','#',' ',' ',' ',' ',' ','#',' ','#'},    {'#',' ',' ',' ',' ','#',' ',' ',' ','#'},    {'#',' ','#','#','#',' ',' ',' ',' ','#'},    {'#',' ','#',' ','#',' ',' ','#',' ','#'},    {' ',' ','#',' ',' ',' ','#',' ',' ','#'},    {'#',' ','#','#','#','#','#','#',' ','#'},    {'#','#',' ',' ',' ',' ',' ',' ',' ','#'},    {'#','#',' ','#','#','#','#','#','#','#'}};SElem * pMaze[10][10];  //定义100个指向SElem结构体的指针 SqStack PrintOnRoad; //记录所求路径 /* 创建并初始化100个SElem结构体,并用pMaze指针数组分别指向它们 */void InitMaze() {    int i,j;    for(i=0; i<10; ++i)        for(j=0; j<10; ++j) {            pMaze[i][j] = (SElem *)malloc( sizeof(SElem) );            pMaze[i][j]->x = i;            pMaze[i][j]->y = j;            pMaze[i][j]->di = 0;        }}/* 判断(xValue,yValue)对应的SElem的指针是否在堆栈S中 */bool IsInStack(const SqStack *S,int xValue,int yValue) {    SElem **top = S->top;    if(S->top == S->base) return FALSE;    do{        top--;        if((*top)->x == xValue && (*top)->y == yValue) return TRUE;    } while(top != S->base);    return FALSE;}/* 判断位置(x,y)是否可走 */bool OnePass(int x,int y) {    if( IsInStack( &PrintOnRoad,x,y ) ) return FALSE; //是否在PrintOnRoad堆栈中    else if (pMaze[x][y]->di == 4) return FALSE; //是否之前已走过且已知不通     else if (Maze[x][y] == '#') return FALSE; //是否是墙    else return TRUE; //可走 }/* 判断位置(x,y)四周是否有路有走 */bool Pass(int x,int y) {   if(!OnePass(x,y)) return FALSE; //(x,y)本身就不能走   pMaze[x][y]->di++;   if(x+1 <= 9)        if(OnePass(x+1,y)) return TRUE; //南路是否可走    pMaze[x][y]->di++;   if(y-1 >= 0)        if(OnePass(x,y-1)) return TRUE; //西路是否可走    pMaze[x][y]->di++;   if(x-1 >= 0)        if(OnePass(x-1,y)) return TRUE; //北路是否可走    pMaze[x][y]->di++;   if(y+1 <= 9)        if(OnePass(x,y+1)) return TRUE; //东路是不可走    return FALSE; //四周都走不通 }/* 初始化堆栈 */bool InitStack( SqStack *S) {    S->base = (SElem **)malloc(INIT_STACK_SIZE * sizeof(SElem *));    if(!S->base) return FAIL;    S->top = S->base;    S->stacksize = INIT_STACK_SIZE;    return OK;}/* 将e所指向的SElem *类型的指针入栈 */bool Push(SqStack *S, SElem **e) {    if(S->top - S->base >= S->stacksize) {        S->base = (SElem **)realloc(S->base, (S->stacksize + INCREASE_SIZE) * sizeof(SElem *));        if(!S->base) return FAIL;        S->top = S->base + S->stacksize;        S->stacksize += INCREASE_SIZE;    }    *(S->top) = *e;    S->top++;    return OK;}/* 出栈,并用e所指向的空间存放所弹出的表项 */bool Pop(SqStack *S,SElem **e) {    if(S->top == S->base) return FAIL;    S->top--;    *e = *(S->top);    return OK;}/* 判断S堆栈是否为空 */bool IsEmpty(const SqStack *S) {    if(S->top == S->base) return TRUE;    else return FALSE;}/* 判断(x,y)是否是出口,(xBegin,yBegin)是入口坐标 */bool IsTheExit(int x,int y,int xBegin,int yBegin) {    if( x == xBegin && y == yBegin) return FALSE;    if((x == 9 || x == 0 || y == 9 || y == 0) && Maze[x][y] == ' ' ) return TRUE;    else return FALSE;}/* 给定入口坐标(xBegin,yBegin),求出口坐标(*xEnd,*yEnd),并将路径存入堆栈PrintOnRoad中 */bool MazePath(int xBegin,int yBegin,int *xEnd,int *yEnd) {    InitStack( &PrintOnRoad );    InitMaze();    SElem *e = (SElem *)malloc( sizeof(SElem) );    int x = xBegin, y = yBegin;    do {/* 如果是出口则入栈并返回坐标值 */        if( IsTheExit(x,y,xBegin,yBegin) ) {            *xEnd = x;            *yEnd = y;            Push( &PrintOnRoad, &(pMaze[x][y]) );            return OK;        }/* 如果(x,y)四周有路可走 */        if( Pass(x,y) ) {/* 保存该路径 */            Push( &PrintOnRoad, &(pMaze[x][y]) );/* 判断该走哪条路 */            switch( pMaze[x][y]->di ) {                case 1 : ++x; break; //走南路                 case 2 : --y; break; //走西路                 case 3 : --x; break; //走北路                 case 4 : ++y; break; //走东路                 default: return FAIL;            }        }/* 如果(x,y)四周不通 */        else {/* 是否无路可退 */            if( !IsEmpty(&PrintOnRoad) ) {/* 向后退,退到四周还有路未走过的地方*/                Pop( &PrintOnRoad, &e );                while(e->di == 4 && !IsEmpty(&PrintOnRoad)) {                    Pop( &PrintOnRoad, &e );                }/*重新选择一条路 */                if(e->di < 4) {                    x = e->x;                    y = e->y;                    e->di++;                    switch( e->di ) {                        case 1 : ++x; break; //走南路                         case 2 : --y; break; //走西路                         case 3 : --x; break; //走北路                         case 4 : ++y; break; //走东路                         default: return FAIL;                    }/* 重新保存该路径 */                    Push( &PrintOnRoad, &e );                }            }        }    }while( !IsEmpty(&PrintOnRoad) ); //是否没有出口,或入口有误     return FAIL;}/* 打印迷宫 */void PrintMaze() {    SElem **base = PrintOnRoad.base;    int i,j;    int k = '0';/* 如果PrintOnRoad保存有路径,则用0~9,A~Z,a~...来表示路径顺序,并打印出来 */    while(base != PrintOnRoad.top) {        if(k <= '9')            Maze[(*base)->x][(*base)->y] = k;        else if(k <= 'S')            Maze[(*base)->x][(*base)->y] = k + 7;        else             Maze[(*base)->x][(*base)->y] = k + 39;        base++;        k++;    }     for(i=0; i<10; ++i) {        printf( "              " );        for(j=0; j<10; ++j) {            printf("%2c", Maze[i][j]);        }        putchar('\n');    }}int main( int argc, const char *argv[] ){    int xBegin = 6, yBegin = 0, xEnd = 0,yEnd = 0;    printf( "The maze is as follows,and we assume the entrance is at (6,0).\n\n" );    PrintMaze();    if( MazePath(xBegin,yBegin,&xEnd,&yEnd) )         printf( "\nThe exit locate at : (%d,%d), and the route is as the follows:\n\n",xEnd,yEnd);    else printf( "There is not exit at all or the entrance is wrong!\n" );    PrintMaze();return 0;}

原创粉丝点击