您的位置:首页 > 编程语言 > C语言/C++

【C语言】迷宫

2018-10-12 16:46 232 查看
一,涉及知识点
结构体,栈,递归
二,实现逻辑
1.定义一个结构体保存当前位置坐标
2.用数组初始化一个迷宫,1表示可以走,0表示墙,迷宫最后一列都是出口
3.打印迷宫
4.走迷宫方法一:使用栈,通过压栈出栈回溯;方法二:在栈的基础上,用递归做回溯
5.记录最短路径,把路径压入栈中,打印最短路径
三,源码
#pragma once
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

#define ROWS (6)       //行数
#define COLS (6)        //列数
#define MAX_SIZE (100)

//结构体存放坐标
typedef struct Position
{
int x;
int y;
}Position;
typedef Position StackDataType;
//栈
typedef struct Stack
{
StackDataType array[MAX_SIZE];
int top;        //表示当前个数
}Stack;
void StackInit(Stack *pStack)
{
pStack->top = 0;
}
void StackDestroy(Stack *pStack)
{
pStack->top = 0;
}
void StackPush(Stack *pStack, StackDataType data)
{
assert(pStack->top < MAX_SIZE);
//pStack->top 永远指向的栈顶后的一个空间
pStack->array[pStack->top++] = data;
}
void StackPop(Stack *pStack)
{
assert(pStack->top>0);
pStack->top--;
}
Position StackTop(Stack *pStack)
{
assert(pStack->top > 0);
return pStack->array[pStack->top-1];
}
int StackSize(const Stack *pStack)
{
return pStack->top;
}
int StackFull(const Stack *pStack)
{
return pStack->top >= MAX_SIZE;
}
int StackEmpty(const Stack *pStack)
{
return pStack->top <= 0;
}
void StackCopy(Stack *pDest,Stack *pSrc)
{
memcpy(pDest->array, pSrc->array, sizeof(StackDataType)*pSrc->top);
pDest->top = pSrc->top;
}

Stack path;     //当前路径
Stack min;      //之前的最小路径

//简单迷宫
int gMaze[ROWS][COLS] = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 1 },
{ 0, 0, 1, 0, 0, 0 }
};
//入口
Position gEntry = { 5, 2 };
//判断是否走到出口,最后一列都是出口
int IsExit(Position pos)
{
if (pos.y == COLS - 1){
return 1;
}
else {
return 0;
}
}
//判断是否可以走,没有越界&&值是1
int CanPass(Position pos)
{
if (pos.x >= ROWS){
return 0;
}
if (pos.y >= COLS){
return 0;
}
return gMaze[pos.x][pos.y] == 1;
}
//打印路径
void PrintPath(Stack *pStack)
{
Position at;
for (int i = 0; i < pStack->top; i++){
at = pStack->array[i];
printf("x=%d y=%d\n", at.x, at.y);
}
}
//打印迷宫
void PrintMaze()
{
for (int i = 0; i < ROWS;i++){
for (int j = 0; j < COLS;j++){
if (gMaze[i][j] == 0)
{
printf("■", gMaze[i][j]);
}
else if (gMaze[i][j] == 1)
{
printf("  ", gMaze[i][j]);
}
else if (gMaze[i][j] == 2){
printf("☆", gMaze[i][j]);
}
}
printf("\n");
}
printf("\n\n");
}
//方法二
//调用栈做回溯,递归
void RunMazeRec(Position at)
{
Position next;
StackPush(&path,at);

//一进来标记我走过了
gMaze[at.x][at.y] = 2;
PrintMaze();

if (IsExit(at)){
//如果当前路径(path)小于之前的最小路径(min),最小路径是path
if (StackEmpty(&min) || StackSize(&path) < StackSize(&min)){
StackCopy(&min, &path);
//打印出最短路径
PrintPath(&path);
}
}
//根据左->上->右->下来尝试
//左
next.x = at.x;
next.y = at.y - 1;
if (CanPass(next)){
RunMazeRec(next);//递归
//PrintMaze();
}
//上
next.x = at.x - 1;
next.y = at.y;
if (CanPass(next)){
RunMazeRec(next);
//PrintMaze();
}
//右
next.x = at.x;
next.y = at.y + 1;
if (CanPass(next)){
RunMazeRec(next);
//PrintMaze();
}
//下
next.x = at.x + 1;
next.y = at.y;
if (CanPass(next)){
RunMazeRec(next);
//PrintMaze();
}
//如果at的四周都没法儿走,at重新置为1
gMaze[at.x][at.y] = 1;
StackPop(&path);
return;   //回溯
}

//方法一
//需要一个栈回溯,压栈出栈
void RunMaze()
{
Stack stack;
StackInit(&stack);
Position next;
Position at;
at.x = gEntry.x;
at.y = gEntry.y;

while (1){
//一进来标记我走过了
gMaze[at.x][at.y] = 2;
PrintMaze();
//把当前位置压入栈中,方便做回溯
StackPush(&stack, at);

if (IsExit(at)){
//如果到了出口,退出
PrintPath(&stack);
return;
}
//根据左->上->右->下来尝试
//左
next.x = at.x;
next.y = at.y - 1;
if (CanPass(next)){
at.x = next.x;
at.y = next.y;
continue;
}
//上
next.x = at.x - 1;
next.y = at.y;
if (CanPass(next)){
at.x = next.x;
at.y = next.y;
continue;
}
//右
next.x = at.x;
next.y = at.y + 1;
if (CanPass(next)){
at.x = next.x;
at.y = next.y;
continue;
}
//下
next.x = at.x + 1;
next.y = at.y;
if (CanPass(next)){
at.x = next.x;
at.y = next.y;
continue;
}
//如果四周都没法儿走,出栈
StackPop(&stack);
if (StackEmpty(&stack)){
printf("没有出口\n");
return;
}
at = StackTop(&stack);   //回溯
StackPop(&stack);
}
}
void testRunMazeRec()
{
StackInit(&path);
StackInit(&min);
PrintMaze();
RunMazeRec(gEntry);
}
int main()
{
PrintMaze();
//RunMaze();
testRunMazeRec();
system("pause");
return 0;
}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: