登录
这段代码实现了一个简单的登录功能。具体实现过程如下:
- 首先清屏,然后输出登录界面的提示信息。
- 用户输入用户名和密码。用户名通过gets()函数获取,密码则通过getch()函数一个一个字符输入,并用星号进行掩盖,以保证安全性。同时,当用户输入退格键时,会将前面输入的星号用空格覆盖,以便用户重新输入。
- 将用户名和密码合并为一个字符串,添加换行字符,并打开user.txt文件进行读取。
- 读取文件内容,并将每行内容与用户输入的用户名和密码进行比较,如果匹配成功,则将ok变量设为1,退出循环。
- 如果匹配成功,则输出登录成功的提示信息,并等待1秒后进入下一步操作。
- 如果匹配失败,则输出登录失败的提示信息,并等待1秒后清屏,再次调用loginOrRegister()函数,让用户选择登录或注册。
- 最后关闭文件并退出函数。
需要注意的是,该代码存在一些潜在的安全风险,比如用户输入的密码长度没有做任何限制,可能会导致缓冲区溢出;另外,该代码还存在一些不规范的操作,比如使用了gets()函数,没有考虑文件读取失败的情况等。
注册
这段代码实现了一个简单的用户注册功能。具体实现过程如下:
-
首先清屏,然后打开user.txt文件,并以追加模式(“a”)打开。如果该文件不存在,则会自动创建。
-
输出注册界面的提示信息,并让用户输入账号和密码,分别使用gets()函数获取。
-
将输入的账号和密码分别写入文件中,每个字符串后面添加一个换行符,以便于后续读取文件。
-
调用fflush()函数清除stdin缓存区中的内容。
-
关闭文件,并输出注册成功的提示信息,等待1秒后调用login()函数,让用户进行登录操作。
需要注意的是,该代码存在一些潜在的安全风险,比如用户输入的账号和密码长度没有做任何限制,可能会导致缓冲区溢出;另外,该代码还存在一些不规范的操作,比如使用了gets()函数,没有考虑文件打开失败的情况等。
void Register()
{
system("cls");
FILE* fp = fopen("user.txt", "a"); //以写模式打开文件user.txt,如果不存在,会自动创建
printf("注册界面\n");
printf("请输入账号\n");
gets(name);
printf("请输入密码\n");
gets(pas);
/*输入名称和密码*/
fputs(name, fp);
fputs(pas, fp); //将名称和密码以字符串形式写入文件
fputs("\n", fp);
fflush(stdin); //清除缓存
fclose(fp); //关闭文件
printf("创建账号成功!");
Sleep(1000);
Login(); //注册完转到登录界面
}
//登陆后的界面,输出主菜单
主菜单
这段代码实现了游戏登录后的主界面,输出了游戏规则和主菜单选项。具体实现过程如下:
- 调用goto_xy()函数设置光标位置,输出一段横线作为界面的边框。
- 输出游戏规则的提示信息,分别说明了游戏的目标和规则。
- 输出主菜单选项的提示信息,包括四个选项:开始游戏、难度调整、初始生命值和游戏说明。
- 再次调用goto_xy()函数设置光标位置,输出横线作为界面的底部边框。
该界面主要用于帮助用户了解游戏规则和选择游戏选项,使用户能够方便地进行游戏操作。
主菜单的实现
这段代码是一个菜单函数,用于展示游戏的主菜单,并根据用户的输入来进行不同的操作。具体来说,这个函数会在屏幕上显示一个菜单,包括开始游戏、选择难度、更改初始生命值和游戏说明等选项。用户可以通过键盘输入来选择不同的选项。如果用户选择开始游戏,则函数会返回并开始游戏。如果用户选择选择难度,则函数会提示用户输入难度等级,并根据用户的输入设定游戏难度。如果用户选择更改初始生命值,则函数会提示用户输入初始生命值,并根据用户的输入设定初始生命值。如果用户选择游戏说明,则函数会在屏幕上显示游戏的说明。在每个选项的处理过程中,函数会在屏幕上显示相应的提示信息,并在一个短暂的时间后返回主菜单。
生成迷宫
这段代码是一个递归函数,用于生成地图。它的参数包括一个指向二维数组的指针map_way,表示地图的布局,以及两个整数x和y,表示当前要挖掘的位置。函数开始时,会将当前位置标记为通路(WAY)。
然后,函数会随机打乱四个方向的顺序,以确保挖掘的方向是随机的。接着,函数会向每个方向开挖,挖掘的范围由Rank来控制,Rank越大,挖掘的距离越远。在挖掘的过程中,函数会检查当前位置是否已经是通路,如果是,则停止挖掘;如果当前位置周围已经有两条以上的通路,也停止挖掘。如果挖掘的距离还没有达到设定的范围,函数会继续向同一个方向挖掘,并将挖掘的位置标记为通路。
如果挖掘的距离已经达到了设定的范围,函数会检查是否有挖穿危险。如果当前位置周围已经有两条以上的通路,说明挖穿危险,函数会停止挖掘。如果没有挖穿危险,函数会以当前位置为节点,递归调用自身,生成更多的通路。
这样,递归函数会不断生成新的通路,直到整个地图都被挖掘完毕。生成的地图具有迷宫的特点,可以用于游戏等应用。
void CreateMap(int** map_way, int x, int y)
{
map_way[x][y] = WAY;
//确保四个方向随机
int direction[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
for (int i = 0; i < 4; i++)
{
int r = rand() % 4; //r = 0,1,2,3
int temp = direction[0][0];
direction[0][0] = direction[r][0];
direction[r][0] = temp;
temp = direction[0][1];
direction[0][1] = direction[r][1];
direction[r][1] = temp;
}
//向四个方向开挖
for (int i = 0; i < 4; i++)
{
int dx = x;
int dy = y; //初始坐标为(2,2)
//控制挖的距离,由Rank来调整大小
int range = 1 + (Rank == 0 ? 0 : rand() % Rank);
while (range > 0)
{
dx += direction[i][0];
dy += direction[i][1];
//排除掉回头路
if (map_way[dx][dy] == WAY)
break;
int count = 0;
for (int j = dx - 1; j < dx + 2; j++)
{
for (int k = dy - 1; k < dy + 2; k++)
{
if (abs(j - dx) + abs(k - dy) == 1 && map_way[j][k] == WAY)
count++;
}
}
if (count > 1)
break;
//确保不会挖穿时,前进
--range;
map_way[dx][dy] = WAY;
}
//没有挖穿危险,以此为节点递归
if (range <= 0)
CreateMap(map_way, dx, dy);
}
}
迷宫的制作
这段代码用于生成迷宫地图,并在地图上随机生成终点和陷阱。函数的参数是一个指向二维数组的指针map_way,表示地图的布局。函数首先将地图的最外层全部设为通路(WAY),然后调用createmap函数生成迷宫路径,起始点为坐标(2,2)。
接着,函数进入一个循环,随机确定终点的位置。终点的位置是在地图的右下角,由于地图的大小为NN,因此可以随机生成两个坐标i和j(i和j均小于N/2),然后将终点的位置设为(N-i,N-j),如果该位置是通路,则将该位置标记为终点(3),否则重新生成随机数,直到找到一个合适的位置。
接下来,函数进入另一个循环,用于随机确定陷阱的位置。函数先将陷阱的数量设为NN/36(即地图面积的1/6),然后重复生成陷阱,直到达到指定数量。每次生成陷阱时,函数随机生成两个坐标i和j(i和j均小于N-2),如果该位置是墙(WALL),则将该位置标记为陷阱(2),否则重新生成随机数,直到找到一个合适的位置。
最终,函数生成的地图包括迷宫路径、终点和陷阱,可以用于游戏等应用。
//迷宫图像的制作
void map_make(int** map_way)
{
for (int i = 0; i < N; i++) //将最外层全部设为路径
{
map_way[i][0] = WAY;
map_way[0][i] = WAY;
map_way[i][N - 1] = WAY;
map_way[N - 1][i] = WAY;
}
CreateMap(map_way, 2, 2);
while (1) //随机确定终点位置
{
int i = rand() % (N / 2), j = rand() % (N / 2);
if (i > 1 && j > 1 && map_way[N - i][N - j] == WAY)
{
map_way[N - i][N - j] = 3;
break;
}
}
for (int k = pow(N / 6, 2); k > 0; k--) //重复生成陷阱
{
while (1) //随机确定陷阱位置
{
int i = rand() % (N - 2), j = rand() % (N - 2);
if (i > 1 && j > 1 && map_way[i][j] == WALL)
{
map_way[i][j] = 2;
break;
}
}
}
}
光标移动
这段代码定义了一个函数goto_xy,用于将光标移动到控制台上指定的位置。函数的参数包括两个整数x和y,表示要移动到的位置的坐标。函数首先获取控制台输出句柄,然后创建一个COORD结构体pos,将x和y赋值给pos的X和Y成员。最后,函数调用SetConsoleCursorPosition函数将光标移动到pos指定的位置。因此,调用goto_xy函数可以实现在控制台上输出指定位置的内容。
//获取光标的位置x
int wherex()
{
CONSOLE_SCREEN_BUFFER_INFO pBuffer;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &pBuffer);
return (pBuffer.dwCursorPosition.X + 1);
}
//获取光标的位置y
int wherey()
{
CONSOLE_SCREEN_BUFFER_INFO pBuffer;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &pBuffer);
return (pBuffer.dwCursorPosition.Y + 1);
}
//设置光标的位置(密码变*号)
void goto1xy(int ax, int ay)
{
COORD c;
c.X = ax - 1;
c.Y = ay - 1;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
//移动光标到指定位置
void goto_xy(int x, int y)
{
HANDLE hout;
hout = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x,y };
SetConsoleCursorPosition(hout, pos);
}
打印地图
这段代码定义了一个函数map_print,用于在控制台上打印迷宫地图。函数的参数是一个指向二维数组的指针map_way,表示地图的布局。函数首先通过两个for循环遍历整个地图,对于每个位置,根据其在地图中对应的数值,使用不同的颜色和字符输出。具体来说:
- 如果该位置是通路(WAY),则使用Way_color颜色打印两个空格,表示该位置是可走的路径;
- 如果该位置是终点(EXIT),则使用Exit_color颜色打印一个星号(★),表示该位置是迷宫的终点;
- 如果该位置是陷阱(TRAP),则使用Trap_color颜色打印一个美元符号($),表示该位置是一个陷阱;
- 如果该位置是墙(WALL),则使用Wall_color颜色打印一个▓字符,表示该位置是墙壁。
其中,函数调用了color函数,用于设置输出的颜色。最后,函数输出一个换行符,将光标移动到下一行,以便输出下一行的地图信息。调用map_print函数可以将生成的迷宫地图在控制台上打印出来,供用户查看。
//打印地图
void map_print(int** map_way)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (map_way[i][j] == WAY)
{
color(Way_color);
printf(" "); //中间的通路可以打印空格即为可走路线
}
else if (map_way[i][j] == EXIT)
{
color(Exit_color);
printf("★"); //任意输出终点★
}
else if (map_way[i][j] == TRAP)
{
color(Trap_color);
printf("$"); //随机生成陷阱$
}
else if (map_way[i][j] == WALL)
{
color(Wall_color);
printf("▓ "); //若不为通路则为墙壁 ▓
}
}
printf("\n");
}
}
撞墙提示
这段代码包含两个函数,分别是zhuangqiang和trap。
zhuangqiang函数用于在控制台上打印“撞墙!”的提示信息,表示玩家在游戏中撞到了墙。函数首先调用goto_xy函数将光标移动到地图的右侧中央(即坐标为N*2,5的位置),然后使用Exit_color颜色打印“撞墙!”的提示信息。该函数可以在玩家撞墙时调用,提醒玩家需要避免撞墙。
trap函数用于提示玩家掉入陷阱,并更新玩家的生命值。函数的参数是玩家的生命值x,函数返回值是更新后的生命值。函数首先将光标移动到地图的右侧(即坐标为N+50,10的位置),然后使用Exit_color颜色打印提示信息“很遗憾,你掉入了陷阱,生命值减一!当前剩余:xx”,其中xx表示更新后的生命值。该函数可以在玩家掉入陷阱时调用,提醒玩家需要注意避免陷阱,同时更新玩家的生命值。
//撞墙提示
void zhuangqiang()
{
goto_xy(N * 2, 5);
color(Exit_color);
printf("撞墙!");
}
int trap(int x)//掉入陷阱
{
int a;
//goto_xy(N*2,6);
goto_xy(N + 50, 10);
a = x - 1;
color(Exit_color);
printf("很遗憾,你掉入了陷阱,生命值减一!当前剩余:%2d", a);//打印提示语句
return a;
}
玩家移动
这段代码是迷宫游戏中玩家移动的核心代码,通过接收玩家的按键操作,判断玩家是否可以向上下左右四个方向移动,并在移动过程中判断是否与墙壁、陷阱、终点等进行碰撞。具体来说,代码通过调用goto_xy函数控制光标移动到指定位置,再通过color函数设置输出字符的颜色,最后通过printf函数输出字符并更新玩家的位置。同时,代码还调用了其他函数,如zhuangqiang函数(当玩家撞到墙壁时的提示)、trap函数(当玩家掉入陷阱时的提示)和pass函数(当玩家到达终点时的提示)。该函数的返回值为int型,当函数执行完毕后,通过返回值结束函数并退出游戏。
这段代码实现了玩家在地图上的移动,主要通过监听玩家键盘输入的方向键来判断玩家的行动,并根据行动来更新玩家在地图上的位置和显示。具体实现细节如下:
- 通过调用
getch()
函数来监听玩家键盘输入的方向键。 - 对于玩家执行“上下左右”的操作,通过判断所移动的位置是否为墙壁、陷阱、终点或者空地来进行相应的操作。
- 如果所移动的位置是墙壁,则调用
zhuangqiang()
函数来打印提示语句。 - 如果所移动的位置是陷阱,则调用
trap()
函数来打印提示语句,并减少玩家的生命值,如果生命值减少到了0,则结束游戏。 - 如果所移动的位置是终点,则调用
pass()
函数来打印提示语句,并结束游戏。 - 如果所移动的位置是空地,则将玩家的位置更新,并根据之前所在位置是否为陷阱或空地来更新显示。
- 在玩家移动时,还会打印当前的生命值和一些提示语句,这些都是为了更好的游戏体验。
- 整个函数使用了无限循环来监听玩家的操作,直到玩家结束游戏或者到达终点。
//玩家的移动
int move(int** map_way) //为了能在运行过程中通过返回值return的方式,提前退出当前函数,故将函数定义为了int型
{
int i, j, k = LIFE, a = 0;
char Anjian;
goto_xy(N + 50, 11);
color(Menu_color);
printf("设定生命值:%d", LIFE);
goto_xy(man_x * 2, man_y);
color(Man_color);
printf("☆");
while (1)
{
goto_xy(N * 2, 0);
if (ch1 = getch())
{
ch2 = getch(); //调用getch(),等待按键后执行下面语句
switch (ch2) //对于上下左右的行动进行判断
{
case 72: //玩家执行“上”的操作
if (map_way[man_y - 1][man_x] == WALL)//与墙壁相冲突
{
zhuangqiang();
break;
}
else if (map_way[man_y - 1][man_x] == TRAP)//掉入陷阱
{
a = trap(k);
k = k - 1;
if (a == 0) //生命值为0
{
Sleep(500);
system("cls");
return 0;
}
if (map_way[man_y][man_x] == TRAP)//当玩家离开过后,仍出现陷阱
{
goto_xy(man_x * 2, man_y);
color(Trap_color);
printf("$");
}
else
{
goto_xy(man_x * 2, man_y);
color(Way_color);
printf(" ");
}
goto_xy(man_x * 2, man_y - 1);
color(Man_color);
printf("☆");
man_y--;
goto_xy(N * 2, 5);
color(7);
printf(" "); //抹去之前打印的提示语句
break;
}
else if (map_way[man_y - 1][man_x] == EXIT)
{
pass();
return 0;
}
else if (map_way[man_y - 1][man_x] == WAY)
{
if (map_way[man_y][man_x] == TRAP)
{
goto_xy(man_x * 2, man_y);
color(Trap_color);
printf("$");
}
else
{
goto_xy(man_x * 2, man_y);
color(Way_color);
printf(" ");
}
goto_xy(man_x * 2, man_y - 1);
color(Man_color);
printf("☆");
man_y--;
goto_xy(N * 2, 5);
color(7);
printf(" ");
goto_xy(N * 2, 6);
color(7);
printf(" ");
break;
}
case 80: //玩家执行“下”的操作
if (map_way[man_y + 1][man_x] == WALL) //与墙壁相冲突
{
zhuangqiang();
break;
}
else if (map_way[man_y + 1][man_x] == TRAP)//掉入陷阱
{
a = trap(k);
k = k - 1;
if (a == 0)
{
Sleep(500);
system("cls");
return 0;
}
if (map_way[man_y][man_x] == TRAP)
{
goto_xy(man_x * 2, man_y);
color(Trap_color);
printf("$");
}
else
{
goto_xy(man_x * 2, man_y);
color(Way_color);
printf(" ");
}
goto_xy(man_x * 2, man_y + 1);
color(Man_color);
printf("☆");
man_y++;
goto_xy(N * 2, 5);
color(7);
printf(" "); //抹去之前打印的提示语句
break;
}
else if (map_way[man_y + 1][man_x] == EXIT)
{
pass();
return 0;
}
else if (map_way[man_y + 1][man_x] == WAY)
{
if (map_way[man_y][man_x] == TRAP)
{
goto_xy(man_x * 2, man_y);
color(Trap_color);
printf("$");
}
else
{
goto_xy(man_x * 2, man_y);
color(Way_color);
printf(" ");
}
goto_xy(man_x * 2, man_y + 1);
color(Man_color);
printf("☆");
man_y++;
goto_xy(N * 2, 5);
color(7);
printf(" ");
goto_xy(N * 2, 6);
color(7);
printf(" ");//抹去之前打印的提示语句
break;
}
case 75: //玩家执行“左”的操作
if (map_way[man_y][man_x - 1] == WALL) //与墙壁相冲突
{
zhuangqiang();
break;
}
else if (map_way[man_y][man_x - 1] == TRAP) //掉入陷阱
{
a = trap(k);
k = k - 1;
if (a == 0)
{
Sleep(500);
system("cls");
return 0;
}
if (map_way[man_y][man_x] == TRAP)
{
goto_xy(man_x * 2 - 2, man_y);
color(Man_color); //代表人物的字符☆占两个标准字符位置,应此要乘2
printf("☆");
color(Trap_color);
printf("$");
}
else
{
goto_xy(man_x * 2 - 2, man_y); //代表人物的字符☆占两个标准字符位置,应此要乘2
color(Man_color);
printf("☆");
color(Way_color);
printf(" ");
}
man_x--;
goto_xy(N * 2, 5);
color(7);
printf(" ");//抹去之前打印的提示语句
break;
}
else if (map_way[man_y][man_x - 1] == EXIT) //到达终点
{
pass(); //打印提示语句
return 0; //退出
}
else if (map_way[man_y][man_x - 1] == WAY) //将人物向指定位置移动
{
if (map_way[man_y][man_x] == TRAP)
{
goto_xy(man_x * 2 - 2, man_y); //代表人物的字符☆占两个标准字符位置,应此要乘2
color(Man_color);
printf("☆");
color(Trap_color);
printf("$");
}
else
{
goto_xy(man_x * 2 - 2, man_y); //代表人物的字符☆占两个标准字符位置,应此要乘2
color(Man_color);
printf("☆");
color(Way_color);
printf(" ");
}
man_x--;
goto_xy(N * 2, 5);
color(7);
printf(" "); //抹去之前打印的提示语句
goto_xy(N * 2, 6);
color(7);
printf(" ");
break;
}
case 77: //玩家执行“右”的操作
if (map_way[man_y][man_x + 1] == WALL) //与墙壁相冲突
{
zhuangqiang();
break;
}
else if (map_way[man_y][man_x + 1] == TRAP)//掉入陷阱
{
a = trap(k);
k = k - 1;
if (a == 0)
{
Sleep(500);
system("cls");
return 0;
}
if (map_way[man_y][man_x] == TRAP)
{
goto_xy(man_x * 2, man_y);
color(Trap_color);
printf("$");
color(Man_color);
printf("☆");
}
else
{
goto_xy(man_x * 2, man_y);
color(Way_color);
printf(" ");
color(Man_color);
printf("☆");
}
man_x++;
goto_xy(N * 2, 5);
color(7);
printf(" ");
break;
}
else if (map_way[man_y][man_x + 1] == EXIT)
{
pass();
return 0;
}
else if (map_way[man_y][man_x + 1] == WAY)
{
if (map_way[man_y][man_x] == TRAP)
{
goto_xy(man_x * 2, man_y);
color(Trap_color);
printf("$");
color(Man_color);
printf("☆");
}
else
{
goto_xy(man_x * 2, man_y);
color(Way_color);
printf(" ");
color(Man_color);
printf("☆");
}
man_x++;
goto_xy(N * 2, 5);
color(7);
printf(" "); //抹去之前打印的提示语句
goto_xy(N * 2, 6);
color(7);
printf(" ");//抹去之前打印的提示语句
break;
}
default:
break;
}
}
}
}
pass
这段代码实现了游戏通关后的相关操作,主要包括以下内容:
- 首先通过
time()
函数获取当前的时间戳,并计算出玩家通关所用的时间。 - 然后使用
system("cls")
函数清空控制台屏幕,以便在屏幕中央输出通关信息。 - 使用
color()
函数设置输出文字的颜色。 - 使用
goto_xy()
函数将输出光标移动到屏幕中央,并输出通关信息。 - 使用
Sleep()
函数暂停程序执行,以便玩家查看通关信息。
具体解释如下: - 第一行代码将当前的时间戳赋值给
time_now
变量。 - 第二行代码通过减去游戏开始时间
Time
的方式计算出玩家通关所用的时间,并将秒数和分钟数分别赋值给sec
和min
变量。 - 第三行代码使用
system("cls")
函数清空控制台屏幕,以便在屏幕中央输出通关信息。 - 第四行代码使用
color()
函数设置输出文字的颜色,这里使用了Menu_color
这个全局变量。 - 第五行代码使用
goto_xy()
函数将输出光标移动到屏幕中央,并输出通关信息。 - 第六行代码使用
goto_xy()
函数将输出光标移动到屏幕中央,并输出玩家通关所用的时间。 - 第七行代码使用
goto_xy()
函数将输出光标移动到屏幕中央,并输出通关信息。 - 最后一行代码使用
Sleep()
函数暂停程序执行,以便玩家查看通关信息,这里暂停了 1500 毫秒。
//玩家通过游戏后输出界面
void pass()
{
int sec, min, time_now;
time_now = time(NULL); //暂停计时
//换算时间
sec = (time_now - Time) % 60;
min = (time_now - Time) / 60 % 60;
system("cls");
color(Menu_color);
goto_xy(48, 4);
printf("**************************************************");
goto_xy(48, 5);
printf("* 恭喜你,成功通关! *");
goto_xy(48, 6);
printf("* 耗时:%2d分 %2d秒 *", min, sec);//通过游戏过后出现通关所用时间
goto_xy(48, 7);
printf("**************************************************");
Sleep(1500);
}
end
这段代码实现了游戏结束后的相关操作,主要包括以下内容:
- 使用
system("cls")
函数清空控制台屏幕,以便在屏幕中央输出游戏结束信息。 - 使用
goto_xy()
函数将输出光标移动到屏幕中央,并输出游戏结束信息。 - 使用一个循环来释放之前分配的地图数组
map_way
的内存空间。 - 最后使用
free()
函数释放map_way
数组所占用的内存空间。
具体解释如下: - 第一行代码使用
system("cls")
函数清空控制台屏幕,以便在屏幕中央输出游戏结束信息。 - 第二行代码使用
goto_xy()
函数将输出光标移动到屏幕中央,并输出游戏结束信息。 - 第三行代码使用
goto_xy()
函数将输出光标移动到屏幕中央,并输出 GAME OVER!的信息。 - 第四行代码使用
for
循环遍历之前分配的地图数组map_way
的每一行。 - 在循环内部,使用
free()
函数释放每一行所占用的内存空间。 - 第六行代码使用
free()
函数释放map_way
数组所占用的内存空间。这一步是为了防止内存泄漏。
需要注意的是,由于map_way
是一个二维数组,所以需要分别释放每一行所占用的内存空间。释放内存的顺序应该和分配内存的顺序相反。
//游戏结束界面
void end(int** map_way)
{
system("cls");
goto_xy(48, 4);
printf("**************************************************");
goto_xy(48, 5);
printf("* 游戏结束 *");
goto_xy(48, 6);
printf("* GAME OVER! *");
goto_xy(48, 7);
printf("**************************************************");
goto_xy(48, 8);
for (int i = 0; i < N; i++)
free(map_way[i]); //释放内存
free(map_way); //释放内存
}