所有实践项目的源程序可到我的Github上下载:https://github.com/liulizhi1996/C-Programming-Practice-in-short-semester
问题描述:
以一个n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍,设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
对于本问题需用栈实现“穷举求解”算法,即:从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。加入所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。迷宫数据是一个n阶矩阵用二维数组存储,起点为(1,1),终点为(n,n),再在迷宫外围加上一层围墙(默认为1,不需用户输入,用户只需输入迷宫数据即可),对于迷宫中每个数据都有四个方向可通。
具体实现算法的函数及要点如下:初始化栈,销毁栈,清空栈,判栈空,取栈顶元素,插入新的栈顶元素,删除栈顶元素,从栈底到栈顶依次访问栈中的每个结点,最重要的就是要判断迷宫的通路。
从迷宫的入口到出口找出一条通路的算法如下:设定当前位置的初值为入口位置;
do{
若当前位置可通,
则{将当前位置插入栈顶;
若该位置是出口位置,则算法结束;
否则切换当前位置的东邻方块为新的位置;
}
否则{回到当前位置的前一个位置,判断是否可通(类似于上面算法)
……
}
}while(栈不空);
若栈不空且栈顶位置尚有其他方向未被探索,
则设定新的当前位置为: 沿顺时针方向旋转
找到的栈顶位置的下一相邻块;
若栈不空但栈顶位置的四周均不可通,
则{删去栈顶位置;// 从路径中删去该通道块
若栈不空,则重新测试新的栈顶位置,
直至找到一个可通的相邻块或出栈至栈空;
}
若栈空,则表明迷宫通路。
最后根据栈储存的数据输出迷宫径即可。
stack.h
#ifndef STACK_H
#define STACK_H
struct Pos
{
int x;
int y;
};
struct Node
{
struct Pos pos;
int direction;
struct Node *next;
};
void init(struct Node **head);
void destroy(struct Node **head);
void clear(struct Node *head);
int is_empty(struct Node *head);
int top(struct Node *head, struct Pos *pos, int *direction);
void push(struct Node *head, struct Pos pos, int direction);
int pop(struct Node *head, struct Pos *pos, int *direction);
void traverse(struct Node *head);
#endif //STACK_H
stack.cpp
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
void init(struct Node **head)
{
*head = (struct Node *)malloc(sizeof(struct Node));
(*head)->next = NULL;
}
void destroy(struct Node **head)
{
struct Node *p, *q;
p = *head;
if (*head)
q = (*head)->next;
while (p)
{
free(p);
p = q;
if (q)
q = q->next;
}
*head = NULL;
}
void clear(struct Node *head)
{
struct Node *p, *q;
if (head)
{
destroy(&(head->next));
head->next = NULL;
}
}
int is_empty(struct Node *head)
{
if (head && head->next)
return 0;
else
return 1;
}
int top(struct Node *head, struct Pos *pos, int *direction)
{
if (!is_empty(head))
{
pos->x = head->next->pos.x;
pos->y = head->next->pos.y;
*direction = head->next->direction;
return 1;
}
else
return 0;
}
void push(struct Node *head, struct Pos pos, int direction)
{
struct Node *p = (struct Node *)malloc(sizeof(struct Node));
p->pos.x = pos.x;
p->pos.y = pos.y;
p->direction = direction;
p->next = head->next;
head->next = p;
}
int pop(struct Node *head, struct Pos *pos, int *direction)
{
if (!is_empty(head))
{
struct Node *p = head->next;
pos->x = p->pos.x;
pos->y = p->pos.y;
*direction = p->direction;
head->next = p->next;
free(p);
return 1;
}
else
return 0;
}
void recursive_traverse(struct Node *p)
{
if (p)
{
recursive_traverse(p->next);
printf("(%d, %d)->", p->pos.x, p->pos.y);
}
}
void traverse(struct Node *head)
{
if (!is_empty(head))
{
recursive_traverse(head->next);
}
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int maze[30][30] = { 0 };
struct Node *stack;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
void solve_maze(int N)
{
struct Pos pos;
int direction;
pos.x = 1, pos.y = 1, direction = -1;
push(stack, pos, direction);
while (!is_empty(stack))
{
pop(stack, &pos, &direction);
direction++;
while (direction < 4)
{
if (maze[pos.x+dx[direction]][pos.y+dy[direction]] == 0)
{
push(stack, pos, direction);
maze[pos.x][pos.y] = -1;
pos.x = pos.x + dx[direction];
pos.y = pos.y + dy[direction];
if (pos.x == N && pos.y == N)
{
printf("Path: ");
traverse(stack);
printf("(%d, %d)\n", N, N);
return;
}
else
direction = 0;
}
else
direction++;
}
}
printf("No Path!\n");
}
int main()
{
int N;
printf("Please enter the size of maze: ");
scanf("%d", &N);
for (int i = 0; i <= N+1; ++i)
{
maze[0][i] = 1;
maze[N+1][i] = 1;
maze[i][0] = 1;
maze[i][N+1] = 1;
}
printf("Please enter the maze: \n");
for (int i = 1; i <= N; ++i)
{
for (int j = 1; j <= N; ++j)
{
scanf("%d", &maze[i][j]);
}
}
init(&stack);
solve_maze(N);
destroy(&stack);
return 0;
}
测试数据:
Test 1:
8
0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 0 0 1 1 0 0
0 1 1 1 0 0 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 1 0 0
0 1 1 1 0 1 1 0
1 0 0 0 0 0 0 0
Test 2:
2
1 1
1 1
Test 3:
5
0 1 1 1 1
0 0 0 1 1
1 1 1 1 0
0 0 0 0 1
1 1 0 1 0
Test 4:
3
0 0 1
0 1 1
0 0 1
Test 5:
10
0 0 1 0 0 0 0 1 0 1
1 0 1 0 1 1 0 1 1 0
1 0 0 0 1 1 0 0 0 1
0 1 0 1 1 0 0 1 1 1
0 1 0 0 1 1 0 1 0 0
1 0 1 0 1 1 0 0 1 0
0 1 1 0 0 0 1 0 1 1
0 1 0 1 1 0 0 0 0 0
0 1 1 0 0 1 1 1 1 0
1 0 1 0 1 1 0 0 1 0
Test 6:
8
0 0 1 1 1 0 1 0
1 0 0 1 1 1 0 1
1 1 0 0 0 0 0 1
1 1 0 1 1 1 0 1
1 1 0 1 1 1 0 1
1 1 0 0 0 0 0 1
1 1 1 1 1 1 0 1
1 1 0 0 0 0 0 0