本文是对严蔚敏老师的数据结构一书中,第3.2.4一节 迷宫求解问题的实现
迷宫图如下所示
本代码用到的栈为上一篇文章中的链表栈
ElemType.h
1 #ifndef _ELEMTYPE_H_ 2 #define _ELEMTYPE_H_ 3 4 /*定义需要的数据类型,这里可以是基本数据类型,也可以是结构体数据类型, 5 结构体中最好不要使用指针,使用结构体时请包含相关头文件*/ 6 7 typedef struct{ 8 int x; //横向坐标 9 int y; //纵向坐标 10 }PosType; 11 12 typedef struct{ 13 int ord; //通道在路径上的序号 14 PosType seat; //通道在迷宫中的坐标位置 15 int di; //从此通道块走向下一通道块的方向 16 //1 表示上 2表示下 3表示左 4表示右 17 }MazePath; 18 19 typedef MazePath ElemType; 20 typedef ElemType* PElemType; 21 typedef const ElemType* PCElemType; 22 23 24 /**************************************** 25 Purpose : 打印数据 26 Input : pVal --要被打印的数据 27 Return : None 28 *****************************************/ 29 void visit(PCElemType pVal); 30 31 #endif
ElemType.c
#include <stdio.h> #include "ElemType.h" /************************************************************************* Function: visit() Purpose : 打印输出数据 Input : pVal --要被打印的数据 Return : None Modify : Remark : *************************************************************************/ void visit(PCElemType pVal) { extern char g_nMapVisit[10][10]; switch(pVal->di) { case 1: g_nMapVisit[pVal->seat.x][pVal->seat.y] ='S'; //'↑'; break; case 2: g_nMapVisit[pVal->seat.x][pVal->seat.y] ='X'; //printf(" ↓ "); break; case 3: g_nMapVisit[pVal->seat.x][pVal->seat.y] ='Z'; //printf(" ← "); break; case 4: g_nMapVisit[pVal->seat.x][pVal->seat.y] ='Y'; //printf(" → "); break; } }
MazePath.c
1 /********************************************************************* 2 *: 3 *: Filename: MazePaht.c 4 *: 5 *: Author: DongXiaolin 6 *: Copyright (c) 2012, DongXiaolin 7 *: 8 *: Created at: 2012.06.15 9 *: Last modified: 2012.06.15 10 *: 11 *: Introduction: 迷宫求解问题(栈实现) 12 *: 13 *: 14 *:*********************************************************************/ 15 #include <stdio.h> 16 #include "LinkListStack.h" 17 18 19 #define N 10 20 21 /*地图信息, 1表示 不能通过 0表示能通过 2表示已经走过 3表示试探过*/ 22 int g_nMap[][N]= 23 { 24 {1,1,1,1,1,1,1,1,1,1}, 25 {1,0,0,1,0,0,0,1,0,1}, 26 {1,0,0,1,0,0,0,1,0,1}, 27 {1,0,0,0,0,1,1,0,0,1}, 28 {1,0,1,1,1,0,0,0,0,1}, 29 {1,0,0,0,1,0,0,0,0,1}, 30 {1,0,1,0,0,0,1,0,0,1}, 31 {1,0,1,1,1,0,1,1,0,1}, 32 {1,1,0,0,0,0,0,0,0,1}, 33 {1,1,1,1,1,1,1,1,1,1}, 34 }; 35 int g_nStartX = 1; 36 int g_nStartY = 1; 37 int g_nEndX = 8; 38 int g_nEndY = 8; 39 40 char g_nMapVisit[N][N]={'0'}; 41 42 void Display(LinkListStack *pStack, int flag) 43 { 44 //system("clear"); 45 int i,j; 46 for(i=0;i<N;i++) 47 { 48 for(j=0;j<N;j++) 49 { 50 if(i == g_nStartX && j == g_nStartY) 51 { 52 //画起点 53 g_nMapVisit[i][j]= 'B'; 54 } 55 else if(i == g_nEndX && j == g_nEndY) 56 { 57 //画终点 58 g_nMapVisit[i][j] = 'E'; 59 } 60 61 else if(g_nMap[i][j] == 1) 62 { 63 g_nMapVisit[i][j] ='#'; 64 } 65 else 66 { 67 g_nMapVisit[i][j] ='O'; 68 } 69 } 70 } 71 TraverseLinkListStack(pStack, visit); 72 73 74 for(i=0;i<N;i++) 75 { 76 for(j=0;j<N;j++) 77 { 78 switch(g_nMapVisit[i][j]) 79 { 80 case 'S': printf(" ↑ "); 81 break; 82 case 'X': printf(" ↓ "); 83 break; 84 case 'Z': printf(" ← "); 85 break; 86 case 'Y': printf(" → "); 87 break; 88 default: 89 printf(" %c ", g_nMapVisit[i][j]); 90 } 91 92 } 93 printf("\n"); 94 } 95 96 getchar(); 97 } 98 99 100 101 /************************************************************************* 102 Purpose : 判断当前位置是否可通过 103 Input : pos --坐标指针 104 Return : 0 --可以通过 105 其他 --不可通过 106 Modify : 107 *************************************************************************/ 108 int Pass(PosType* pos) 109 { 110 if(pos == NULL) 111 { 112 return -1; 113 } 114 if(g_nMap[pos->x][pos->y] == 0) 115 { 116 return 0; 117 } 118 return -1; 119 } 120 121 void FootPrint(PosType* pos) 122 { 123 //表示该坐标已经走过 124 g_nMap[pos->x][pos->y] = 2; 125 } 126 127 void MarkPrint(PosType* pos) 128 { 129 //表示该坐标已试探过,且不可通过 130 g_nMap[pos->x][pos->y] = 3; 131 } 132 133 /************************************************************************* 134 Purpose : 判断是否结束 135 Input : pos --坐标指针 136 Return : 0 --结束 137 其他 --未结束 138 Modify : 139 *************************************************************************/ 140 int IsEnd(PosType* pos) 141 { 142 if(pos->x == g_nEndX && pos->y == g_nEndY) 143 { 144 return 0; 145 } 146 return -1; 147 } 148 149 /************************************************************************* 150 Purpose : 定位下一个点 151 Input : mData --结构指针 152 Return : None 153 Modify : 154 *************************************************************************/ 155 void FindNextPos(ElemType* pData) 156 { 157 switch(pData->di) 158 { 159 case 1: //该点的上方 160 pData->seat.x = pData->seat.x - 1; 161 if(pData->seat.x < 0) 162 { 163 pData->seat.x = 0; 164 } 165 break; 166 case 2: //该点的下方 167 pData->seat.x = pData->seat.x + 1; 168 if(pData->seat.x > N-1) 169 { 170 pData->seat.x = N-1; 171 } 172 break; 173 case 3: //该点的左方 174 pData->seat.y = pData->seat.y - 1; 175 if(pData->seat.y < 0) 176 { 177 pData->seat.y = 0; 178 } 179 break; 180 case 4: //该点的右方 181 pData->seat.y = pData->seat.y + 1; 182 if(pData->seat.y > N-1) 183 { 184 pData->seat.y = N-1; 185 } 186 break; 187 } 188 189 //对方向进行初始化 190 pData->di = 1; 191 pData->ord++; 192 } 193 194 //迷宫求解 195 int MazePathCalc() 196 { 197 LinkListStack mStack; 198 ElemType mData; 199 InitLinkListStack(&mStack); 200 mData.ord = 1; 201 mData.seat.x = g_nStartX; 202 mData.seat.y = g_nStartY; 203 mData.di = 1; 204 do 205 { 206 if(Pass(&(mData.seat)) == 0) //当前位置可以通过,即是未曾走过的通道 207 { 208 FootPrint(&(mData.seat)); //留下足迹 209 PushLinkListStack(&mStack, &mData); //入栈 210 printf("入栈1 [%d:%d][%d]\n",mData.seat.x,mData.seat.y,mData.di); 211 //getchar(); 212 Display(&mStack,1); 213 if(IsEnd(&(mData.seat)) == 0) //是否是终点 214 { 215 DestroyLinkListStack(&mStack); 216 return 0; 217 } 218 FindNextPos(&mData); //查找下一个点 219 } 220 else //当前位置不能通过 221 { 222 if(IsEmptyLinkListStack(&mStack) != 0) 223 { 224 PopLinkListStack(&mStack, &mData); 225 printf("出栈1 [%d:%d][%d]\n",mData.seat.x,mData.seat.y,mData.di); 226 Display(&mStack,0); 227 while(mData.di == 4&& IsEmptyLinkListStack(&mStack) != 0) 228 { 229 MarkPrint(&(mData.seat)); 230 PopLinkListStack(&mStack, &mData); 231 printf("出栈2 [%d:%d][%d]\n",mData.seat.x,mData.seat.y,mData.di); 232 Display(&mStack,0); 233 } 234 if(mData.di < 4) 235 { 236 mData.di++; 237 PushLinkListStack(&mStack, &mData); //换下一个方向 238 printf("入栈2 [%d:%d][%d]\n",mData.seat.x,mData.seat.y,mData.di); 239 Display(&mStack,1); 240 FindNextPos(&mData); 241 } 242 } 243 } 244 }while(IsEmptyLinkListStack(&mStack) != 0); 245 DestroyLinkListStack(&mStack); 246 return -1; 247 } 248 249 int main(int argc, char* argv[]) 250 { 251 if(MazePathCalc()) 252 { 253 printf("失败,未找到出口\n"); 254 return 1; 255 } 256 257 printf("成功,已找到出口\n"); 258 return 0; 259 }
上述程序,清晰的演示了迷宫求解的每一个步骤,效果如下
。。。。。
本程序按照上下左右的顺序来找路径,4个方向的先后顺序不同,则找到的路径亦不相同。