#include <stdio.h>
//#define DEBUG 1
#include "../lib/debug.h"
#define OK (0)
#define NOK (-1)
#define MAZE_SIZE 4
enum Tagderection
{
RIGHT = 0,
DOWN,
LEFT,
UP,
END
};
typedef struct TagPosition
{
int x;
int y;
/* 当前位置是上个位置往哪个方向走得到的,回溯的时候取下个方向 */
int dire;
}Position;
typedef struct TagMazePath
{
Position pos[MAZE_SIZE*MAZE_SIZE]; /* 迷宫最长路径为 MAZE_SIZE*MAZE_SIZE */
int top;
}MazePath;
/* 初始化迷宫,1表示可以走,0表示不能走 */
void MazeInit(int maze[][MAZE_SIZE])
{
int i,j;
for(i = 0; i < MAZE_SIZE; i++)
for (j = 0; j < MAZE_SIZE; j++)
maze[i][j] = 0;
for(i = 0; i < MAZE_SIZE ; i++)
maze[0][i] = 1;
for(i = 0; i < MAZE_SIZE ; i++)
maze[i][MAZE_SIZE-1] = 1;
for(i = 0; i < MAZE_SIZE; i++)
maze[i][0] = 1;
for(i = 0; i < MAZE_SIZE; i++)
maze[MAZE_SIZE-1][i] = 1;
return ;
}
/*************************************************
打印出迷宫的出路
*************************************************/
void MazeDisplayPath(MazePath my_path)
{
int i;
for(i = 0; i <= my_path.top ; i++)
{
printf("%d,%d ",my_path.pos[i].x,my_path.pos[i].y);
}
printf("\n");
}
/*************************************************
打印出迷宫,X表示可以走,0表示不能走
*************************************************/
int MazeDisplay(int maze[][MAZE_SIZE])
{
int i,j;
for(i = 0; i < MAZE_SIZE; i++)
for (j = 0; j < MAZE_SIZE; j++)
{
if(1 == maze[i][j])
printf("X");
else
printf("0");
if((MAZE_SIZE-1) == j)
printf("\n");
}
return ;
}
/*************************************************
迷宫入口入栈
*************************************************/
void MazePathInit(MazePath *my_path)
{
my_path->top = 0;
my_path->pos[0].x = 0;
my_path->pos[0].y = 0;
my_path->pos[0].dire = UP;
}
/*************************************************
判断栈是否为空,为空返回OK,否则返回NOK
*************************************************/
int PathEmpty(MazePath my_path)
{
if(my_path.top >= 0)
return NOK;
else
return OK;
}
/*************************************************
是否找到迷宫出口,找到则返回OK,否则返回NOK
*************************************************/
int MazeFoundWay(MazePath my_path)
{
if(my_path.pos[my_path.top].x != (MAZE_SIZE-1) || my_path.pos[my_path.top].y != (MAZE_SIZE-1))
return NOK;
else
return OK;
}
/*************************************************
判断移动是否合法,合法返回OK,否则返回NOK
*************************************************/
int MoveValid(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath my_path,int move_diretion)
{
int cur_x,cur_y,next_x,next_y;
cur_x = my_path.pos[my_path.top].x;
cur_y = my_path.pos[my_path.top].y;
switch(move_diretion)
{
case RIGHT:
next_x = cur_x;
next_y = cur_y + 1;
break;
case DOWN:
next_x = cur_x + 1;
next_y = cur_y;
break;
case LEFT:
next_x = cur_x;
next_y = cur_y - 1;
break;
case UP:
next_x = cur_x - 1;
next_y = cur_y;
break;
default:
return NOK;
}
if(next_x < 0 || next_x >= MAZE_SIZE || next_y < 0 || next_y >= MAZE_SIZE)
{
DB("Meet the wall");
return NOK;
}
if(1 == mark[next_x][next_y])
{
DB("Already passes this position");
return NOK;
}
if(0 == maze[next_x][next_y])
{
DB("This position is not way");
return NOK;
}
return OK;
}
/*************************************************
向选定的方向前进一步
*************************************************/
void MoveForward(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath *my_path,int move_diretion)
{
int cur_x,cur_y,next_x,next_y;
cur_x = my_path->pos[my_path->top].x;
cur_y = my_path->pos[my_path->top].y;
switch(move_diretion)
{
case RIGHT:
next_x = cur_x;
next_y = cur_y + 1;
break;
case DOWN:
next_x = cur_x + 1;
next_y = cur_y;
break;
case LEFT:
next_x = cur_x;
next_y = cur_y - 1;
break;
case UP:
next_x = cur_x - 1;
next_y = cur_y;
break;
default:
exit(1);
}
mark[next_x][next_y] = 1;
my_path->top ++;
my_path->pos[my_path->top].x = next_x;
my_path->pos[my_path->top].y = next_y;
my_path->pos[my_path->top].dire = move_diretion;
return ;
}
/*************************************************
回退到上个位置继续查找路径
*************************************************/
void MoveBack(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath *my_path)
{
int cur_x,cur_y;
cur_x = my_path->pos[my_path->top].x;
cur_y = my_path->pos[my_path->top].y;
mark[cur_x][cur_y] = 0;
my_path->top --;
}
/*************************************************
迷宫问题解法函数,采用回溯算法
*************************************************/
void MazeFindWayOut(int maze[][MAZE_SIZE])
{
int i,j;
int move_diretion;
int diretion_start = RIGHT;
MazePath my_path;
int mark[MAZE_SIZE][MAZE_SIZE] = {0}; /* 标记该位置是否到过 */
MazePathInit(&my_path); /* 迷宫入口入栈 */
mark[0][0] = 1;
while(OK != PathEmpty(my_path))
{
if( OK == MazeFoundWay(my_path))
{
DB("Find way out");
MazeDisplayPath(my_path);
#if 0
/* 如果是只要找到一条路径,那么在这里退出 */
return;
#else
diretion_start = my_path.pos[my_path.top].dire + 1;
DB("back");
MoveBack(maze,mark,&my_path);
continue;
#endif
}
for(move_diretion = diretion_start ; move_diretion < END ; move_diretion++)
{
if(OK == MoveValid(maze,mark,my_path,move_diretion))
{
MoveForward(maze,mark,&my_path,move_diretion);
break;
}
}
/* 死路,回溯 */
if(END == move_diretion)
{
/* 本位置是从上个位置的哪个方向移动得到 */
/* 回溯后则从上个位置的下个方向开始移动 */
diretion_start = my_path.pos[my_path.top].dire + 1;
DB("back");
MoveBack(maze,mark,&my_path);
}
else
{
diretion_start = RIGHT;
}
}
}
int main(int argc, char **argv)
{
int maze[MAZE_SIZE][MAZE_SIZE];
MazeInit(maze);
MazeDisplay(maze);
MazeFindWayOut(maze);
return;
}
//#define DEBUG 1
#include "../lib/debug.h"
#define OK (0)
#define NOK (-1)
#define MAZE_SIZE 4
enum Tagderection
{
RIGHT = 0,
DOWN,
LEFT,
UP,
END
};
typedef struct TagPosition
{
int x;
int y;
/* 当前位置是上个位置往哪个方向走得到的,回溯的时候取下个方向 */
int dire;
}Position;
typedef struct TagMazePath
{
Position pos[MAZE_SIZE*MAZE_SIZE]; /* 迷宫最长路径为 MAZE_SIZE*MAZE_SIZE */
int top;
}MazePath;
/* 初始化迷宫,1表示可以走,0表示不能走 */
void MazeInit(int maze[][MAZE_SIZE])
{
int i,j;
for(i = 0; i < MAZE_SIZE; i++)
for (j = 0; j < MAZE_SIZE; j++)
maze[i][j] = 0;
for(i = 0; i < MAZE_SIZE ; i++)
maze[0][i] = 1;
for(i = 0; i < MAZE_SIZE ; i++)
maze[i][MAZE_SIZE-1] = 1;
for(i = 0; i < MAZE_SIZE; i++)
maze[i][0] = 1;
for(i = 0; i < MAZE_SIZE; i++)
maze[MAZE_SIZE-1][i] = 1;
return ;
}
/*************************************************
打印出迷宫的出路
*************************************************/
void MazeDisplayPath(MazePath my_path)
{
int i;
for(i = 0; i <= my_path.top ; i++)
{
printf("%d,%d ",my_path.pos[i].x,my_path.pos[i].y);
}
printf("\n");
}
/*************************************************
打印出迷宫,X表示可以走,0表示不能走
*************************************************/
int MazeDisplay(int maze[][MAZE_SIZE])
{
int i,j;
for(i = 0; i < MAZE_SIZE; i++)
for (j = 0; j < MAZE_SIZE; j++)
{
if(1 == maze[i][j])
printf("X");
else
printf("0");
if((MAZE_SIZE-1) == j)
printf("\n");
}
return ;
}
/*************************************************
迷宫入口入栈
*************************************************/
void MazePathInit(MazePath *my_path)
{
my_path->top = 0;
my_path->pos[0].x = 0;
my_path->pos[0].y = 0;
my_path->pos[0].dire = UP;
}
/*************************************************
判断栈是否为空,为空返回OK,否则返回NOK
*************************************************/
int PathEmpty(MazePath my_path)
{
if(my_path.top >= 0)
return NOK;
else
return OK;
}
/*************************************************
是否找到迷宫出口,找到则返回OK,否则返回NOK
*************************************************/
int MazeFoundWay(MazePath my_path)
{
if(my_path.pos[my_path.top].x != (MAZE_SIZE-1) || my_path.pos[my_path.top].y != (MAZE_SIZE-1))
return NOK;
else
return OK;
}
/*************************************************
判断移动是否合法,合法返回OK,否则返回NOK
*************************************************/
int MoveValid(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath my_path,int move_diretion)
{
int cur_x,cur_y,next_x,next_y;
cur_x = my_path.pos[my_path.top].x;
cur_y = my_path.pos[my_path.top].y;
switch(move_diretion)
{
case RIGHT:
next_x = cur_x;
next_y = cur_y + 1;
break;
case DOWN:
next_x = cur_x + 1;
next_y = cur_y;
break;
case LEFT:
next_x = cur_x;
next_y = cur_y - 1;
break;
case UP:
next_x = cur_x - 1;
next_y = cur_y;
break;
default:
return NOK;
}
if(next_x < 0 || next_x >= MAZE_SIZE || next_y < 0 || next_y >= MAZE_SIZE)
{
DB("Meet the wall");
return NOK;
}
if(1 == mark[next_x][next_y])
{
DB("Already passes this position");
return NOK;
}
if(0 == maze[next_x][next_y])
{
DB("This position is not way");
return NOK;
}
return OK;
}
/*************************************************
向选定的方向前进一步
*************************************************/
void MoveForward(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath *my_path,int move_diretion)
{
int cur_x,cur_y,next_x,next_y;
cur_x = my_path->pos[my_path->top].x;
cur_y = my_path->pos[my_path->top].y;
switch(move_diretion)
{
case RIGHT:
next_x = cur_x;
next_y = cur_y + 1;
break;
case DOWN:
next_x = cur_x + 1;
next_y = cur_y;
break;
case LEFT:
next_x = cur_x;
next_y = cur_y - 1;
break;
case UP:
next_x = cur_x - 1;
next_y = cur_y;
break;
default:
exit(1);
}
mark[next_x][next_y] = 1;
my_path->top ++;
my_path->pos[my_path->top].x = next_x;
my_path->pos[my_path->top].y = next_y;
my_path->pos[my_path->top].dire = move_diretion;
return ;
}
/*************************************************
回退到上个位置继续查找路径
*************************************************/
void MoveBack(int maze[][MAZE_SIZE],int mark[][MAZE_SIZE],MazePath *my_path)
{
int cur_x,cur_y;
cur_x = my_path->pos[my_path->top].x;
cur_y = my_path->pos[my_path->top].y;
mark[cur_x][cur_y] = 0;
my_path->top --;
}
/*************************************************
迷宫问题解法函数,采用回溯算法
*************************************************/
void MazeFindWayOut(int maze[][MAZE_SIZE])
{
int i,j;
int move_diretion;
int diretion_start = RIGHT;
MazePath my_path;
int mark[MAZE_SIZE][MAZE_SIZE] = {0}; /* 标记该位置是否到过 */
MazePathInit(&my_path); /* 迷宫入口入栈 */
mark[0][0] = 1;
while(OK != PathEmpty(my_path))
{
if( OK == MazeFoundWay(my_path))
{
DB("Find way out");
MazeDisplayPath(my_path);
#if 0
/* 如果是只要找到一条路径,那么在这里退出 */
return;
#else
diretion_start = my_path.pos[my_path.top].dire + 1;
DB("back");
MoveBack(maze,mark,&my_path);
continue;
#endif
}
for(move_diretion = diretion_start ; move_diretion < END ; move_diretion++)
{
if(OK == MoveValid(maze,mark,my_path,move_diretion))
{
MoveForward(maze,mark,&my_path,move_diretion);
break;
}
}
/* 死路,回溯 */
if(END == move_diretion)
{
/* 本位置是从上个位置的哪个方向移动得到 */
/* 回溯后则从上个位置的下个方向开始移动 */
diretion_start = my_path.pos[my_path.top].dire + 1;
DB("back");
MoveBack(maze,mark,&my_path);
}
else
{
diretion_start = RIGHT;
}
}
}
int main(int argc, char **argv)
{
int maze[MAZE_SIZE][MAZE_SIZE];
MazeInit(maze);
MazeDisplay(maze);
MazeFindWayOut(maze);
return;
}