#include <stdio.h>
#define MAX 5
int maze[MAX][MAX]={
{0,0,1,0,0},
{0,0,0,0,1},
{0,0,0,1,1},
{0,0,0,0,1},
{0,0,1,0,0}
};
int inThePath[MAX][MAX];//to indicate wether (x,y) is in the current path, an overhead to enhance efficency
typedef enum Orientation{
UNKNOWDIRECTION,EAST,SOUTH,WEST,NORTH,NODIRECTION
}Orientation;
/*StepRecord is the path node record type*/
struct StepRecord{
int x,y;//the position
Orientation direction;//the last outgoing direction
};
struct StepRecord path[MAX*MAX];//should initilize to 0
int top = -1;
void push(struct StepRecord rec)
{
path[++top] = rec;
}
struct StepRecord pop()
{
return path[top--];
}
int isStackEmpty()
{
return top == -1;
}
/*always point to the current position*/
struct StepRecord *current;
/**
*return true if pos is not int current path. the function is used to avoid infinite loop.
*/
int inPath(struct StepRecord* pos)
{
return inThePath[pos->x][pos->y];
}
/**
* return true if pos is inside the maze;
*/
int inMaze(struct StepRecord* pos)
{
return (pos->x < MAX) && (pos->y < MAX) && (pos->x >= 0) && (pos->y >= 0);
}
/**
* test maze matrix,return true if pos is blocked.
* pos->y means which row, pos->x means which column
*/
int isNotBlocked(struct StepRecord* pos)
{
return maze[pos->y][pos->x] == 0;
}
/**
*test if direction of current is walkable, which means the next position indicated by direct
*is inside the maze matrix and not in the current path (to avoid infinite loop).
*/
int testForDirection(Orientation direct)
{
struct StepRecord tmp = *current;
switch(direct){
case EAST:
tmp.x += 1;
break;
case SOUTH:
tmp.y += 1;
break;
case WEST:
tmp.x -= 1;
break;
case NORTH:
tmp.y -= 1;
break;
default:
break;
}
if(!inPath(&tmp) && inMaze(&tmp) && isNotBlocked(&tmp))
return 1;
return 0;
}
/**
*continues to test from the next direction from last direction to NODIRECTION,return the next walkable direction of current position
*/
Orientation nextWalkableDirection()
{
Orientation direct;
for(direct = (Orientation)(current->direction + 1); direct < NODIRECTION; direct = (Orientation)(direct + 1))
{
if(testForDirection(direct)){
return direct;
}
}
return direct;
}
/**
*advance to next walkable postion,always call nextWalkableDirection to return a valid direction
*and pass it to this function as direction
*/
void advanceByDirection(Orientation direction)
{
struct StepRecord nextPos = *current;
nextPos.direction = UNKNOWDIRECTION;
if(direction == EAST){
nextPos.x += 1;
}else if(direction == SOUTH){
nextPos.y += 1;
}else if(direction == WEST){
nextPos.x -= 1;
}else{
nextPos.y -= 1;
}
current->direction = direction;
push(nextPos);
printf("(%d,%d,%d) pushed\n",nextPos.x,nextPos.y,nextPos.direction);
inThePath[nextPos.x][nextPos.y] = 1;
current ++;
}
/**
*return true if a position is equal to b position;
*/
int equal(struct StepRecord* a,struct StepRecord* b)
{
return ((a->x == b->x) && (a->y == b->y));
}
/**
* print out the successful path
*/
void printPath()
{
for(int i = 0; i <= top; i++)
printf("(%d,%d)\n",path[i].x,path[i].y);
}
/**
* return back to previous position
*/
void stepBack()
{
struct StepRecord tmp = pop();
printf("(%d,%d,%d) poped\n",tmp.x,tmp.y,tmp.direction);
inThePath[tmp.x][tmp.y] = 0;
current--;
}
int main(void)
{
struct StepRecord start = {0,0,UNKNOWDIRECTION};
// struct StepRecord sentinel = start;
struct StepRecord final = {4,4,UNKNOWDIRECTION};
Orientation direction;
// push(sentinel);
push(start);
current = path;
while(!equal(current,&final) && !isStackEmpty())
{
direction = nextWalkableDirection();
if(direction == NODIRECTION){
stepBack();
}else{
advanceByDirection(direction);
}
}
if(isStackEmpty()){
printf("no path to the end");
return 0;
}
printPath();
return 0;
}
#define MAX 5
int maze[MAX][MAX]={
{0,0,1,0,0},
{0,0,0,0,1},
{0,0,0,1,1},
{0,0,0,0,1},
{0,0,1,0,0}
};
int inThePath[MAX][MAX];//to indicate wether (x,y) is in the current path, an overhead to enhance efficency
typedef enum Orientation{
UNKNOWDIRECTION,EAST,SOUTH,WEST,NORTH,NODIRECTION
}Orientation;
/*StepRecord is the path node record type*/
struct StepRecord{
int x,y;//the position
Orientation direction;//the last outgoing direction
};
struct StepRecord path[MAX*MAX];//should initilize to 0
int top = -1;
void push(struct StepRecord rec)
{
path[++top] = rec;
}
struct StepRecord pop()
{
return path[top--];
}
int isStackEmpty()
{
return top == -1;
}
/*always point to the current position*/
struct StepRecord *current;
/**
*return true if pos is not int current path. the function is used to avoid infinite loop.
*/
int inPath(struct StepRecord* pos)
{
return inThePath[pos->x][pos->y];
}
/**
* return true if pos is inside the maze;
*/
int inMaze(struct StepRecord* pos)
{
return (pos->x < MAX) && (pos->y < MAX) && (pos->x >= 0) && (pos->y >= 0);
}
/**
* test maze matrix,return true if pos is blocked.
* pos->y means which row, pos->x means which column
*/
int isNotBlocked(struct StepRecord* pos)
{
return maze[pos->y][pos->x] == 0;
}
/**
*test if direction of current is walkable, which means the next position indicated by direct
*is inside the maze matrix and not in the current path (to avoid infinite loop).
*/
int testForDirection(Orientation direct)
{
struct StepRecord tmp = *current;
switch(direct){
case EAST:
tmp.x += 1;
break;
case SOUTH:
tmp.y += 1;
break;
case WEST:
tmp.x -= 1;
break;
case NORTH:
tmp.y -= 1;
break;
default:
break;
}
if(!inPath(&tmp) && inMaze(&tmp) && isNotBlocked(&tmp))
return 1;
return 0;
}
/**
*continues to test from the next direction from last direction to NODIRECTION,return the next walkable direction of current position
*/
Orientation nextWalkableDirection()
{
Orientation direct;
for(direct = (Orientation)(current->direction + 1); direct < NODIRECTION; direct = (Orientation)(direct + 1))
{
if(testForDirection(direct)){
return direct;
}
}
return direct;
}
/**
*advance to next walkable postion,always call nextWalkableDirection to return a valid direction
*and pass it to this function as direction
*/
void advanceByDirection(Orientation direction)
{
struct StepRecord nextPos = *current;
nextPos.direction = UNKNOWDIRECTION;
if(direction == EAST){
nextPos.x += 1;
}else if(direction == SOUTH){
nextPos.y += 1;
}else if(direction == WEST){
nextPos.x -= 1;
}else{
nextPos.y -= 1;
}
current->direction = direction;
push(nextPos);
printf("(%d,%d,%d) pushed\n",nextPos.x,nextPos.y,nextPos.direction);
inThePath[nextPos.x][nextPos.y] = 1;
current ++;
}
/**
*return true if a position is equal to b position;
*/
int equal(struct StepRecord* a,struct StepRecord* b)
{
return ((a->x == b->x) && (a->y == b->y));
}
/**
* print out the successful path
*/
void printPath()
{
for(int i = 0; i <= top; i++)
printf("(%d,%d)\n",path[i].x,path[i].y);
}
/**
* return back to previous position
*/
void stepBack()
{
struct StepRecord tmp = pop();
printf("(%d,%d,%d) poped\n",tmp.x,tmp.y,tmp.direction);
inThePath[tmp.x][tmp.y] = 0;
current--;
}
int main(void)
{
struct StepRecord start = {0,0,UNKNOWDIRECTION};
// struct StepRecord sentinel = start;
struct StepRecord final = {4,4,UNKNOWDIRECTION};
Orientation direction;
// push(sentinel);
push(start);
current = path;
while(!equal(current,&final) && !isStackEmpty())
{
direction = nextWalkableDirection();
if(direction == NODIRECTION){
stepBack();
}else{
advanceByDirection(direction);
}
}
if(isStackEmpty()){
printf("no path to the end");
return 0;
}
printPath();
return 0;
}