以前把代码上传过,通过上传资源,后来才发现上传的资源CSDN收费下载……
现在放到文章里
去年,2020年写的代码
记忆中,accessMazePrime和move函数是在网上搜的代码
生成随机迷宫,设置迷宫难度,Prim算法查找迷宫出口,用户自己走迷宫这几个功能。
#include#include #include // 用来定位,刷新指定位置 局部刷新 #define random(x) (rand()%x) // 生成不重复的随机数 int ** initMaze(int row, int column); //优雅 // 分配地址,初始化迷宫 void accessMazePrime(int row, int column, int **maze); // 生成随机迷宫 void printMaze(int row, int column, int **maze); // 打印整个迷宫,局部刷新前调用用来初始化 void freeMaze(int **maze, int row); // 释放二维迷宫数组空间 void move(int row, int column, int **maze); //迷宫移动 // 用户控制迷宫移动 wasd void showMain(); // 显示主函数界面 int ** initVisited(int **visited, int row, int column); // 初始化一个二维数组,元素值为0或1,标记是否访问过该结点 void pathFind(int **visited, int **maze, int x, int y, int *DA_x, int *SW_y, int row, int column, int *pFindExitFlag); // 查找迷宫路径,寻找出口 int selectOption(int smaller, int bigger); // 两个参数表示范围,要求:smaller < 返回值 < bigger void mazeGameDescription(); // 游戏说明 void mazeGame(); // 系统创建迷宫,集成了初始化迷宫,生成迷宫,寻找迷宫出口等功能,在主函数中调用 int selectSize(); // 选择迷宫尺寸 -- 难度 void showSelectSizeMenu(); // 显示难度菜单 void showUserOrSystemPathFindMenu(); // 显示开始游戏的方式,计算机进行游戏,用户进行游戏,在选定难度之后调用 void systemFindMazeExit(int row, int column, int **maze); // 计算机查找迷宫出口 void setMazeBeginAndEnd(int row, int column, int **maze); // 设置迷宫的起点和终点 void gotoxy(int x, int y); // 定位指定位置,坐标从(0,0)开始 void putcharMaze (int mazeNum); // 根据二位数组元素的值打印指定的字符 void gotoxyAndPutchar (int x, int y, int **maze); // 定位指定的坐标(x,y),并根据maze[y][x]的值打印指定的字符,用于局部刷新,gotoxy()和putcharMaze()的集成 // 猜测不malloc,地址不变 // malloc 本质上是重新分配了地址空间,所以指针变量指向的地址空间会改变,所以要return 地址给指针变量 // 而其他情况,例如对分配好地址空间的变量,用指针在函数之间传递,改变指针指向的变量的值,其地址不变,不需要return返回变量地址,因为地址并没有改变 // 对指针在函数间传递有了更深的理解,不再是简单的 传递指针,修改变量的值,指针指向的变量不变,有了更深层次的理解,又回归了概念。收获满满。 int main(void) { int option; // 选项 while (1) { showMain(); // 调用主函数菜单 option = selectOption(0,2); // 获取用户选择 switch (option) { case 1:mazeGame();break; // 迷宫游戏 case 2:mazeGameDescription();break; // 游戏说明 case 0:return 0; // 退出程序 default:; } printf("按任意键继续"); getch(); } } void gotoxyAndPutchar (int x, int y, int **maze) { // 局部刷新 gotoxy(x,y); // 调用函数定位,坐标为(x,y),(0,0)开始 putcharMaze(maze[y][x]); // 根据(x,y)位置对应的maze[y][x]值,输出对应的字符 } void gotoxy(int x, int y) { //COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标 COORD cor; //句柄 HANDLE hout; //设定我们要定位到的坐标 cor.X = x; cor.Y = y; //GetStdHandle函数获取一个指向特定标准设备的句柄,包括标准输入,标准输出和标准错误。 //STD_OUTPUT_HANDLE正是代表标准输出(也就是显示屏)的宏 hout = GetStdHandle(STD_OUTPUT_HANDLE); //SetConsoleCursorPosition函数用于设置控制台光标的位置 SetConsoleCursorPosition(hout, cor); } void mazeGame() { int size; // 迷宫尺寸 迷宫难度 int endFlag = 0; while (1) { showSelectSizeMenu(); size = selectSize(); if (size != 0) { // 判断是否进行游戏,是,选择难度;否,返回主菜单 int row, column; int **maze; int option; switch(size){ // 设置迷宫的尺寸 --难度 case 1: row=10;column=20;break; case 2: row=15;column=30;break; case 3: row=20;column=40;break; } maze = initMaze(row, column); // 分配地址,迷宫数组初始化 accessMazePrime(row, column, maze); // 随机生成迷宫 setMazeBeginAndEnd(row, column, maze); // 设置迷宫起点和终点 showUserOrSystemPathFindMenu(); // 显示菜单 option = selectOption(0,3); switch(option) { case 1:move(row, column, maze);break; // 用户操作闯关 case 2:systemFindMazeExit(row, column, maze);break; // 计算机查找迷宫路径 case 3:break; // 返回上一级菜单 case 0:endFlag=1;break; // 返回主菜单 default :; } freeMaze(maze, row); // 释放资源 if (endFlag == 1) { // 返回主菜单 break; } } else { // 返回主菜单 break; } } } void setMazeBeginAndEnd(int row, int column, int **maze) { maze[1][1]=3; // 设置起点 maze[row*2-1][column*2]=0; // 设置终点 } void showUserOrSystemPathFindMenu() { int i; printf("n -- 1. 开始游戏 2. 计算机寻找迷宫出口 3. 返回上一级 0. 返回主菜单 --n"); for (i=0; i<80; i++) { printf ("-"); } printf("n"); } void systemFindMazeExit(int row, int column, int **maze) { int SW_y[] = { 0, 1, 0, -1 }; // 该数组定义四个元素,分别对应 右、下、左、上四个方向。例如向下移动,则y+SW_y[1]。 int DA_x[] = { 1, 0, -1, 0 }; // 该数组同上一个数组类似,x+DA_x[i] int **visited; // 指针,一个二维数组的指针,用于标记结点是否访问过,访问为1,未访问为0 int findExitFlag = 0; // 标记是否找到迷宫出口,找到为1 int *pFindExitFlag = &findExitFlag; // 指针指向findExitFlag,确保参数传递时可以修改值 visited = initVisited(visited, row, column); // 初始化visited数组,赋地址 // 初始化迷宫 system("cls"); printMaze(row,column,maze); pathFind(visited, maze, 1, 1, DA_x, SW_y, row, column, pFindExitFlag); // 递归,计算机递归的查找迷宫出口 freeMaze(visited, row); // 释放 } int selectSize() { // 选择难度 int size; size = selectOption(0,3); return size; } void showSelectSizeMenu() { int i; printf ("nttt -- 迷 宫 难 度 选 择 --nn"); printf("n"); printf("tt -- 1.初级 2.中级 3.高级 0.退出 -- n"); for (i=0; i<80; i++) { printf ("-"); } printf("n"); } void mazeGameDescription() { printf("nttt -- 迷 宫 游 戏 说 明 --n"); printf("t--操作说明:请切换为英文输入法,按w(上↑),a(左←),s(下↓),d(右→)移动n"); printf("t--开始高级迷宫时,建议全屏开始游戏nn"); } int ** initVisited(int **visited, int row, int column) { // 分配地址空间,初始化 int i, j; int r=row*2+1, c=column*2+1; visited = (int**)malloc(r*sizeof(int*)); // 存行地址 for(i=0; i -1 && move_x > -1 && move_x < row && move_y < column && repos >= 0 && repos < count && noacc[repos] != 0) { noacc[repos] = 0; // 访问过结点,在未访问结点中取出 acc[++accsize] = repos; // 第二个结点,新的结点,迷宫路径 添加结点到已访问队列 pos = repos; // pos指向新的结点 offpos = point; // 偏移量 //相邻的格子中间的位置放1 maze[2 * x + 1 + offR[point]][ 2 * y + 1 + offC[point]] = 0; //将新结点对应的迷宫位置的墙破开,因为初始化时奇数位LabId[奇数][奇数]=0,是路径,没有墙,起点不是墙,上下左右偏移一位都会是墙 break; } else { if (accsize == count - 1)// 是否到达最大的路径结点数,是就结束,不是就进行下一次循环 return ; // 此处也不需要返回指针值了,因为指针指向的变量地址没有改变,函数改成void即可 continue; } } if (offpos < 0) // 四个方向都已经访问过一次或是边界,找不到路 {// 周边没有找到能走的路了 从走过的路里重新找个起点 pos = acc[random(accsize + 1)]; } } } int **initMaze(int row, int column) { int r = 2 * row + 1, c = 2 * column + 1; int i, j; int **maze; maze = (int**)malloc(r*sizeof(int*)); for(i=0; i bigger) // 当输入的选择不在smaller到bigger时,重新选择 { printf ("该选项不存在,请重新输入:"); scanf ("%d", &option); //输入选项 getchar(); } return option; }



