C语言 栈 数据结构 迷宫求解(附完整代码)

一、程序设计思路

1、题目:应用栈实现迷宫游戏

要求:以书中3.2.4节迷宫求解为基础实现迷宫游戏,游戏运行时显示一个迷宫地图(迷宫内容结构可以参照书中图片,也可以自己编写),玩家从地图左上角的入口处进入迷宫,从右下角出口离开迷宫。玩家不能穿墙而过。

2、解决思路

采用“穷举求解”方法,需要用到栈,从入口开始,往四个方向走,依次将走过的坐标点–入栈;如果走到“死路”,就出栈;一一循环;最后栈中保存的就是出迷宫的路线。

3、算法描述

求迷宫中一条从入口到出口的路径的算法可简单描述如下:

设当前位置的初值为入口位置;

do{
若当前位置可通,
则{
将当前位置压至栈顶; //纳入路径
如果当前位置是出口位置,则结束;
否则切换当前位置的东邻方块为新的当前位置;
}
否则,
若栈不为空且栈顶位置尚有其他方向未经探索,
则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻方块;
若栈不为空且栈顶位置的四周均不可通,
则{
删去栈顶位置;
若栈不为空,则重新测试新的栈顶位置,
直至找到一个可通的相邻块或者出栈至栈空;
}
}while(栈不为空);

二、程序源代码
栈部分




#include "stdafx.h"                //包含标准C的头文件,stdio.h,string.h等

#include <malloc.h>               //动态储存分配函数头文件,用于栈的储存空间分配

#include <stdlib.h>               //standard library标准库头文件

typedef int DirectiveType;        //下一个通道方向  

#define RANGE 100                 //迷宫大小  

#define STACK_INIT_SIZE 100       //定义栈的初始大小

#define STACKINCREMENT    10      //定义栈的储存增量,在栈长度越界时

typedef int DirectiveType;        //下一个通道方向  

#define RANGE 100                 //迷宫大小  

#define ROW 10                    //迷宫的行数

#define COL 10                    //迷宫的列数    

 

typedef struct        

{

    int m, n;

    int arr[RANGE][RANGE];       //迷宫数组

}MazeType;                       //迷宫的类型

 

typedef struct

{

    int row;                     //迷宫中的行

    int col;                     //迷宫中的列

}PosType;                        //坐标(row,col)

 

typedef struct

{

    int step;                    //当前位置在路径上的"序号"

    PosType seat;                //当前的坐标位置

    DirectiveType di;            //往下一个坐标位置的方向

}SElemType;                      //栈的元素类型

 

typedef struct

{

    SElemType *base;             //栈底

    SElemType *top;              //栈顶

    int stacksize;               //栈的大小

}SqStack;                        //定义栈

 

bool InitStack(SqStack &s)

{                                //栈的初始化

    s.base = (SElemType
*)malloc(STACK_INIT_SIZE * sizeof(SElemType));

    if (!s.base)

    {

       exit(-2);

    }

    s.top = s.base;

    s.stacksize = STACK_INIT_SIZE;

    return true;

}

 

bool GetTop(SqStack s, SElemType &e)  
//当栈s不为空时,返回栈顶e

{

    if (s.top == s.base)

       return false;

    e = *(s.top - 1);

    return true;

}

 

bool Push(SqStack &s, SElemType e)    
//在栈s中插入元素e,入栈

{

    if (s.top - s.base >=
s.stacksize)

    {                                 //若栈满,追加存储空间

       s.base = (SElemType
*)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(SElemType));

       if (!s.base)

           exit(-2);  

       s.top = s.base + s.stacksize;

       s.stacksize += STACKINCREMENT;

    }

    *s.top++ = e;

    return true;

}

 

bool Pop(SqStack &s, SElemType &e)     //在栈s中删除栈顶,出栈

{

    if (s.top == s.base)               //当栈空时

       return false;                  //返回错误

    e = *--s.top;                      //e指向新栈顶

    return true;

}

 

bool StackEmpty(SqStack s)            
//栈判空

{

    return s.base == s.top;            

}

 

bool DestoryStack(SqStack &s)         
//销毁栈

{

    free(&s);                          //释放栈s的储存空间

    return true;

}


迷宫部分



bool InitMaze(MazeType &maze, int a[ROW][COL], int row, int col)  //初始化迷宫

{

    int i, j;                            //设置迷宫maze的初值,包括加上边缘一圈的值

    for (i = 1; i<row - 1;
i++)         

    {

       for (j = 1; j<col - 1; j++)

       {

           maze.arr[i][j] = a[i][j];

       }

    }                                          

    for (j = 0; j<row; j++)                     //加上围墙

       maze.arr[0][j] = maze.arr[row
- 1][j] = 1;

    for (i = 0; i<col; i++)

       maze.arr[i][0] =
maze.arr[i][col - 1] = 1;

    return true;

}

 

bool Pass(MazeType maze, PosType curpos)

{                                                 
//判断当前节点是否通过

    if (maze.arr[curpos.row][curpos.col]
== 0)     //当节点为0时返回真

       return true;

    else

       return false;

}

 

bool FootPrint(MazeType &maze, PosType curpos)

{                                                  
//留下足迹

    maze.arr[curpos.row][curpos.col]
= 2;           //走过且走得通

    return true;

}

 

bool MarkPrint(MazeType &maze, PosType curpos)

{                                                  
//留下不能通过的标记

    maze.arr[curpos.row][curpos.col]
= 3;           //走过但走不通

    return true;

}

 

SElemType CreateSElem(int step, PosType pos, int di)

{                                                   
//创建元素e

    SElemType e;

    e.step = step;

    e.seat = pos;

    e.di = di;

    return e;

}

 

PosType NextPos(PosType curpos, DirectiveType di)   //curpos当前位置

{                                                  
//返回当前节点的下一节点

    PosType pos = curpos;

    switch (di)

    {

    case 1:        //右

       pos.col++;

       break;

    case 2:        //下

       pos.row++;

       break;

    case 3:        //左

       pos.col--;

       break;

    case 4:        //上

       pos.row--;

       break;

    }

    return pos;

}

 

bool PosEqual(PosType pos1, PosType pos2)

{                                               
//判断是不是出口

    if (pos1.row == pos2.row
&& pos1.col == pos2.col)    

       return true;                            

    else

       return false;

}

 

void PrintMaze(MazeType maze, int row, int col)

{                                               
//打印路径

    int i, j;

    printf(" ");

    for (i = 0; i<col; i++)                    //打印列数名

       printf("%d ", i);

    printf("\n");

    for (i = 0; i<row; i++)

    {

       printf("%d",
i);                      //打印行数名

       for (j = 0; j<col; j++)

       {

           switch (maze.arr[i][j])

           {

           case 0:

              printf("  ");                 //没走过,但是通路

              break;

           case 1:

              printf("■");                  //墙,障碍物

              break;

           case 2:

              printf("*
");                 //走过且走得通

              break;

           case 3:

              printf("@
");                 //走过但走不通,死胡同

              break;

           default:

              break;

           }

       }

       printf("\n");

    }

}

 

bool MazePath(MazeType &maze, PosType start, PosType end)

{                               //求解迷宫maze中,从入口start到出口end的一条路径

    SqStack s;                  //定义栈

    SElemType e;            

    InitStack(s);               //初始化栈

    PosType curpos = start;             

    int curstep = 1;                                //探索第一步

    do {

       if (Pass(maze, curpos))

       {    //如果当前位置可以通过,即是未曾走到的通道块

           FootPrint(maze,
curpos);                //留下足迹

           e = CreateSElem(curstep,
curpos, 1);    //创建元素

           Push(s, e);                             //加入路径

           if (PosEqual(curpos,
end))              //到达终点(出口)

              return true;                        

           curpos = NextPos(curpos,
1);            //获得下一节点

           curstep++;                              //探索下一步

       }

       else 

       {                                           //当前位置不能通过

           if (!StackEmpty(s))

           {

              Pop(s, e);

              while (e.di == 4
&& !StackEmpty(s)) //找寻了四个方向

              {

                  MarkPrint(maze,
e.seat);

                  Pop(s, e);                      //留下不能通过的标记,并退回一步

              }

              if (e.di<4)

              {

                  e.di++;                         //换一个方向探索

                  Push(s, e);

                  curpos =
NextPos(e.seat, e.di); //设定当前位置是该方向上的相邻块

              }

           }

       }

    } while (!StackEmpty(s));

    return false;

}

 


主函数部分



int main()                   //迷宫求解主函数

{

    int i, j;                

    PosType start, end;      //开始,终点坐标

    MazeType maze;           

    int a[ROW][COL] = {                 //原始迷宫,其中'1'表示墙,'0'表示通道

       { 1,1,1,1,1,1,1,1,1,1 },

       { 1,0,0,1,0,0,0,1,0,1 },

       { 1,0,0,1,0,0,0,1,0,1 },

       { 1,0,0,0,0,1,1,0,0,1 },

       { 1,0,1,1,1,0,0,0,0,1 },

       { 1,0,0,0,1,0,0,0,0,1 },

       { 1,0,1,0,0,0,1,0,0,1 },

       { 1,0,1,1,1,0,1,1,0,1 },

       { 1,1,0,0,0,0,0,0,0,1 },

       { 1,1,1,1,1,1,1,1,1,1 }

    };

    printf("\n-------------------------------------------------\n");

    printf("\n原始迷宫如下:\n");

    printf("(其中'1'表示墙,'0'表示通道)\n");

    for (i = 0; i<10; i++)           //双重循环输出原始迷宫

    {

       for (j = 0; j<10; j++)

       {

           printf("%d ",
a[i][j]);

       }

       printf("\n");

    }

    InitMaze(maze, a, ROW, COL);                 //初始化迷宫

    start.row = 1;                               //给定迷宫起点坐标

    start.col = 1;                               //(1,1)

    end.row = 8;                                 //给定迷宫终点坐标   

    end.col = 8;                                 //(8,8)

    if (MazePath(maze, start,
end))              //如果找到一条路径

    {

       printf("\n-------------------------------------------------\n");

       printf("\n穷举法求解迷宫路径如下:\n");

       printf("(其中'*'表示求解路径,'@'表示死胡同)\n");

       PrintMaze(maze, ROW,
COL);               //输出迷宫路径

    }

    else                                         //否则,没有通路

       printf("\n---------从入口到出口没有通路!-----\n");

}


三、运行结果
迷宫求解

附:源代码链接迷宫求解源代码

  • 68
    点赞
  • 458
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: 好的,下面是用 C 语言实现的迷宫求解代码。这里我们使用来存储路径。 首先,我们需要定义一些常量和结构体: ``` #define N 10 // 迷宫的大小 #define M 2 // 走到下一步所需的步数 #define S 2 // 两种走法:向左或向右 // 定义点的坐标结构体 struct point { int x, y; } st; // 定义的结构体 struct stack { point data[N * N]; // 内存储的点 int top; // 顶元素的下标 } stk; ``` 然后,我们可以实现一个函数来判断某个点是否可以走: ``` // 判断点 p 是否可以走 int pd(point p) { // 判断是否越界 if (p.x < 0 || p.x >= N || p.y < 0 || p.y >= N) return 0; // 判断是否是障碍 if (maze[p.x][p.y] == 1) return 0; // 判断是否已经走过 if (book[p.x][p.y] == 1) return 0; return 1; } ``` 接下来,我们可以实现一个函数来搜索迷宫: ``` // 搜索迷宫 void dfs(point p) { // 将当前点压入中 stk.data[stk.top++] = p; // 标记当前点已经走过 book[p.x][p.y] = 1; // 如果到达终点,则输出路径 if (p.x == N - 1 && p.y == N - 1) { for (int i = 0; i < stk.top; i++) { printf("(%d, ### 回答2: 以下是一个使用求解迷宫问题的C语言完整代码: ```c #include <stdio.h> #define MAX_SIZE 100 typedef struct { int x; //位置的横坐标 int y; //位置的纵坐标 int direction; //当前位置的前进方向 } Position; int main() { int maze[5][5] = { //定义一个5x5的迷宫,1表示墙,0表示通路 {0, 1, 1, 0, 0}, {0, 0, 0, 1, 0}, {1, 1, 0, 1, 0}, {1, 1, 0, 0, 0}, {0, 0, 0, 1, 0} }; int visited[5][5] = {0}; //定义一个5x5的数组记录已经访问过的位置 Position stack[MAX_SIZE]; //定义一个大小为MAX_SIZE的 int top = -1; //初始为空 Position startPos, endPos; startPos.x = 0; startPos.y = 0; startPos.direction = 0; endPos.x = 4; endPos.y = 4; stack[++top] = startPos; //将起始位置入 while (top != -1) { //当非空时,继续搜索 Position curPos = stack[top]; //获取顶位置 visited[curPos.x][curPos.y] = 1; //标记当前位置为已访问 if (curPos.x == endPos.x && curPos.y == endPos.y) { //找到终点,返回路径 for (int i = 0; i <= top; i++) { printf("(%d, %d) ", stack[i].x, stack[i].y); } printf("\n"); return 0; } int i; for (i = curPos.direction; i <= 3; i++) { //按照右、下、左、上的顺序依次尝试移动 Position nextPos; nextPos.direction = i + 1; //更新下个位置的前进方向 switch (i) { case 0: //向右 nextPos.x = curPos.x + 1; nextPos.y = curPos.y; break; case 1: //向下 nextPos.x = curPos.x; nextPos.y = curPos.y + 1; break; case 2: //向左 nextPos.x = curPos.x - 1; nextPos.y = curPos.y; break; case 3: //向上 nextPos.x = curPos.x; nextPos.y = curPos.y - 1; break; } if (nextPos.x >= 0 && nextPos.x < 5 //判断是否越界 && nextPos.y >= 0 && nextPos.y < 5 && maze[nextPos.x][nextPos.y] == 0 && visited[nextPos.x][nextPos.y] == 0) { //判断是否为通路且未访问过 stack[++top] = nextPos; //将下个位置入 break; //搜索下一个位置 } } if (i > 3) { //上个位置的所有方向都无法继续移动,退继续搜索 top--; } } printf("无法找到路径。\n"); return 0; } ``` 该代码通过使用来实现深度优先搜索(DFS)的思想,从起点开始不断尝试移动到相邻的可走位置,直到找到终点或无法继续移动为止。同时,利用visited数组来记录已经访问过的位置,避免重复访问。当找到终点时,将中的位置逐个输出,即为迷宫的求解路径。 ### 回答3: 迷宫求解算法是一种常见的问题,可以使用深度优先搜索(DFS)结合数据结构来解决。下面是一个C语言中使用来求解迷宫的完整代码。 ```c #include<stdio.h> #include<stdlib.h> #define ROW 8 //迷宫行数 #define COL 8 //迷宫列数 // 定义坐标结构体 typedef struct { int x; int y; } Coordinate; // 定义的结构体 typedef struct { Coordinate position[ROW * COL]; int top; } Stack; // 初始化 void initStack(Stack* stack) { stack->top = -1; } // 是否为空 int isStackEmpty(Stack* stack) { return stack->top == -1; } // 入 void push(Stack* stack, Coordinate coord) { stack->position[++stack->top] = coord; } // 出 Coordinate pop(Stack* stack) { return stack->position[stack->top--]; } // 迷宫求解函数 void mazeSolver(int maze[ROW][COL], Coordinate entry, Coordinate exit) { Stack stack; Coordinate current = entry; initStack(&stack); push(&stack, current); while (!isStackEmpty(&stack)) { current = pop(&stack); int x = current.x; int y = current.y; // 如果到达出口,则退出循环 if (x == exit.x && y == exit.y) { printf("Successfully solved the maze!\n"); return; } // 标记当前位置已被访问 maze[x][y] = 2; // 下一步可能的方向 Coordinate next[4] = { {x-1, y}, // 上 {x, y+1}, // 右 {x+1, y}, // 下 {x, y-1} // 左 }; // 将下一步可能的位置入 for (int i = 0; i < 4; i++) { int nextX = next[i].x; int nextY = next[i].y; // 判断下一步是否为合法位置 if (nextX >= 0 && nextY >= 0 && nextX < ROW && nextY < COL && maze[nextX][nextY] == 0) { Coordinate nextCoord = {nextX, nextY}; push(&stack, nextCoord); } } } printf("Failed to solve the maze!\n"); } int main() { int maze[ROW][COL] = { {1, 1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 1, 0, 0, 0, 1}, {1, 0, 0, 1, 0, 0, 1, 1}, {1, 1, 0, 0, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1} }; Coordinate entry = {1, 1}; Coordinate exit = {6, 6}; mazeSolver(maze, entry, exit); return 0; } ``` 这段代码首先定义了迷宫的行数和列数,以及坐标和数据结构迷宫求解函数中使用深度优先搜索算法来遍历迷宫并寻找路径,通过入和出操作来回溯遍历过程。在一个8x8的迷宫中,1代表墙壁,0代表通路,2代表已访问过的路径。程序通过来存储下一步可能的位置坐标,直到找到出口或者所有可能路径都已访问完。主函数中定义了一个迷宫数组,以及入口和出口的坐标,然后调用迷宫求解函数来解决迷宫问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值