递归求解迷宫问题
????????相信大家伙看見過很多有關迷宮問題的文章了,但是許多文章的迷宮查找方向是上下左右。今天,小編就給大家伙來點不一樣的,咱使用八個方向來查找迷宮的通路,即上、上右、右、右下、下、下左、左、左上這八個方向。下面就讓小編給大家一一講解吧。
一、問題描述:以一個m*n的長方陣表示迷宮,0和1分別表示迷宮中的通路和障礙。迷宮問題要求求出從入口(1,1)到出口(m,n)的通路,或得出沒有通路的結論。每次查找到迷宮通路后我們都會有鏈式輸出與方陣輸出兩種選擇。
二、模塊設計:(1)迷宮建立模塊,用來建立迷宮;(2)棧模塊,包含棧的初始化、出棧、入棧與free棧函數,用于棧的相關操作;(3)迷宮查找模塊,是主要函數,用來查找迷宮的通路;(4)迷宮輸出模塊,包含迷宮的鏈式輸出與迷宮的方陣輸出。
三、主要函數算法剖析:(1)判斷是否到達迷宮的終點,如到達迷宮的終點就選擇自己喜歡的形式輸出,否則就按照定義的八個方向一次查找;
(2)先確定下一次的查找方向,再判斷本次所在位置是否能夠通過、是否符合迷宮規定,如不通過就換個方向查找,否則就執行下面程序;
(3)將本次所在位置標記1,表示已經查找過了,再將本次位置入棧,然后再次調用迷宮查找函數;
(4)待再次調用查找函數結束后,就將上次標記過的位置重新標記為0,后再出棧。
四、項目文件:
(1)labyrinth.h文件
#include<stdio.h> #include<stdlib.h>//定義迷宮的最大的大小 #define max_x 1000 #define max_y 1000 int flag;//用來記錄迷宮擁有的路徑 int m,n;//用來表示迷宮的行與列 struct int_slink_stack *re;//用來儲存迷宮出路的棧struct int_slink_stack//棧的定義 { struct int_slink_stack_node *top;int count; }; struct int_slink_stack_node//棧內元素的定義 { int i;//本次行位置int j;//本次列位置struct int_slink_stack_node *next; };struct int_slink_stack *int_slink_stack_init();//棧的初始化void int_slink_stack_free(struct int_slink_stack *s);//free棧void int_slink_stack_push(struct int_slink_stack *s, int i,int j);//入棧函數struct int_slink_stack_node* int_slink_stack_pop(struct int_slink_stack *s);//出棧函數void output();//棧的鏈式輸出void search(int hang, int lie);//迷宮路徑的查找函數void found();//迷宮的建立并且輸出函數void map();//迷宮通路的圖形輸出void xuanze();//選擇迷宮路徑的輸出形式(2)main.c文件
#include"labyrinth.h"extern int a1[max_x][max_y];//定義一個儲存迷宮路徑的二維數組 extern int a[max_x][max_y];//定義一個儲存迷宮的二維數組void main() {re = int_slink_stack_init();//定義迷宮路徑儲存棧//輸入實際迷宮的大小printf("請輸入迷宮行(m)列(n)大小:\n");scanf("%d %d",&m,&n);//判斷輸入是否合理if(m > max_x || n > max_y || m < 1 || n < 1){//不合理printf("輸入錯誤!\n");}else{//合理found();//建立迷宮,初始化迷宮//分別判斷(1,2)、(2,1)、(2,2)和(m-1,n)(m,n-1)(m-1,n-1)是否為1if((a[1][2]==1 && a[2][1]==1 && a[2][2])==1 || (a[m-1][n]==1 && a[m][n-1]==1 && a[m-1][n-1]==1)){flag = 0;//都為1表示直接找不到迷宮的通路}else{//否則就先將迷宮的起點標記為1,再查找迷宮的通路a1[1][1]=1; search(1,1);}//判斷迷宮是否有通路if(flag == 0){//沒有通路printf("本迷宮沒有從起點到終點的路!\n");}else{//有通路printf("該迷宮一共有 %d 條路\n",flag);}}int_slink_stack_free(re);//free棧 }(3)labyrinth.c文件
#include"labyrinth.h" #include<stdlib.h> #include<time.h>int a[max_x][max_y];//定義一個儲存迷宮的二維數組 int a1[max_x][max_y] = {0};//定義一個儲存迷宮路徑的二維數組 int yidong1[8][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};//迷宮查找的八個方向 int biao = 0;//用來輔助迷宮路徑的輸出,0表示可以自由輸入選擇struct int_slink_stack *int_slink_stack_init() {//棧的初始化函數struct int_slink_stack *s=NULL;s=(struct int_slink_stack *)malloc(sizeof(struct int_slink_stack)); s->top = NULL;s->count = 0;return(s) ; }void int_slink_stack_free(struct int_slink_stack *s) {//free棧函數 struct int_slink_stack_node *p;while(s->top){p = s->top;s->top = p->next;free(p);s->count--;}free(s); }void int_slink_stack_push(struct int_slink_stack *s, int i,int j) {//入棧函數 struct int_slink_stack_node *p;p=(struct int_slink_stack_node *)malloc(sizeof(struct int_slink_stack_node));p->i = i;p->j = j;p->next = s->top;s->top = p;s->count++; }struct int_slink_stack_node* int_slink_stack_pop(struct int_slink_stack *s) { //出棧函數 struct int_slink_stack_node *p = NULL;p = s->top;s->top = p->next;s->count--;return p; }void output() {//迷宮路徑的鏈式二元組輸出int count = re->count;struct int_slink_stack_node *q= re->top;printf("迷宮的鏈式輸出如下:\n");while(count > 0){int i = 0;struct int_slink_stack_node *p = q;while(i < count -1){p = p->next;i++;}printf("(%d %d)->",p->i,p->j);count--;}printf("終點\n"); }void xuanze() {//選擇迷宮路徑的輸出方式int mn;printf("\n已找到第 %d 條迷宮的出路:",flag);//判斷是否需要輸入選擇if(biao == 0){//需要選擇printf("迷宮通路表示方法有以下幾種:\n");printf(" 1:本次迷宮通路鏈式表示. \n");printf(" 2:本次迷宮通路圖形表示. \n");printf(" 3:迷宮通路就以圖形表示. \n");printf(" 其他:迷宮通路就以鏈式表示. \n");printf("請輸入您的選擇:");scanf("%d",&mn);}else{//不需要選擇mn = biao;}switch(mn){case 1: output();biao = 0;//本次迷宮路徑鏈式輸出break;case 2: map();biao = 0;//本次迷宮路徑圖形輸出break;case 3: map();biao = 3;//迷宮路徑一直以圖形輸出break;default: output();biao = 5;//迷宮路徑一直以鏈式輸出} }void found() {//建立迷宮并且輸出函數int i,j;srand((unsigned int)time(0));//定義隨機數種子//建立迷宮的墻for(i=0;i<=m+1;i++){a[i][0]=2;a[i][n+1]=2;a1[i][0]=2;a1[i][n+1]=2;}for(i=0;i<=n+1;i++){a[0][i]=2;a[m+1][i]=2;a1[0][i]=2;a1[m+1][i]=2;}//建立實際迷宮for(i=1;i<=m;i++){for(j=1;j<=n;j++){a[i][j] = rand()%2;}}//將迷宮的起點與終點強制置0a[1][1] = 0;a[m][n] = 0;//輸出隨機生成的迷宮printf("隨機生成的迷宮為(2代表迷宮邊界):\n");for(i=0;i<m+2;i++){for(j=0;j<n+2;j++){printf("%d ",a[i][j]);}printf("\n");} }void map() {//迷宮的圖形輸出int i,j;int count = re->count;//獲取棧內元素的個數大小struct int_slink_stack_node *q= re->top;//獲取棧內元素的棧頂指針a1[m][n] = 1;//強制將迷宮終點置1//圖形輸出迷宮printf("迷宮的通路地圖如下(0表示墻,1代表通路,2代表邊界):\n");for(i = 0;i < m+2;i++){for(j = 0;j < n+2;j++){printf("%d ",a1[i][j]);}printf("\n");}//圖形輸出迷宮路徑后還需要出棧while(count > 0){q = q->next;count--;} }void search(int hang, int lie) {//迷宮通路查找函數int i,x,y;//判斷是否到達迷宮的終點if(hang==m && lie==n ){//到達迷宮終點直接輸出flag += 1;xuanze();return ;}else{//未到達迷宮終點繼續查找for(i=0;i<8;i++){//按照定義的八個方向一次查找//求得下一次查找的位置x=hang + yidong1[i][0];y=lie + yidong1[i][1];//判斷下一次查找是否為0,是否在合理的范圍內if(a1[x][y]||a[x][y]||x<1||y<1||x > m||y > n) continue;//下一次查找不符合要求就再次查找//復合查找要求a1[x][y]=1;//將本次所在位置標記1,表示已經查找過了int_slink_stack_push(re,hang,lie);//將本次位置入棧search(x,y);//查找下一次位置a1[x][y]=0;//將本次所在位置標記0,表示未查找int_slink_stack_pop(re);//出棧}} }五、程序執行結果:
待輸入選擇:
選項1:
選項2:
(注:至于其他的兩個選項其實就是對于選項1、選項2的另外一種選擇形式。)
相信大家看了我的文章或多或或少有一些關于迷宮問題求解的思路。小編第一次寫文章,倘若有啥不妥之處歡迎大家留言。若大家在看完之后有什么疑惑,也歡迎大家留言。
總結
- 上一篇: 日志无法打印问题总结
- 下一篇: 题目0.0