前言
以前写过一篇博客,用栈走迷宫,然后就想着自己生成迷宫,自己走,就上网查了查自动生成迷宫的算法,也是研究了好一会,才用代码实现了这个算法,采用的就是常见的随机Prim算法。
原理
参考博客:https://blog.csdn.net/juzihongle1/article/details/73135920/
这篇博客讲的原理就很清楚,我就是按照这个思路写出来的,不过这篇博客用的是Python实现的,我用纯C语言实现了一下。
引用博客里的原理:
1.让迷宫全是墙.
2.选一个单元格作为迷宫的通路,然后把它的邻墙放入列表
3.当列表里还有墙时
1.从列表里随机选一个墙,如果这面墙分隔的两个单元格只有一个单元格被访问过
1.那就从列表里移除这面墙,即把墙打通,让未访问的单元格成为迷宫的通路
2.把这个格子的墙加入列表
2.如果墙两面的单元格都已经被访问过,那就从列表里移除这面墙
程序中用到了链表,因为要动态分配内存,实现动态数组。
程序
运行截图:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include <windows.h>
#define MAX_NUM 9
/******************************link**********************************/
typedef struct node
{
int x;
int y;
struct node *next;
}node;
node sentinel = {0, 0, 0, NULL};
node *head = &sentinel;
int sum = 0;
//创建节点
node *mk_node(int x, int y)
{
node *p = (node *)malloc(sizeof(node));
if (p == NULL)
{
printf("malloc failed!\n");
exit(1);
}
p->x = x;
p->y = y;
p->next = NULL;
return p;
}
//释放节点
void free_node(node *p)
{
free(p);
}
//插入节点
void insert_node(node *p)
{
sum++;
p->next = head->next;
head->next = p;
}
//遍历节点
void traverse()
{
node *p = head->next;
while (p != NULL)
{
printf("[%d, %d] ", p->x, p->y);
p = p->next;
}
printf("\n");
}
//销毁链表
void destroy_link()
{
node *p = head->next;
while (head->next != NULL)
{
sum--;
p = head->next;
head->next = p->next;
free_node(p);
}
}
//查找节点
node *search_node(int x, int y)
{
node *p = head->next;
while (p != NULL)
{
if (p->x == x && p->y == y)
{
return p;
}
p = p->next;
}
return NULL;
}
//查找节点
node *search_index(int index)
{
int i = 0;
node *p = head->next;
while (p != NULL)
{
if (i == index)
{
return p;
}
else
{
i++;
p = p->next;
}
}
return NULL;
}
void rm_node(node *p)
{
node *pre = head;
while (pre->next != NULL)
{
if (pre->next == p)
{
sum--;
pre->next = p->next;
p->next = NULL;
//free_node(p);
return;
}
pre = pre->next;
}
}
/******************************link**********************************/
int map[MAX_NUM][MAX_NUM] = {0};
int count_map()
{
int i = 0;
int j = 0;
int count = 0;
for (i = 0; i < MAX_NUM; i++)
{
for (j = 0; j < MAX_NUM; j++)
{
if (map[j][i] == 7)
count++;
}
}
return count;
}
//将邻墙放入链表
void insert_around(node *p)
{
node *p_t;
if (search_node((p->x) - 1, p->y) == NULL &&
(p->x)-1 > -1 && map[(p->x)-1][p->y] == 7) //左边没越界且为墙
{
p_t = mk_node((p->x) - 1, p->y);
insert_node(p_t);
}
if (search_node((p->x) + 1, p->y) == NULL &&
(p->x)+1 < MAX_NUM && map[(p->x)+1][p->y] == 7) //右边没越界且为墙
{
p_t = mk_node((p->x)+1, p->y);
insert_node(p_t);
}
if (search_node((p->x), (p->y) - 1) == NULL &&
(p->y)-1 > -1 && map[p->x][(p->y)-1] == 7) //上边没越界且为墙
{
p_t = mk_node(p->x, (p->y)-1);
insert_node(p_t);
}
if (search_node((p->x),(p->y) + 1) == NULL &&
(p->y)+1 < MAX_NUM && map[p->x][(p->y)+1] == 7) //下边没越界且为墙
{
p_t = mk_node(p->x, (p->y)+1);
insert_node(p_t);
}
}
void show_map()
{
int i = 0;
int j = 0;
for (i = 0; i < MAX_NUM; i++)
{
for (j = 0; j < MAX_NUM; j++)
{
printf("%d ", map[j][i]);
}
printf("\n");
}
}
void print_map()
{
int i = 0;
int j = 0;
for (i = 0; i < MAX_NUM; i++)
{
for (j = 0; j < MAX_NUM; j++)
{
if (map[j][i] == 7)
printf("* ");
else
printf("1 ");
}
printf("\n");
}
}
//7 墙
int main()
{
int i = 0;
int j = 0;
srand((int)time(0));
//全部为墙
for (i = 0; i < MAX_NUM; i++)
{
for (j = 0; j < MAX_NUM; j++)
{
map[i][j] = 7;
}
}
show_map();
map[0][0] = 1; //00被访问
node *p;
p = mk_node(0, 0);
//insert_around(p); //放入邻墙
p = mk_node(1, 0);
insert_node(p);
p = mk_node(0, 1);
insert_node(p);
//traverse();
while (sum != 0)
{
node *p_t;
int index = rand() % sum;
//printf("index = %d\n", index);
p = search_index(index);
//printf("p = [%d, %d]\n", p->x, p->y);
if ( (p->x)-1 > -1 && (p->x)+1 < MAX_NUM
&& map[(p->x)-1][(p->y)] == 1 && map[(p->x)+1][(p->y)] == 7)//左被访问右未被访问
{
map[(p->x)][(p->y)] = 1;
map[(p->x)+1][(p->y)] = 1;
p_t = mk_node((p->x)+1, (p->y));
insert_around(p_t);
rm_node(p);
free_node(p);
//printf("LR1\n");
}
else if ( (p->x)-1 > -1 && (p->x)+1 < MAX_NUM
&& map[(p->x)-1][(p->y)] == 7 && map[(p->x)+1][(p->y)] == 1)//右被访问左未被访问
{
map[(p->x)][(p->y)] = 1;
map[(p->x)-1][(p->y)] = 1;
p_t = mk_node((p->x)-1, (p->y));
insert_around(p_t);
rm_node(p);
//printf("LR2\n");
}
else if ( (p->y)-1 > -1 && (p->y)+1 < MAX_NUM
&& map[(p->x)][(p->y)-1] == 1 && map[(p->x)][(p->y)+1] == 7)//上被访问下未被访问
{
map[(p->x)][(p->y)] = 1;
map[(p->x)][(p->y)+1] = 1;
p_t = mk_node((p->x), (p->y)+1);
insert_around(p_t);
rm_node(p);
//printf("UD1\n");
}
else if ( (p->y)-1 > -1 && (p->y)+1 < MAX_NUM
&& map[(p->x)][(p->y)-1] == 7 && map[(p->x)][(p->y)+1] == 1)//下被访问上未被访问
{
map[(p->x)][(p->y)] = 1;
map[(p->x)][(p->y)-1] = 1;
p_t = mk_node((p->x), (p->y)-1);
insert_around(p_t);
rm_node(p);
//printf("UD2\n");
}
else
{
//map[(p->x)][(p->y)] = 1;
rm_node(p);
//printf("全部被访问\n");
}
//traverse();
//show_map();
//Sleep(100);
}
printf("wall is %d\n", count_map());
//show_map();
print_map();
traverse();
destroy_link();
return 0;
}
总结
与我联系
QQ:1570553025
github:https://github.com/myzcl
微信公众号,扫二维码即可关注: