这是最近看到的一个小题目,以C语言来实作练练手。
题目叙述:
设计一个程式,读入文件中的迷宫地图数据,然后利用回圈或递回函数在迷宫中行进。
并且使用堆叠(同堆栈、stack)记录走过的分岔路口座标,以便走到死路时可从堆叠中取出分岔路口座标來返回分岔路口。
最后将找到的那条从入口到出口的行进路径输出到一个文件中。
输出行进路径举例:
右, 右, 下, 下, 下, Push(5,4), 下, 下, 遇到死路, (5,4)= Pop(), 右, 右, 右, Push(5,7), 下, 下, ...
输入档案格式:
1)第一列有两个数字m、n,代表地图的大小。
2)接下来有 m * n 个以空格或断行分隔的数字,其值为 0 或 1。(注意:每一列储存n个数字,档案中总共会有 m * n 个数字来标示地图)
3)地图由 m * n 个位置组成,数值0 表示可走之位置,1 表示不可走之位置。
4)入口为 字母M,出口为 字母O。
5)如果无法走到出口请印出“无法离开”讯息。
Input:
input_map.txt 內容
10 10
M 1 1 1 1 1 1 1 1 1
0 0 0 0 1 0 0 1 1 0
1 0 1 0 0 0 1 1 0 0
0 0 1 1 0 1 0 1 1 0
1 0 0 1 0 0 0 0 0 0
1 1 0 1 1 0 1 1 1 1
1 1 0 0 1 1 1 1 0 1
1 0 0 0 0 1 0 0 1 1
0 0 1 1 0 0 0 0 0 0
0 1 1 1 1 1 1 1 1 O
Output:
下, 右, Push(2,2), 下, 下, Push(4,2), 左, 遇到死路, (4,2) = Pop(), 下, 右, 下, 下, Push(7,3), 下, Push(8,3), 左, 下, 左, 下, 遇到死路, (8,3) = Pop(), 右, Push(8,4), 上, 遇到死路, (8,4) = Pop(), 右, 下, 右, 右, Push(9,7), 上, 右, 下, 右, 右, 下, 到達
以下是簡陋的流程圖:
以下给出实作代码:
#include
#include
#define FILE_MAP "input_map.txt"
#define FILE_OUTPUT "output_route.txt"
#define MAP_MAXSIZE_X 100
#define MAP_MAXSIZE_Y 100
#define MAX_STACK (MAP_MAXSIZE_X*MAP_MAXSIZE_Y)/2
#define bool int
#define true 1
#define false 0
int max_x=0, max_y=0;
char map[MAP_MAXSIZE_X][MAP_MAXSIZE_Y]={1};
bool passed[MAP_MAXSIZE_X][MAP_MAXSIZE_Y]={0};
struct _POSITION { // coordinate data
int x;
int y;
};
typedef struct _POSITION POSITION;
POSITION stack[MAX_STACK]; // stack declaration
int top = -1; // top of the stack
// To know whether stack is empty
bool IsEmpty()
{
if(top == -1)
return true;
return false;
}
// To know whether stack is full
bool IsFull()
{
if(top < MAX_STACK-1)
return false;
return true;
}
// pop data from stack
POSITION Pop()
{
return stack[top--];
}
// push data into stack
void Push(POSITION posData)
{
stack[++top]=posData;
}
void run(int x, int y)
{
FILE *fptr;
POSITION last; // last position data
unsigned int branch = 0; // branch numbers
int direction = 1; // 1:east, 2:south, 3:west, 4:north
fptr = fopen(FILE_OUTPUT, "w");
while(map[x][y] != 'O') // loop until reach the goal
{
branch = 0; // reset branch to 0
passed[x][y] = 1; // set this position is passed
// TODO: choose a way to go
if((y+1=0) && ((map[x][y-1] == 'O') || (map[x][y-1] == '0'))
&& (passed[x][y-1] == 0))
{
branch++;
direction = 3;
}
if((x-1>=0) && ((map[x-1][y] == 'O') || (map[x-1][y] == '0'))
&& (passed[x-1][y] == 0))
{
branch++;
direction = 4;
}
// TODO: move forward
if(branch > 1) // if there are many ways can go
{
if(!IsFull())
{ // if stack is not full, push the branch position into the stack
last.x = x;
last.y = y;
Push(last);
printf("Push(%d,%d), ", last.x+1, last.y+1);
fprintf(fptr, "Push(%d,%d), ", last.x+1, last.y+1);
}
}
else if(branch == 0) // if there is no route, is a dead end
{
printf("遇到死路, ");
fprintf(fptr, "遇到死路, ");
if(!IsEmpty())
{
last = Pop();
x = last.x;
y = last.y;
printf("(%d,%d) = Pop(), ", last.x+1, last.y+1);
fprintf(fptr, "(%d,%d) = Pop(), ", last.x+1, last.y+1);
}
else
{
printf("無法離開\n");
fprintf(fptr, "無法離開\n");
fclose(fptr);
return;
}
continue;
}
// TODO: choose a way from last one direction, and move forward
switch(direction)
{
case 1:
y = y + 1;
printf("右, ");
fprintf(fptr, "右, ");
break;
case 2:
x = x + 1;
printf("下, ");
fprintf(fptr, "下, ");
break;
case 3:
y = y - 1;
printf("左, ");
fprintf(fptr, "左, ");
break;
case 4:
x = x - 1;
printf("上, ");
fprintf(fptr, "上, ");
break;
}
}
printf("到達\n");
fprintf(fptr, "到達\n");
fclose(fptr);
}
int main()
{
FILE *fptr;
int i,j,start_x,start_y;
// TODO: Load file
fptr = fopen(FILE_MAP,"r");
if(!fptr)
{
printf("File loaded error!\n");
return 0;
}
// TODO: Read file
fscanf(fptr, "%d %d\n",&max_x, &max_y);
if(max_x==0 || max_y==0)
return 0;
for(i=0;i