数据结构课设| |迷宫问题

迷宫问题

思想:分成了三大部分,头文件maze.h,函数功能源文件maze.c,测试源文件test.c

1.源文件maze.h

#ifndef __MAZE_H__
#define __MAZE_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <stdbool.h>

//迷宫的最大行列数
#define MAXSIZE 20

//迷宫起点,终点坐标类型
typedef struct fix
{
    int x;
    int y;
}Pos, *pPos;

//迷宫类型
typedef struct maze
{
    int row;//行
    int col;//列
    int wall;//墙的个数
    int arr_maze[MAXSIZE][MAXSIZE];
}Maze, *pMaze;

//栈类型
typedef struct
{
    int arr_stack[400][2]; //栈数组
    int top; //栈顶指针
}Stack, *pStack;

void ShowMaze(Maze maze, Pos terminal);
void ShowMazeStack(Maze maze, Pos terminal, Stack stack);
void ShowCreateMaze(Maze maze);
void CreatMazeRand(pMaze pmaze);
void CreatMazeMe(pMaze pmaze);
void CreatOrigo(pMaze pmaze, pPos origo);
void CreatTerminal(pMaze pmaze,pPos origo, pPos terminal);
void SolveMazePath(pMaze pmaze, Pos origo, Pos terminal);
void SolveMazePathAllRecursion(pMaze pmaze, Pos origo, Pos terminal);
void SolveMazePathAllStack(pMaze pmaze, Pos origo, Pos terminal, pStack stack);
void PopStack(pStack pstack);
void PushStack(pStack pstack, int x, int y);
void InitMaze(pMaze pmaze);
void InitOrigoTerminal(pMaze pmaze,pPos origo, pPos terminal);



#endif //__MAZE_H__

2.函数功能源文件maze.c

#include "maze.h"

void ShowMaze(Maze maze, Pos terminal)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < maze.row + 2; i++)
    {
        for (j = 0; j < maze.col + 2; j++)
        {
            if (maze.arr_maze[i][j] == 1)
            {
                printf("█");
            }
            else if (maze.arr_maze[i][j] == 2)
            {
                printf("◇");
            }
            else
            {
                printf("  ");
            }
        }
        printf("\n");
    }
    printf("展示完毕!\n");
}

void ShowMazeStack(Maze maze, Pos terminal, Stack stack)
{
    int i = 0;
    int j = 0;
    //次数计数器
    static count = 1;
    printf("方法%d:\n", count++);
    printf("图形展示:\n");
    for (i = 0; i < maze.row + 2; i++)
    {
        for (j = 0; j < maze.col + 2; j++)
        {
            if (maze.arr_maze[i][j] == 1)
            {
                printf("█");
            }
            else if (maze.arr_maze[i][j] == 2)
            {
                printf("◇");
            }
            else
            {
                printf("  ");
            }
        }
        printf("\n");
    }
    printf("坐标展示:\n");
    for (i = 0; i < stack.top; i++)
    {
        if (i != stack.top - 1)
        {
            printf("(%d,%d)-->", stack.arr_stack[i][0], stack.arr_stack[i][1]);
        }
        else
        {
            printf("(%d,%d)", stack.arr_stack[i][0], stack.arr_stack[i][1]);
        }
    }
    printf("展示完毕!\n");
}


void ShowCreateMaze(Maze maze)
{
    int i = 0;
    int j = 0;
    //坐标列
    for (i = 0; i <= maze.col; i++)
    {
        if (i == 0)
        {
            printf("%2d   ", i);
        }
        else
        {
            printf("%2d   ", i);
        }
    }
    printf("\n");
    for (i = 0; i <= maze.col; i++)
    {
        if (i == 0)
        {
            printf("    ");
        }
        else if (i == 1)
        {
            printf("----");
        }
        else
        {
            printf("-----");
        }
    }
    printf("\n");
    for (i = 1; i <= maze.row; i++)
    {
        //坐标行
        printf("%2d  |", i);
        for (j = 1; j <= maze.col; j++)
        {
            printf("%2d   ", maze.arr_maze[i][j]);
        }
        printf("\n\n");
    }
}

void CreatMazeRand(pMaze pmaze)
{
    int i = 0;
    int j = 0;
    bool flag = true;
    assert(pmaze != NULL);

    //迷宫大小
    while (flag)
    {
        printf("请输入迷宫的大小(行*列)<(MAXSIZAE * MAXSIZE)(MAXSIZE = %d):", MAXSIZE);
        scanf("%d*%d", &pmaze->row, &pmaze->col);
        if ((pmaze->row > MAXSIZE) || (pmaze->col > MAXSIZE))
        {
            printf("行列超出最大范围,请重新输入!\n");
            flag = true;
        }
        else
        {
            flag = false;
        }
    }

    //墙的个数
    flag = true;
    while (flag)
    {
        printf("请输入墙的个数(墙的个数要小于等于:<行*列>):");
        if (pmaze->wall > (pmaze->row * pmaze->col))
        {
            printf("墙的个数出错,请重新输入!\n");
            flag = true;
        }
        else
        {
            scanf("%d", &pmaze->wall);
            flag = false;
        }
    }
    
    //增加边框,并且全部赋值0
    memset(pmaze->arr_maze, 0, sizeof(pmaze->arr_maze));

    //边框全部变为1
    //第1行和最后1行
    for (i = 0; i < pmaze->col + 2; i++)
    {
        pmaze->arr_maze[0][i] = 1;
        pmaze->arr_maze[pmaze->row + 2 -1][i] = 1;
    }
    //第1列和最后1列
    for (i = 1; i < pmaze->row + 2 - 1; i++)
    {
        pmaze->arr_maze[i][0] = 1;
        pmaze->arr_maze[i][pmaze->col + 2 - 1] = 1;
    }
    //边框内部全部进行随机值赋值
    srand((unsigned int)time(NULL));
    while (pmaze->wall != 0)
    {
        int x = rand() % pmaze->row + 1;
        int y = rand() % pmaze->col + 1;
        if (pmaze->arr_maze[x][y] != 1)
        {
            pmaze->arr_maze[x][y] = 1;
            pmaze->wall--;
        }
    }
}

void CreatMazeMe(pMaze pmaze)
{
    int i = 0;
    int j = 0;
    assert(pmaze != NULL);
    printf("请输入迷宫的大小(行*列)>:");
    scanf("%d*%d", &pmaze->row, &pmaze->col);
    //增加边框,并且全部赋值0
    memset(pmaze->arr_maze, 0, sizeof(pmaze->arr_maze));
    //边框全部变为1
    //第1行和最后1行
    for (i = 0; i < pmaze->col + 2; i++)
    {
        pmaze->arr_maze[0][i] = 1;
        pmaze->arr_maze[pmaze->row + 2 - 1][i] = 1;
    }
    //第1列和最后1列
    for (i = 1; i < pmaze->row + 2 - 1; i++)
    {
        pmaze->arr_maze[i][0] = 1;
        pmaze->arr_maze[i][pmaze->col + 2 - 1] = 1;
    }
    //自己输入要创建的迷宫
    for (i = 1; i < pmaze->row + 2 - 1; i++)
    {
        printf("迷宫第%d行>:", i);
        for (j = 1; j < pmaze->col + 2 - 1; j++)
        {
            scanf("%d", &pmaze->arr_maze[i][j]);
        }
        printf("\n");
    }
}

void CreatOrigo(pMaze pmaze, pPos origo)
{
    bool flag = 0;
    assert(pmaze != NULL);
    flag = true;
    printf("请输入你要选择的入口(x,y)>:");
    while (flag)
    {
        scanf("%d,%d", &origo->x, &origo->y);
        if (pmaze->arr_maze[origo->x][origo->y] != 1)
        {
            //pmaze->arr_maze[origo->x][origo->y] = 6;
            flag = false;
        }
        else
        {
            printf("您创建的入口已被占用,请重新创建:>");
            flag = true;
        }
    }
}

void CreatTerminal(pMaze pmaze, pPos origo, pPos terminal)
{
    bool flag = 0;
    assert(pmaze != NULL);
    flag = true;
    printf("请输入你要选择的出口(x,y)>:");
    //确保创建的出口不是入口,并且出口不是墙
    while (flag)
    {
        scanf("%d,%d", &terminal->x, &terminal->y);
        //终点既不能等于1,也不能等于6
        if (pmaze->arr_maze[terminal->x][terminal->y] != 1) 
        {
            //确保出口不是入口
            if ((terminal->x != origo->x) && (terminal->y != origo->y))
            {
                flag = false;
            }
        }
        else
        {
            printf("您创建的出口已被占用,请重新创建:>");
            flag = true;
        }
    }
}

void recursion_showmaze_all(pMaze pmaze, int x, int y, Pos origo, Pos terminal)
{
    pmaze->arr_maze[x][y] = 2;

    if (x == terminal.x && y == terminal.y)
    {
        ShowMaze(*pmaze, terminal);
    }
    //向下走
    if ((x <= pmaze->row) && (pmaze->arr_maze[x + 1][y]) == 0)
    {
        recursion_showmaze_all(pmaze, x + 1, y, origo, terminal);
    }
    //向右走
    if ((y <= pmaze->col) && (pmaze->arr_maze[x][y + 1]) == 0)
    {
        recursion_showmaze_all(pmaze, x, y + 1, origo, terminal);
    }
    //向左走
    if ((y >= 1) && (pmaze->arr_maze[x][y - 1]) == 0)
    {
        recursion_showmaze_all(pmaze, x, y - 1, origo, terminal);
    }
    //向上走
    if ((x >= 1) && (pmaze->arr_maze[x - 1][y]) == 0)
    {
        recursion_showmaze_all(pmaze, x - 1, y, origo, terminal);
    }


    //如果一个点周围四个方向都走不了,那么就将改点赋值为0
    pmaze->arr_maze[x][y] = 0;
}

void SolveMazePathAllRecursion(pMaze pmaze, Pos origo, Pos terminal)
{
    recursion_showmaze_all(pmaze, origo.x, origo.y, origo, terminal);
}

void PushStack(pStack pstack,int x, int y)
{
    assert(pstack != NULL);
    pstack->arr_stack[pstack->top][0] = x;
    pstack->arr_stack[pstack->top][1] = y;
    pstack->top++;
}

void PopStack(pStack pstack)
{
    assert(pstack != NULL);
    pstack->top--;
}

void showmaze_stack(pMaze pmaze, int x, int y, Pos origo, Pos terminal, pStack pstack)
{
    PushStack(pstack, x, y);
    pmaze->arr_maze[x][y] = 2;
    if (x == terminal.x && y == terminal.y)
    {
        ShowMazeStack(*pmaze, terminal, *pstack);
    }
    //向下走
    if ((x <= pmaze->row) && (pmaze->arr_maze[x + 1][y]) == 0)
    {
        showmaze_stack(pmaze, x + 1, y, origo, terminal, pstack);
    }
    //向右走
    if ((y <= pmaze->col) && (pmaze->arr_maze[x][y + 1]) == 0)
    {
        showmaze_stack(pmaze, x, y + 1, origo, terminal, pstack);
    }
    //向左走
    if ((y >= 1) && (pmaze->arr_maze[x][y - 1]) == 0)
    {
        showmaze_stack(pmaze, x, y - 1, origo, terminal, pstack);
    }
    //向上走
    if ((x >= 1) && (pmaze->arr_maze[x - 1][y]) == 0)
    {
        showmaze_stack(pmaze, x - 1, y, origo, terminal, pstack);
    }

    pmaze->arr_maze[x][y] = 0;
    PopStack(pstack);
}


void SolveMazePathAllStack(pMaze pmaze, Pos origo, Pos terminal, pStack pstack)
{
    showmaze_stack(pmaze, origo.x, origo.y, origo, terminal, pstack);
}

int recursion_showmaze(pMaze pmaze,int x, int y, Pos origo, Pos terminal)
{
    //该点走过,标记为2
    pmaze->arr_maze[x][y] = 2;
    //判断是否成功
    int success = 0;
    //走到终点,成功
    if (x == terminal.x && y == terminal.y)
    {
        ShowMaze(*pmaze, terminal);
        success = 1;
    }
    //向下走
    if ((success != 1) && (pmaze->arr_maze[x + 1][y]) == 0)
    {
        recursion_showmaze(pmaze, x + 1, y, origo, terminal);
    }
    //向右走
    if ((success != 1) && (pmaze->arr_maze[x][y + 1]) == 0) 
    {
        recursion_showmaze(pmaze, x, y + 1, origo, terminal);
    }
    //向左走
    if ((success != 1) && (pmaze->arr_maze[x][y - 1]) == 0)
    {
        recursion_showmaze(pmaze, x, y - 1, origo, terminal);
    }
    //向上走
    if ((success != 1) && (pmaze->arr_maze[x - 1][y]) == 0)
    {
        recursion_showmaze(pmaze, x - 1, y, origo, terminal);
    }
    //该点走过,但没成功,则该点重新置为0
    if (success != 1)
    {
        pmaze->arr_maze[x][y] = 0;
    }
    return success;
}

void SolveMazePath(pMaze pmaze, Pos origo, Pos terminal)
{
    assert(pmaze != NULL);
    recursion_showmaze(pmaze, origo.x, origo.y, origo, terminal);
    pmaze->arr_maze[terminal.x][terminal.y] = 0;
}

void InitMaze(pMaze pmaze)
{
    assert(pmaze != NULL);
    //销毁对其全部都赋0
    memset(pmaze->arr_maze, 0, sizeof(pmaze->arr_maze));
}

void InitOrigoTerminal(pMaze pmaze,pPos origo, pPos terminal)
{
    assert(origo != NULL);
    assert(terminal != NULL);
    assert(terminal != NULL);
    origo->x = 1;
    origo->y = 1;
    terminal->x = pmaze->row;
    terminal->y = pmaze->col;
}

3.测试源文件test.c

#include "maze.h"


void menu()
{
    printf("\t\t\t\t******************************************\n");
    printf("\t\t\t\t*****        迷宫问题                *****\n");
    printf("\t\t\t\t*****     1.系统创建迷宫             *****\n");
    printf("\t\t\t\t*****     2.自己创建迷宫             *****\n");
    printf("\t\t\t\t*****     3.展示创建的迷宫           *****\n");
    printf("\t\t\t\t*****     4.给迷宫入口               *****\n");
    printf("\t\t\t\t*****     5.给迷宫出口               *****\n");
    printf("\t\t\t\t*****     6.求该迷宫的一种路径       *****\n");
    printf("\t\t\t\t*****     7.求该迷宫的所有路径(递归) *****\n");
    printf("\t\t\t\t*****     8.求该迷宫的所有路径(栈)   *****\n");
    printf("\t\t\t\t*****     9.重新开始                 *****\n");
    printf("\t\t\t\t*****     0.退出程序                 *****\n");
    printf("\t\t\t\t******************************************\n");
}

void test()
{
    int input = 1;
    Maze maze = { 0 };
    Pos origo = { 0 };
    Pos terminal = { 0 };
    Stack stack = { 0 };
    menu();
    while (input != 0)
    {
        printf("请选择功能(输入功能序号即可)>:");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
        {
            CreatMazeRand(&maze);
            //默认(1,1)为入口
            origo.x = 1;
            origo.y = 1;
            //默认(maze.row,maze.col)为出口
            terminal.x = maze.row;
            terminal.y = maze.col;
        }
            break;
        case 2:
        {
            CreatMazeMe(&maze);
            //默认(1,1)为入口
            origo.x = 1;
            origo.y = 1;
            //默认(maze.row,maze.col)为出口
            terminal.x = maze.row;
            terminal.y = maze.col;
        }
            break;
        case 3:
        {
            ShowCreateMaze(maze);
        }
            break;
        case 4:
        {
            //起点是4
            CreatOrigo(&maze, &origo);
        }
            break;
        case 5:
        {
            //终点是5
            CreatTerminal(&maze, &origo, &terminal);
        }
            break;
        case 6:
        {
            printf("如果没有给出口与入口的话。默认入口为左上角,出口为右下角!\n");
            SolveMazePath(&maze, origo, terminal);
        }
            break;
        case 7:
        {
            printf("如果没有给出口与入口的话。默认入口为左上角,出口为右下角!\n");
            SolveMazePathAllRecursion(&maze, origo, terminal);
        }
            break;
        case 8:
        {
            printf("如果没有给出口与入口的话。默认入口为左上角,出口为右下角!\n");
            SolveMazePathAllStack(&maze, origo, terminal, &stack);
        }
            break;
        case 9:
        {
            //数组要置为零,并且出口和入口要重置
            InitMaze(&maze);
            InitOrigoTerminal(&maze, &origo, &terminal);
            printf("重置完成!可以重新开始游戏了.\n");
        }
            break;
        case 0:
        {
            printf("程序结束!\n");
        }
            break;
        default:
        {
            printf("功能选择错误!请重新选择!\n");
        }
            break;
        };
    }
}

int main()
{
    test();
    return 0;
}

这就是所有代码了,欢迎观看!

猜你喜欢

转载自blog.csdn.net/qq_40399012/article/details/80827309