1. 程式人生 > >資料結構_迷宮求解

資料結構_迷宮求解

定義迷宮

#include "seqstack.h"

#define MAX_ROW 6 //最大行數
#define MAX_COL 6 //最大列數

typedef struct Maze{
    int map[MAX_ROW][MAX_COL];//定義地圖
}Maze;


void MazeInit(Maze* maze){//迷宮求解
    int map[MAX_ROW][MAX_COL]={
        { 0, 1, 0, 0, 0, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 1, 1, 1, 1, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 0, 0, 0, 1, 0, 0 },
    };
    size_t i = 0;
    for(;i<MAX_ROW;++i){
        size_t j = 0;
        for(;j<MAX_COL;++j){
            maze->map[i][j] = map[i][j];
        }
    }
}

void MazePrint(Maze* maze){//迷宮列印
    size_t i = 0;
    for(;i<MAX_ROW;++i){
        size_t j = 0;
        for(;j<MAX_COL;++j){
            printf("%2d ",maze->map[i][j]);
        }
        printf("\n");
    }
        printf("\n");
}

引用標頭檔案

#pragma once

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

#define FOR_MAZE

#ifdef FOR_MAZE
typedef struct Point{
    int row;
    int col;
}Point;

typedef Point SeqStackType;
#else
typedef char SeqStackType;
#endif

typedef struct SeqStack{
    SeqStackType* data;
    size_t size;
    size_t capacity;
}SeqStack;
void SeqStackInit(SeqStack* s);//棧初始化

void SeqStackPush(SeqStack* s,SeqStackType value);//壓棧

void SeqStackReSize(SeqStack* s);//更改大小

void SeqStackPop(SeqStack* s);//出棧

int SeqStackTop(SeqStack* s,SeqStackType* value);//取棧頂元素

void SeqStackDestroy(SeqStack* s);//銷燬

遞迴版本

//////////////////////////////////////////////////////////////////////////////////////
//              Round1 遞迴版本
/////////////////////////////////////////////////////////////////////////////////////

//是否能落腳,能返回1,不能返回0
int CanStay(Maze* maze,Point pt){
    //判斷點是否在地圖上
    if(pt.row < 0 || pt.row >= MAX_ROW || pt.col < 0 || pt.col >= MAX_COL){
        return 0;
    }
    int value = maze->map[pt.row][pt.col];
    if(value == 1){
        return 1;
    }
    return 0;
}

void Mark(Maze* maze,Point cur){
    maze->map[cur.row][cur.col] = 2;
    return;
}

int IsExit(Maze* maze,Point cur,Point entry){
    (void)maze;
    //如果當前點到了邊界,即為找到了出口,但是不能是入口點
    if(cur.row == entry.row && cur.col == entry.col){
        return  0;
    }
    if(cur.row == 0 || cur.row == MAX_ROW-1 || cur.col == 0 || cur.col == MAX_COL-1){
        return 1;
    }
    return 0;
}

void _GetPath(Maze* maze,Point cur,Point entry){
    printf("row:%d col:%d\n",cur.row,cur.col);
    //1.判斷當前點是否能落腳,不能落腳直接返回
    if(!CanStay(maze,cur)){
        return;
    }
    //2.如果能落腳,標記當前點
    Mark(maze,cur);
    //3.判斷當前點是否為出口點,是則直接return
    if(IsExit(maze,cur,entry)){
        //找到了出口直接返回
        printf("找到了一條出路\n");
        return;
    }
    //4.判斷當前點的上下左右是否有路可走,遞迴判斷
    Point up = cur;
    up.row -= 1;
    _GetPath(maze,up,entry);

    Point right = cur;
    right.col += 1;
    _GetPath(maze,right,entry);

    Point down = cur;
    down.row += 1;
    _GetPath(maze,down,entry);

    Point left = cur;
    left.col -= 1;
    _GetPath(maze,left,entry);

}

void GetPath(Maze* maze,Point entry){
    if(maze == NULL){
        return;
    }
    //使用_GetPath輔助完成遞迴
    _GetPath(maze,entry,entry);
}

非遞迴版本

//////////////////////////////////////////////////////////////////////////////////////
//                  Round2 使用非遞迴版本
/////////////////////////////////////////////////////////////////////////////////////


void GetPathByLoop(Maze* maze,Point entry){
    if(maze == NULL){
        return;
    }
    SeqStackType cur;
    //手動維護一個棧,儲存走過的路徑
    SeqStack stack;
    SeqStackInit(&stack);
    //1.先判斷是否能落腳,能落腳,當前點入棧
    if(!CanStay(maze,entry)){
        return;
    }
    SeqStackPush(&stack,entry);
    //2.如果能落腳,標記當前點
//    Mark(maze,entry);
    //迴圈取棧頂元素
    while(SeqStackTop(&stack,&cur)){
        Mark(maze,cur);
        if(IsExit(maze,cur,entry)){
        printf("找到了一條出路\n");
        return;
        }

        Point up = cur;
        up.row -= 1;
        if(CanStay(maze,up)){
//            Mark(maze,up);
            SeqStackPush(&stack,up);
            continue;
        }

        Point right = cur;
        right.col += 1;
        if(CanStay(maze,right)){
//            Mark(maze,right);
            SeqStackPush(&stack,right);
            continue;
        }

        Point down = cur;
        down.row += 1;
        if(CanStay(maze,down)){
//            Mark(maze,down);
            SeqStackPush(&stack,down);
            continue;
        }

        Point left = cur;
        left.col -= 1;
        if(CanStay(maze,left)){
//            Mark(maze,left);
            SeqStackPush(&stack,left);
            continue;
        }
        SeqStackPop(&stack);
    }
}

測試程式碼

//////////////////////////////////////////////////////////////////////////////////////
//                  以下為測試程式碼
/////////////////////////////////////////////////////////////////////////////////////

#if 1
#define TEST_HEADER printf("\n=========================%s=======================\n",__FUNCTION__)
void test(){
    TEST_HEADER;
    Maze maze;
    MazeInit(&maze);
    MazePrint(&maze);
    Point entry = {0,1};
    GetPath(&maze,entry);
    MazePrint(&maze);
}

void test2(){
    TEST_HEADER;
    Maze maze;
    MazeInit(&maze);
    MazePrint(&maze);
    Point entry = {0,1};
    GetPathByLoop(&maze,entry);
    MazePrint(&maze);

}

int main(){
    test();
    test2();
    return 0;
}
#endif