走迷宫
迷宫地图在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;
}
结果
最难不过坚持!