1. 程式人生 > >資料結構---迷宮問題題解(C語言)

資料結構---迷宮問題題解(C語言)

資料結構—迷宮問題題解(C語言)

#include<stdio.h>
#include<stdlib.h>
#define FALSE 0
#define TRUE  1
#define OK    1 
#define M     20
#define N     20
typedef struct mark //定義迷宮內點的座標
{
    int x;
    int y;
}Mark;
struct Element //資料域 
{
    int x,y; //x行,y列
    int d; //下一步的方向
};
typedef struct LStack //鏈棧
{
    Element elem;
    struct LStack *next;
}*PLStack;
/*************棧函式****************/
int InitStack(PLStack &S)//構造空棧
{
    S=NULL;
    return OK;
}
int StackEmpty(PLStack S)//判斷棧是否為空
{
    if(S==NULL)
        return OK;
    else
        return FALSE;
}
int Push(PLStack &S, Element e)//元素入棧
{
    PLStack p;
    p=(PLStack)malloc(sizeof(LStack));
    p->elem=e;
    p->next=S;
    S=p;
    return OK;
}
int Pop(PLStack &S,Element &e) //元素出棧 
{
    PLStack p;
    if(!StackEmpty(S))
    {
        e=S->elem;
        p=S;
        S=S->next;
        free(p);
        return OK;
    }
    else
        return FALSE;
}


/*************建立迷宮*******************/
void initmaze(int maze[M][N])
{
    int m,n; //迷宮行,列 
    printf("請輸入迷宮的行數 m=");
    scanf("%d",&m);
    printf("請輸入迷宮的列數 n=");
    scanf("%d",&n);
    printf("\n請輸入迷宮的各行各列:\n用空格隔開,0代表路,1代表牆\n",m,n);

    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&maze[i][j]);
    printf("建立的迷宮為(最外圈為牆)\n");     //列印迷宮 
    for(int i=0;i<=m+1;i++) //加一圈圍牆
    {
        maze[i][0]=1;
        maze[i][n+1]=1;
    }
    for(int j=0;j<=n+1;j++)
    {
        maze[0][j]=1;
        maze[m+1][j]=1;
    }
    
     for(int i=0;i<=m+1;i++) //輸出迷宮
    {
        for(int j=0;j<=n+1;j++)
            printf("%d ",maze[i][j]);
        printf("\n");
    }

}



/*************求迷宮路徑函式*************/
void MazePath(struct mark start,struct mark end,int maze[M][N],int diradd[4][2])
{
    int i,j,d;
	int a,b;
    Element elem,e;
    PLStack S1,S2;
    InitStack(S1);
    InitStack(S2);
    maze[start.x][start.y]=2; //入口點作上標記
    elem.x=start.x;
    elem.y=start.y;
    elem.d=0; //開始為0   ,東 1;南 2;西3 ;北 4 
    Push(S1,elem);
    while(!StackEmpty(S1)) //棧不為空 有路徑可走
    {
        Pop(S1,elem);
        i=elem.x;
        j=elem.y;
        d=elem.d+1; //下一個方向
        while(d<=4) //試探南西北各個方向
        {
            a=i+diradd[d-1][0];
            b=j+diradd[d-1][1];
            if(a==end.x && b==end.y && maze[a][b]==0) //找到出口 
            {
                elem.x=i;
                elem.y=j;
                elem.d=d;
                Push(S1,elem);
                elem.x=a;
                elem.y=b;
                elem.d=6; //方向輸出為-1 判斷是否到了出口
                Push(S1,elem);
                printf("\n1=東 2=南 3=西 4=北 6為則走出迷宮\n\n通路為:(行座標,列座標,方向)\n");
                while(S1) //逆置路徑序列 
                {
                    Pop(S1,e);
                    Push(S2,e);
                }
                while(S2) //出棧列印 
                {
                    Pop(S2,e);
                    printf("->(%d,%d,%d)",e.x,e.y,e.d);
                }
                return; //跳出兩層迴圈,本來用break,但發現出錯,exit又會結束程式,選用return還是不錯滴
            }
            if(maze[a][b]==0) //找到可以前進的非出口的點
            {
                maze[a][b]=2; //標記走過此點
                elem.x=i;
                elem.y=j;
                elem.d=d;
                Push(S1,elem); //當前位置入棧
                i=a;           //下一點轉化為當前點
                j=b;
                d=0;
            }
            d++;
        }
    }
    printf("沒有找到可以走出此迷宮的路徑\n");
}

int main(){
    int mg[M][N];
    Mark start,end; //start,end入口和出口的座標
    int add[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//行增量和列增量 方向依次為東南西北 
    initmaze(mg);//建立迷宮
    printf("輸入入口的橫座標,縱座標[逗號隔開]\n");
    scanf("%d,%d",&start.x,&start.y);
    printf("輸入出口的橫座標,縱座標[逗號隔開]\n");
    scanf("%d,%d",&end.x,&end.y);
    MazePath(start,end,mg,add); //find path
	
	return 0;
}