迷宫问题
思想:分成了三大部分,头文件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; }
这就是所有代码了,欢迎观看!