[C] 老鼠走迷宫(使用回圈+堆叠)

这是最近看到的一个小题目,以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 <stdio.h>
#include <windows.h>

#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<max_y) && ((map[x][y+1] == 'O') || (map[x][y+1] == '0'))
			&& (passed[x][y+1] == 0))
		{  // if east can go, and hasn't passed yet
			branch++; // increase the branch, if this way can go
			direction = 1;
		}
		if((x+1<max_x) && ((map[x+1][y] == 'O') || (map[x+1][y] == '0'))
			&& (passed[x+1][y] == 0))
		{
			branch++;
			direction = 2;
		}
		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<max_x;i++)
    {
        for(j=0;j<max_y;j++)
        {
           fscanf(fptr, " %c", &map[i][j]);
           passed[i][j]=0;
           if(map[i][j]=='M')
           {
               start_y=i;
               start_x=j;
           }
        }
    }
    fclose(fptr);
    
    // TODO: show maze
    for(i=0;i<max_x;i++)
    {
        for(j=0;j<max_y;j++)
        {
           printf("%c ", map[i][j]);
        }
        printf("\n");
    }
    
    run(start_y,start_x); // run maze
    
    system("pause");
    return 0;
}



©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页