[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;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个简单的C语言代码,用于实现老鼠走迷宫游戏。请注意,这只是一个示例代码,您需要根据具体情况进行修改。 ```c #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define ROW 10 #define COL 10 // 定义迷宫 int maze[ROW][COL] = { {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 1, 0, 0, 0, 1, 0, 1}, {1, 0, 0, 1, 0, 0, 0, 1, 0, 1}, {1, 0, 0, 0, 0, 1, 1, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 1, 0, 0, 0, 0, 1}, {1, 0, 1, 0, 0, 0, 1, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 1, 1, 0, 1}, {1, 1, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1} }; // 定义老鼠的移动方向 int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 手动输入 // 定义栈的结构体 typedef struct { int x; int y; } Stack; Stack stack[ROW * COL]; int top = -1; // 判断某个点是否为终点 bool isEnd(int x, int y) { return (x == ROW - 2) && (y == COL - 2); // 手动输入 } // 压栈 void push(int x, int y) { top++; stack[top].x = x; stack[top].y = y; } // 出栈 void pop() { top--; } // 判断栈是否为空 bool isEmpty() { return top == -1; } // 获取栈顶元素 Stack getTop() { return stack[top]; } // 打印路径 void printPath() { int i; for (i = 0; i <= top; i++) { printf("(%d, %d) ", stack[i].x, stack[i].y); } printf("\n"); } // 判断某个点是否为可行路径 bool isPath(int x, int y) { return maze[x][y] == 0; } // 判断某个点是否已经过 bool isVisited(int x, int y) { return maze[x][y] == 2; } // 标记某个点为已经过 void markVisited(int x, int y) { maze[x][y] = 2; } // 回溯函数,递归实现老鼠走迷宫 void backtrack(int x, int y) { int i; if (isEnd(x, y)) { push(x, y); printPath(); pop(); return; } for (i = 0; i < 4; i++) { int next_x = x + dir[i][0]; int next_y = y + dir[i][1]; if (isPath(next_x, next_y) && !isVisited(next_x, next_y)) { markVisited(next_x, next_y); push(x, y); backtrack(next_x, next_y); pop(); maze[next_x][next_y] = 0; // 恢复现场 } } } int main() { markVisited(1, 1); // 标记起点为已经过 push(1, 1); // 入栈 backtrack(1, 1); // 回溯 return 0; } ``` 请注意,上述代码只是一个示例,您需要根据实际情况进行修改,比如修改迷宫的大小、起点和终点的坐标等。此外,回溯算法的时间复杂度较高,可能会导致程序运行时间过长。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值