1、单条通路迷宫
实现思路:
代码如下:
头文件maze.h
#ifndef __MAZE_H__
#define __MAZE_H__
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define H 5
#define L 5
#define MAX_SIZE 100
typedef struct position
{
int x;
int y;
}position;
typedef struct Maze
{
int _Map[H][L];
}Maze;
typedef position DataType;
typedef struct stack
{
DataType data[MAX_SIZE];
int top;
}Stack;
/
栈操作
void InitStack (Stack *p); //初始化栈
void PushStack (Stack *p, DataType d); //入栈
void PopStack (Stack *p); // 出栈
DataType TopNumAndTop (Stack *p); //返回栈顶元素然后出栈
int IsEmpty (Stack *p); // 判空
int StackSize (Stack* p); //返回栈的大小
//
//迷宫操作
void InitMaze (Maze* maze, int arr[H][L]);//初始化迷宫地图
void PrintMap (Maze maze);//打印迷宫
int IsEntry (Maze *maze, position *entry);//判断迷宫是否合法,合法返回1,否则返回0
void RunInMaze (Maze *maze, position *entry);//走迷宫
int IsPositionOk (Maze* maze, position *pos);//判断当前位置是否为通路
int IsExit(Maze* maze, position *entry, position *cur);//判断是否为出口
#endif
主演函数main.c
#include "maze.h"
///
//栈操作
void InitStack (Stack *p) //初始化
{
assert (p != NULL);
p->top = 0;
}
void PushStack (Stack *p, DataType d) //入栈
{
assert (p);
if (p->top == MAX_SIZE)
{
printf ("栈满,无法入栈!!!\n");
return;
}
p->data[p->top] = d;
p->top++;
}
int IsEmpty (Stack *p) // 判空
{
return (p->top == 0);//如果为空,返回1;如果不为空,返回0
}
void PopStack (Stack *p)//出栈
{
assert (p);
if (p->top == 0)
{
printf ("栈空,操作失败!!!\n");
return;
}
p->top --;
}
DataType TopNumAndTop (Stack *p) //返回栈顶元素(出栈)
{
if (p->top == 0)
{
printf ("栈为空!!\n");
return ;
}
return p->data[--(p->top)];
}
int StackSize (Stack* p)//返回栈的大小
{
return p->top;
}
//单条通路迷宫操作
void InitMaze (Maze* maze,int arr[H][L]) //初始化迷宫
{
int i = 0;
int j = 0;
for (i=0; i<H; i++)
{
for (j=0; j<L; j++)
{
maze->_Map[i][j] = arr[i][j];
}
}
}
void PrintMap (Maze maze) //打印迷宫
{
int i = 0;
int j = 0;
for (i=0; i<H; i++)
{
for (j=0; j<L; j++)
{
printf ("%d\t", maze._Map[i][j]);
}
printf ("\n\n\n");
}
}
int IsEntry (Maze *maze, position *entry) //判断是否是迷宫入口
{
if (entry->x == 0 || entry ->x == H-1 || entry->y == 0 || entry->y == L-1)
{
if (maze->_Map[entry->x][entry->y] == 1)
{
return 1;
}
}
return 0;
}
int IsPositionOk (Maze* maze, position *pos) //判断迷宫当前位置是否是通路
{
assert (pos != NULL);
if (pos->x >= 0 && pos->x < H && pos ->y >= 0 && pos ->y < L)
{
if (maze->_Map[pos->x][pos->y] == 1)
{
return 1;
}
}
return 0;
}
int IsExit(Maze* maze, position *entry, position *cur)//判断是否为出口
{
assert (maze != NULL && entry != NULL && cur != NULL);
if (cur->x == 0 || cur ->x == H-1 || cur->y == 0 || cur->y == L-1)
{
if (maze->_Map[cur->x][cur->y] == 2 && cur->x != entry->x && cur->y != entry->y)
{
return 1;
}
}
return 0;
}
void RunInMaze (Maze *maze, position *entry)//走迷宫
{
position *cur = NULL;
position next ;
Stack s;
InitStack (&s);
assert (maze != NULL && entry != NULL);
if (IsEntry (maze, entry) == 0)
{
printf ("入口非法!!!\n");
return;
}
//入口合法
cur = entry;
maze->_Map[cur->x][cur->y] = 2;
next.x = cur->x;
next.y = cur->y;
PushStack (&s, next);
while (!IsEmpty(&s) && !IsExit(maze, entry, &next))
{
//上
next.x --;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
//左
next .x ++;
next.y --;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
//右
next.y++;
next.y ++;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
//下
next.y--;
next.x ++;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
//四个方向都不合法,坐标出栈,回退
next = TopNumAndTop (&s);
}
if (IsEmpty(&s) == 1)
{
printf ("迷宫无出口!!\n");
}
else
{
printf ("迷宫已走完!!!\n");
}
}
测试代码:
test.c
#include "maze.h"
void test_1()
{
Maze maze;
position entry ;
int arr[H][L] = {
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 1, 1, 1, 1},
{0, 1, 0, 0, 0},
{0, 1, 0, 0, 0},
};
InitMaze (&maze, arr);
PrintMap (maze);
entry.x = H-1;
entry.y = 1;
RunInMaze (&maze, &entry);
PrintMap (maze);
}
int main()
{
test_1();
system ("pause");
return 0;
}
测试结果:
2、多条通路的迷宫
对于多条通路的迷宫,和上面的一种相比,只是多了几个出口,所以在遇到出口时,只需要将出口值赋为0,将出口堵死,知道栈为空时,迷宫走完所有通路
所以走迷宫的函数为(其余函数和上一个的一样):
void RunInMaze (Maze *maze, position *entry)//走迷宫
{
position* cur = NULL;
position next ;
Stack s;
InitStack (&s);
assert (maze != NULL && entry != NULL);
cur = entry;
if (0 == IsEntry (maze, entry))
{
printf ("非法入口!!!\n");
return ;
}
maze->_Map[cur->x][cur->y] = 2;
next.x = cur->x;
next.y = cur->y;
PushStack (&s, next);
while (!IsEmpty (&s))
{
//如果走到出口,将出口值赋为0,回退
if (1 == IsExit(maze, entry, &next))
{
maze->_Map[next.x][next.y] = 0;
next = TopNumAndTop (&s);
}
//上
next.x --;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
next .x ++;
//左
next.y --;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
next.y++;
//右
next.y ++;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
next.y--;
//下
next.x ++;
if(IsPositionOk (maze, &next) == 1)//位置合法
{
/*cur = &next;*/
maze->_Map[next.x][next.y] = 2;
PushStack (&s, next);
continue;
}
//上下左右都不能走,出栈回退
next = TopNumAndTop (&s);
}
printf ("迷宫已经走完!!!\n");
}
测试结果:
3、带环的迷宫:
带环迷宫和之前的也不一样,标记方式改为每走一步就把值赋为前一步加一,判断下一步的方式也有所改变,代码如下:
void InitMaze (Maze* maze,int arr[H][L])
{
int i = 0;
int j = 0;
for (i=0; i<H; i++)
{
for (j=0; j<L; j++)
{
maze->_Map[i][j] = arr[i][j];
}
}
}
void PrintMap (Maze maze)
{
int i = 0;
int j = 0;
for (i=0; i<H; i++)
{
for (j=0; j<L; j++)
{
printf ("%d\t", maze._Map[i][j]);
}
printf ("\n\n\n");
}
}
int IsEntry (Maze *maze, position *entry)
{
if (entry->x == 0 || entry ->x == H-1 || entry->y == 0 || entry->y == L-1)
{
if (maze->_Map[entry->x][entry->y] == 1)
{
return 1;
}
}
return 0;
}
int IsPositionOk (Maze* maze, position *pos, position *next)
{
assert (pos != NULL);
if (next->x >= 0 && next->x < H && next ->y >= 0 && next ->y < L)
{
if (maze->_Map[next->x][next->y] == 1 || maze->_Map[next->x][next->y] > maze->_Map[pos->x][pos->y])
{
return 1;
}
}
return 0;
}
int IsExit(Maze* maze, position *entry, position *cur)//判断是否为出口
{
assert (maze != NULL && entry != NULL && cur != NULL);
if (cur->x == 0 || cur ->x == H-1 || cur->y == 0 || cur->y == L-1)
{
if (cur->x != entry->x && cur->y != entry->y)
{
return 1;
}
}
return 0;
}
Stack* GetShortPath(Stack* path, Stack* short_path)
{
if (StackSize (short_path) == 0 || StackSize (path) < StackSize (short_path))
{
int i = 0;
for ( ;i<StackSize (path); i++)
{
short_path->data[i] = path->data[i];
}
short_path->top = path->top;
}
return short_path;
}
void RunInMaze (Maze *maze, position cur, position* entry, Stack* path, Stack* short_path)//走迷宫---其中maze为迷宫,cur 为 当前所在位
//置,entry 为入口位置,path 为当前正在走的路径,short_path为较短路径
{
position up, down, left, right;
assert (maze != NULL && entry != NULL);
//不是出口,继续往上左右下四个方向走
//上
up = cur;
up.x --;
if(IsPositionOk (maze, &cur, &up) == 1)//位置合法
{
PushStack (path, up); //入栈
//判断当前是否为出口
if (IsExit (maze, entry, &up) == 1)//是出口
{
maze->_Map[up.x][up.y] = maze->_Map[cur.x][cur.y]+1; //标记
short_path = GetShortPath (path, short_path); //获取最短路径
cur = TopNumAndTop (path); //往回退,查找其他路径
return;
}
maze->_Map[up.x][up.y] = maze->_Map[cur.x][cur.y]+1; //标记
RunInMaze (maze, up, entry, path, short_path);
}
//左
left = cur;
left.y --;
if(IsPositionOk (maze, &cur, &left) == 1)//位置合法
{
PushStack (path, left); //入栈
//判断当前是否为出口
if (IsExit (maze, entry, &left) == 1)//是出口
{
maze->_Map[left.x][left.y] = maze->_Map[cur.x][cur.y]+1; //标记
short_path = GetShortPath (path, short_path); //获取最短路径
cur = TopNumAndTop (path); //往回退,查找其他路径
return;
}
maze->_Map[left.x][left.y] = maze->_Map[cur.x][cur.y]+1; //标记
RunInMaze (maze, left, entry, path, short_path);
}
//右
right = cur;
right.y ++;
if(IsPositionOk (maze, &cur, &right) == 1)//位置合法
{
PushStack (path, right); //入栈
//判断当前是否为出口
if (IsExit (maze, entry, &right) == 1)//是出口
{
maze->_Map[right.x][right.y] = maze->_Map[cur.x][cur.y]+1; //标记
short_path = GetShortPath (path, short_path); //获取最短路径
cur = TopNumAndTop (path); //往回退,查找其他路径
return;
}
maze->_Map[right.x][right.y] = maze->_Map[cur.x][cur.y]+1; //标记
RunInMaze (maze, right, entry, path, short_path);
}
//下
down = cur;
down.x ++;
if(IsPositionOk (maze, &cur, &down) == 1)//位置合法
{
PushStack (path, down); //入栈
//判断当前是否为出口
if (IsExit (maze, entry, &down) == 1)//是出口
{
maze->_Map[down.x][down.y] = maze->_Map[cur.x][cur.y]+1; //标记
short_path = GetShortPath (path, short_path); //获取最短路径
cur = TopNumAndTop (path); //往回退,查找其他路径
return;
}
maze->_Map[down.x][down.y] = maze->_Map[cur.x][cur.y]+1; //标记
RunInMaze (maze, down, entry, path, short_path);
}
//四个方向都探测过,出栈回退
cur = TopNumAndTop (path);
}
测试结果: