C语言——走迷宫

走迷宫

迷宫地图在txt文件中,(1为墙,0为路)

通过程序,找到迷宫出口,并打印出路径坐标,及迷宫地图

分文件式编写

 utili.h

公共头文件

#ifndef _UTILI_H_
#define _UTILI_H_

#include<stdio.h>
#include<stdlib.h>

#endif

labyrinth.h

走迷宫头文件

结构体定义

        x,y  :节点位置

        f:下一步方向  1-向上、2-向左、3-向下、4-向右、5-不通

        t:   与上一步的相对方向

                node1  node2  :node1向右到node2  ,node1.f=4

                                            node2的左边是node1,node2.t=2

        next:下一个结点的地址

        last: 上一个结点的地址

函数声明

#ifndef _LABYRINTH_H_
#define _LABYRINTH_H_

#include"utili.h"

/*
定义路径链表
*/
typedef struct Node
{
	int x;				//x坐标
	int y;				//y坐标
	int f;				//1-上、2-左、3-下、4-右、5-不通
	int t;				//上一步相对于当前的位置 
	struct Node* next;	//下一步
	struct Node* last;	//上一步
}Node;
typedef Node* List;

/*
定义方向常量
*/
enum Toward
{

	UP = 1,
	LEFT,
	DOWN,
	RIGHT,
	BACK
};

/*
从文件中获取迷宫地图
通过传址,得到迷宫大小:r  l
name:文件名
r:迷宫长
l:迷宫宽
*/
void initMiGong(char name[80], int* r, int* l);
/*
创建迷宫地图
通过动态内存分配,申请空间。
返回空间地址
r:迷宫长
l:迷宫宽
*/
int** initmap(int r, int l);
/*
创建迷宫并输出打印
*/
int** map(char name[80], int r, int l);
/*
初始化节点
传址调用
node:节点地址
x:行位置,x坐标
y:列位置,y坐标
*/
void initNode(List* node, int x, int y);
/*
添加节点
传址调用
list:链表尾节点
x:所添加节点的x坐标
y:所添加节点的y坐标
*/
void push(List* list, int x, int y);
/*
删除节点
传址调用
list:链表尾节点
*/
void pop(List* list);
/*
判断下一步,是否已存在路径中。(即:下一步,以前走过)
传址调用,已经走过修改下一步的方向;
list:链表尾节点
x:下一步x轴上的移动步长
y:下一步y轴上的移动步长
返回值:1 与以往路劲重合;0 不重合
*/
int choose(List* list, int xnum, int ynum);
/*
走迷宫
传址调用
list:链表,路径
a:迷宫
xout:出口x坐标
yout:出口y坐标
*/
void path(List* list, int** a, int xout, int yout);
/*
打印路径表
传址调用
head:路径首地址
*/
void printList(List* head);
/*
打印路径图
传址调用
list:路径链表
a:迷宫
r:迷宫长
l: 迷宫宽
*/
void printPath(List* list, int** a, int r, int l);
/*
释放申请的动态内存空间
*/
void freeList(List* list);

#endif

labyrinth.c

走迷宫函数实现

1.获取迷宫文件

/*
从文件中获取迷宫地图
通过传址,得到迷宫大小:r  l
name:文件名
r:迷宫长
l:迷宫宽
*/
void initMiGong(char name[80], int* r, int* l)//得迷宫大小 
{
	FILE* p;
	int i, j;
	i = 0; j = 0;
	char c;
	p = fopen(name, "r+");
	while (1)
	{
		c = fgetc(p);
		i++;
		if (c == '\n' || c == EOF)
		{
			j++;
		}
		if (c == EOF)
			break;
	}
	*r = j;
	*l = i / j - 1;
	fclose(p);
}

/*
创建迷宫地图
通过动态内存分配,申请空间。
返回空间地址
r:迷宫长
l:迷宫宽
*/
int** initmap(int r, int l)//动态创建迷宫大小 
{
	int i;
	i = 0;
	int** p;
	p = (int**)malloc(r * sizeof(int*));
	for (i; i < r; i++)
	{
		p[i] = (int*)malloc(l * sizeof(int));
	}
	return p;
}

/*
创建迷宫并输出打印
*/
int** map(char name[80], int r, int l)
{
	FILE* p;
	int** a;
	a = initmap(r, l);
	//int a[25][12];
	char c;
	p = fopen(name, "r");
	int i, j, d;
	j = 0; i = 0;
	while (1)
	{
		while (1)
		{
			c = fgetc(p);
			a[i][j] = c - 48;
			if (c == '\n' || c == EOF)
			{
				break;
			}
			j++;
		}

		if (c == EOF)
		{
			break;
		}
		i++;
		j = 0;
	}
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < l; j++)
		{
			if (i == 1 && j == 1)
				printf("i ");
			else if (i == r - 2 && j == l - 2)
				printf("o ");
			else
				printf("%d ", a[i][j]);
		}
		printf("\n");
	}
	fclose(p);
	return a;
}

2.构建迷宫路径表

基本功能

初始化

/*
初始化节点
传址调用
node:节点地址
x:行位置,x坐标
y:列位置,y坐标
*/
void initNode(List *node, int x, int y)
{
	*node = (Node*)malloc(sizeof(Node));
	if (node == NULL)
	{
		printf("空间申请失败!\n");
		return ;
	}
	(*node)->x = x;
	(*node)->y = y;
	(*node)->f = 1;		//默认下一步向上走
	(*node)->t = 0;		//上一步的位置
	(*node)->next = NULL;
	(*node)->last = NULL;

	return;
}

添加

/*
添加节点
传址调用
list:链表尾节点
x:所添加节点的x坐标
y:所添加节点的y坐标
*/
void push(List* list,int x,int y)
{
	List node = NULL;
	//初始化所添加节点
	initNode(&node, x, y);
	//链表指向节点地址
	(*list)->next = node;
	switch ((*list)->f)
	{
	case UP:
		node->t = DOWN;
		break;
	case LEFT:
		node->t = RIGHT;
		break;
	case DOWN:
		node->t = UP;
		break;
	case RIGHT:
		node->t = LEFT;
		break;
	}
	node->last = (*list);
	(*list) = node;
	return;
}

删除

/*
删除节点
传址调用
list:链表尾节点
*/
void pop(List* list)
{
	List pnode = (*list)->last;
	free(pnode->next);
	pnode->next = NULL;
	(*list) = pnode;
	return;
}

走迷宫

1.

/*
判断下一步,是否已存在路径中。(即:下一步,以前走过)
传址调用,已经走过修改下一步的方向;
list:链表尾节点
x:下一步x轴上的移动步长
y:下一步y轴上的移动步长
返回值:1 与以往路劲重合;0 不重合
*/
int choose(List* list, int xnum, int ynum)
{
	int f = 0;			//作为判定 1-----与以往路径重合 
	List now, per;
	now = (*list);
	per = (*list)->last;
	while (per)
	{
		if (now->x + xnum == per->x && now->y + ynum == per->y)
		{
			now->f++;
			f = 1;
			break;
		}
		per = per->last;
	}
	return f;
}

2.

/*
走迷宫
传址调用
list:链表,路径
a:迷宫
xout:出口x坐标
yout:出口y坐标
*/
void path(List* list, int** a, int xout, int yout)
{
	int flag;		//判定		1-----与以往路径重合
	List phead = (*list);			//保护链表
	while (1)
	{
		/*
		当前坐标与出口坐标重合,表示已走出迷宫
		*/
		if (phead->x == xout && phead->y == yout)
		{
			printf("走出迷宫!\n");
			break;
		}
		/*
		禁止返回上一步
		*/
		else if (phead->f == phead->t)
		{
			phead->f++;
		}
		/*
		判断下一步,是否存在与路径中
		*/
		else
		{
			flag = 1;	//默认与以往路径重合
			while (flag == 1)
			{
				if (phead->f == UP)
					flag = choose(&phead, -1, 0);
				else if (phead->f == LEFT)
					flag = choose(&phead, 0, -1);
				else if (phead->f == DOWN)
					flag = choose(&phead, 1, 0);
				else if (phead->f == RIGHT)
					flag = choose(&phead, 0, 1);
				else
					break;
			}
			/*
			判断下一步,能否走通(是否是路)
			可以走,加入链表
			不能走,换下个方向
				所有方向都不能走,当前位置为死路,删除节点,返回上一步,并换下一方向
			*/
			switch (phead->f)
			{
			case UP:
				if (a[phead->x - 1][phead->y] == 1)
				{
					phead->f++;
				}
				else
				{
					push(&phead, phead->x - 1, phead->y);
				}
				break;
			case LEFT:
				if (a[phead->x][phead->y - 1] == 1)
				{
					phead->f++;
				}
				else
				{
					push(&phead, phead->x, phead->y - 1);
				}
				break;
			case DOWN:
				if (a[phead->x + 1][phead->y] == 1)
				{
					phead->f++;
				}
				else
				{
					push(&phead, phead->x + 1, phead->y);
				}
				break;
			case RIGHT:
				if (a[phead->x][phead->y + 1] == 1)
				{
					phead->f++;
				}
				else
				{
					push(&phead, phead->x, phead->y + 1);
				}
				break;
			case BACK:
				pop(&phead);
				if (phead == NULL)
				{
					printf("迷宫无活路!\n");
					break;
				}
				phead->f++;
				break;
			default:
				break;
			}
		}
	}
}

打印结果

/*
打印路径图
传址调用
list:路径链表
a:迷宫
r:迷宫长
l: 迷宫宽
*/
void printPath(List* list, int** a, int r, int l)
{
	List plist = (*list);
	while (plist)
	{
		a[plist->x][plist->y] = 2;
		plist = plist->next;
	}
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < l; j++)
		{
			if (a[i][j] == 2)
				printf("  ");
			else if (i == 1 && j == 1)
				printf("s ");
			else if (i == r - 2 && j == l - 2)
				printf("e ");
			else
				printf("%d ", a[i][j]);
		}
		printf("\n");
	}
	return;
}

/*
打印路径表
传址调用
head:路径首地址
*/
void printList(List *head)
{
	Node* phead = (*head);
	while (phead != NULL)
	{
		printf("(%2d,%2d) ", phead->x, phead->y);
		phead = phead->next;
	}
}

释放空间

/*
释放申请的动态内存空间
*/
void freeList(List* list)
{
	while ((*list)!=NULL)
	{
		free((*list)->last);
		(*list) = (*list)->next;
	}
	printf("申请空间已释放!\n");
	return;
}

labyrinthMain.c

主函数运行

#include"labyrinth.h"

int main()
{
	system("title 走迷宫");
	system("color 8B");
	

	//获取迷宫地图
	char name[80];
	printf("输入迷宫文件名\n");
	gets(name);
	int r, l;
	initMiGong(name, &r, &l);
	
	int** a;
	printf("迷宫长%d宽%d\n", r, l);
	a = map(name, r, l);
	

	//初始化路径表
	List head = NULL;
	initNode(&head, 1, 1);
	List list = head;

	//走迷宫
	path(&list, a, r - 2, l - 2);
	//打印迷宫线路图
	printPath(&list, a, r, l);
	//打印路径
	printf("路径指南\n");
	printList(&list);
	//释放空间
	freeList(&list);
	free(a);
	return 0;
}

结果

 

 

 

最难不过坚持!

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值