C语言——扫雷

news2025/1/25 9:14:48

扫雷是一款经典的小游戏,那如何使用C语言实现一个扫雷游戏呢?

一、全部源码

直接把全部源码放在开头,如有需要,直接拿走。

源码分为三个文件:

test.cpp/c

主函数的位置

#include "game.h"

int main()
{
	int deep[ROW][COL];//深层,用来记录布置好的地雷和数字,及埋藏在下层的内容
	char face[ROW][COL];//表面,用来打印和记录玩家操作,表层,对玩家操作进行记录
	int menu1 = 0;//外层菜单,0为退出游戏,1为进入游戏
	int menu2 = 0;//内层菜单,0为返回上一步,1为简单难度,2为中等难度,3为大师难度
	do
	{
		GameMenu(1);//外菜单打印
		scanf("%d", &menu1);//接收选择
		switch(menu1)
		{
		case 0://退出游戏
			printf("你已退出游戏!\n");
			break;
		case 1://内层菜单,选择难度
			GameMenu(2);//内层菜单打印
			scanf("%d", &menu2);//接收选择
			switch(menu2)
			{
			case 0://返回上一界面
				break;
			case 1:
				GameEasy(deep, face);//简单难度
				break;
			case 2:
				GameMedium(deep, face);//中等难度
				break;
			case 3:
				GameExpert(deep, face);//大师难度
				break;
			case 4:
				GameNightmare(deep, face);//噩梦难度
				break;
			default:
				printf("ERROR!\n");
				break;
			}
			break;
		default :
			printf("ERROR!\n");
			break;
		}
	} while (menu1);//只要非零就一直循环,进行游戏,为0则退出游戏
	return 0;
}

gane.cpp/c

几乎所有游戏功能函数的位置

#include "game.h"

//用来打印菜单
void GameMenu(int x)
{
	switch(x)
	{
	case 1://外层菜单
		printf("----------------------------\n");
		printf("------ 1 for start ---------\n");
		printf("------ 0 for exit ----------\n");
		printf("----------------------------\n");
		break;
	case 2://内层菜单
		printf("----------------------------\n");
		printf("------ 1 for Easy ----------\n");
		printf("------ 2 for Medium --------\n");
		printf("------ 3 for Expert --------\n");
		printf("------ 4 for Nightmare -----\n");
		printf("------ 0 for back ----------\n");
		printf("----------------------------\n");
		break;
	default :
		printf("ERROR!\n");
		break;
	}
}

//用来初始化深层数组,difficulty用来传难度,不同难度初始化大小不同
void DeepBoardIntial(int deep[ROW][COL], int difficulty)
{
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			deep[i][j] = 0;//初始化为0,以便之后填充数字
		}
	}
}

//用来初始化表面数组,difficulty用来传难度,不同难度初始化大小不同
void FaceBoardIntial(char face[ROW][COL],int difficulty)
{
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			face[i][j] = '_';//初始化为 _ ,表示未揭示的格子
		}
	}
}

//打印内容,对应打印可视化面板,这个是打印内容
void ContentPrint(int deep[ROW][COL], char face[ROW][COL], int i, int j)
{
	if (face[i][j] == 'x')//只要是玩家揭示的,直接打印deep中的内容(如果是炸弹,通过IsGameWin函数判断,就直接失败了,不会打印)
	{
		printf(" %d |", deep[i][j]);
	}
	else if (face[i][j] == 'L')//这里实现的是连续揭示,原版的一种操作,连续解释的赋值为 L ,方便实现当玩家探索一个没有雷的空块时,程序应该自动揭示与该空块相邻的所有空块,直到遇到数字(即与雷相邻的块)。这个特性是原版扫雷游戏的关键特点,加快游戏进程
	{
		if (deep[i][j] == 0)//只要数字是零,则直接打印空格,实现原版的周围八个格没有雷则打印空格
		{
			printf("   |");
		}
		else
		{
			printf(" %d |", deep[i][j]);//数字不是零则打印这个数字
		}
	}
	else
	{
		printf(" %c |",face[i][j]);//没有揭示的格子直接打印 _ 表示未揭示的格子
	}
}

//打印可视化面板
void BoardPrint(int deep[ROW][COL], char face[ROW][COL],int difficulty)
{
	int i = 0, j = 0;
	printf("|");
	for (j = 0; j < difficulty; j++)
	{
		printf("(%-2d|", j + 1);
	}
	printf("\n");
	printf("|");
	for (j = 0; j < difficulty; j++)
	{
		printf("___|");
	}
	printf("___");
	printf("\n");
	for (i = 0; i < difficulty; i++)
	{
		printf("|");
		for (j = 0; j < difficulty; j++)
		{
			ContentPrint(deep,face,i,j);//只有这个是内容打印,其他是打印表格,为了更加美观
		}
		printf("(%-2d", i + 1);
		printf("\n");
		printf("|");
		for (j = 0; j < difficulty; j++)
		{
			printf("___|");
		}
		printf("___");
		printf("\n");
	}
}

//随即放置地雷
void RandomMineGenerate(int deep[ROW][COL],int difficulty,int minesnum)
{
	int x = 0;
	int y = 0;
	int i = 0;
	srand((unsigned int)time(NULL));//设置随机种子
	for(i = 0;i < minesnum;i++)
	{
		x = rand() % difficulty;//产生0~8的数字,表示随机的行
		y = rand() % difficulty;//产生0~8的数字,表示随机的列
		if(deep[x][y] != MINE)//确保这个位置不是雷,只要不是已经是地雷的格子,则放一个地雷,防止重复放置导致的地雷数目减少
		{
			deep[x][y] = MINE;//将这个随机生成的坐标设为雷
		}
		else//如果是雷,则重新生成
		{
			i--;//i--可以实现此次作废,再来生成一次的效果
		}
	}
}

//检查是否胜利,0为输,1为赢,2为继续
int IsGameWin(int deep[ROW][COL], char face[ROW][COL], int row, int col, int difficulty)
{
	if (deep[row][col] == MINE && face[row][col] == 'x')//只要是雷且玩家点击,返回0,即输
	{
		return 0;
	}
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			if (deep[i][j] != MINE && face[i][j] == '_')//只要还有非雷格子没探索,返回2,就继续
			{
				return 2;
			}
		}
	}
	return 1;//没有踩雷,且没有非雷格子未探索,返回1,则赢
}

//连续揭示,点的是周围没有雷的格子,即数字零,周围就会连续揭示,实现原版操作
//连续揭示,原版的一种操作,连续解释的赋值为 L ,方便实现当玩家探索一个没有雷的空块时,程序应该自动揭示与该空块相邻的所有空块,直到遇到数字(即与雷相邻的块)。这个特性是原版扫雷游戏的关键特点,加快游戏进程
void LinkChange(int deep[ROW][COL], char face[ROW][COL], int i, int j,int difficulty)
{
	//由于下面使用了递归,必须加入一些条件使得递归不会一直递归下去
	if (!CheckIfValid(i, j, difficulty))//只要超出雷区范围,直接返回,函数返回值为void,直接return,不带任何值
	{
		return;
	}
	if (face[i][j] == 'L')//已经设置为连续揭示标志 L 的则直接返回
	{
		return;
	}
	if (deep[i][j] > 0 && deep[i][j] < 9)//在数字0旁边的非零数字,也设置为 L 并且返回
	{
		face[i][j] = 'L';
		return;
	}
	if (deep[i][j] == 9)//是地雷则直接返回
	{
		return;
	}
	if (deep[i][j] == 0)//一个位置为0,将这个位值设为 L 并且探索它周围八个格子,进行递归
	{
		face[i][j] = 'L';
		LinkChange(deep, face, i - 1, j - 1, difficulty);
		LinkChange(deep, face, i - 1, j, difficulty);
		LinkChange(deep, face, i - 1, j + 1, difficulty);
		LinkChange(deep, face, i, j - 1, difficulty);
		LinkChange(deep, face, i, j + 1, difficulty);
		LinkChange(deep, face, i + 1, j - 1, difficulty);
		LinkChange(deep, face, i + 1, j, difficulty);
		LinkChange(deep, face, i + 1, j + 1, difficulty);
	}
}

//装填数字,计算非雷格子中应该是数字几,来表示周围雷的个数,装填在数组中
void FillinNum(int deep[ROW][COL],int difficulty)
{
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			if (deep[i][j] == MINE)//如果坐标(i,j)是雷,则将雷旁边的八个格子都加一
			{
				if (CheckIfValid(i - 1,j - 1,difficulty) && deep[i - 1][j - 1] != MINE )//判断格子是否是雷,并且判断坐标是否有效,格子有效且不是地雷才能加一
				{
					deep[i - 1][j - 1]++;
				}
				if (CheckIfValid(i - 1, j, difficulty) && deep[i - 1][j] != MINE)
				{
					deep[i - 1][j]++;
				}
				if (CheckIfValid(i - 1, j + 1, difficulty) && deep[i - 1][j + 1] != MINE)
				{
					deep[i - 1][j + 1]++;
				}
				if (CheckIfValid(i, j - 1, difficulty) && deep[i][j - 1] != MINE)
				{
					deep[i][j - 1]++;
				}
				if (CheckIfValid(i, j + 1, difficulty) && deep[i][j + 1] != MINE)
				{
					deep[i][j + 1]++;
				}
				if (CheckIfValid(i + 1, j - 1, difficulty) && deep[i + 1][j - 1] != MINE)
				{
					deep[i + 1][j - 1]++;
				}
				if (CheckIfValid(i + 1, j, difficulty) && deep[i + 1][j] != MINE)
				{
					deep[i + 1][j]++;
				}
				if (CheckIfValid(i + 1, j + 1, difficulty) && deep[i + 1][j + 1] != MINE)
				{
					deep[i + 1][j + 1]++;
				}
			}
		}
	}
}

//检查坐标是否有效
int CheckIfValid(int row, int col,int difficulty)
{
	if (row >= 0 && row < difficulty && col >= 0 && col < difficulty)//检查坐标是否在雷区内
	{
		return 1;//在雷区内为有效,返回1为有效
	}
	return 0;//不在雷区内为无效,返回0为无效
}

//简单难度
void GameEasy(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 9);//简单难度格子为 9 * 9 大小
	FaceBoardIntial(face, 9);

	RandomMineGenerate(deep, 9,9);//随机生成地雷

	FillinNum(deep, 9);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 9);//打印
		while(1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1,9) && face[row - 1][col - 1] != 'x' && face[row - 1][col - 1] != 'L')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 9) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face,row - 1,col - 1,9);//检查是否胜利或失败以及游戏是否继续
		if(check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if(deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1,9);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if(check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

//中等难度
void GameMedium(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 16);//中等难度格子为 16 * 16 大小
	FaceBoardIntial(face, 16);

	RandomMineGenerate(deep, 16,32);//随机生成地雷

	FillinNum(deep, 16);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 16);//打印
		while (1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1, 16) && face[row - 1][col - 1] != 'x' && face[row - 1][col - 1] != 'L')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 16) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face, row - 1, col - 1, 16);//检查是否胜利或失败以及游戏是否继续
		if (check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if (deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1, 16);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if (check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

//大师难度
void GameExpert(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 30);//大师难度格子为 30 * 30 大小
	FaceBoardIntial(face, 30);

	RandomMineGenerate(deep, 30,90);//随机生成地雷

	FillinNum(deep, 30);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 30);//打印
		while (1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1, 30) && face[row - 1][col - 1] != 'x' && face[row - 1][col - 1] != 'L')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 30) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face, row - 1, col - 1, 30);//检查是否胜利或失败以及游戏是否继续
		if (check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if (deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1, 30);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if (check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

//噩梦难度
void GameNightmare(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 50);//噩梦难度格子为 50 * 50 大小
	FaceBoardIntial(face, 50);

	RandomMineGenerate(deep, 50, 250);//随机生成地雷

	FillinNum(deep, 50);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 50);//打印
		while (1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1, 50) && face[row - 1][col - 1] != 'x' && face[row - 1][col - 1] != 'L')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 50) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face, row - 1, col - 1, 50);//检查是否胜利或失败以及游戏是否继续
		if (check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if (deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1, 50);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if (check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

game.cpp/c

函数声明

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 50//宏定义,方便更改
#define COL 50
#define MINE 9//宏定义,定义9为雷

//菜单打印
void GameMenu(int x);

//深层数组初始化
void DeepBoardIntial(int deep[ROW][COL],int difficulty);

//表面数组初始化
void FaceBoardIntial(char face[ROW][COL],int difficulty);

//连续揭示打印
void LinkChange(int deep[ROW][COL], char face[ROW][COL], int i, int j,int difficulty);

//实际打印实现
void ContentPrint(int deep[ROW][COL], char face[ROW][COL], int i, int j);

//面板打印
void BoardPrint(int deep[ROW][COL], char face[ROW][COL],int difficulty);

//随机生成雷
void RandomMineGenerate(int deep[ROW][COL], int difficulty,int minesnum);

//检查是否胜利
int IsGameWin(int deep[ROW][COL], char face[ROW][COL], int row, int col, int difficulty);

//填入数字
void FillinNum(int deep[ROW][COL], int difficulty);

//检查输入坐标是否有效
int CheckIfValid(int row, int col, int difficulty);

//简单难度
void GameEasy(int deep[ROW][COL], char face[ROW][COL]);

//中等难度
void GameMedium(int deep[ROW][COL], char face[ROW][COL]);

//大师难度
void GameExpert(int deep[ROW][COL], char face[ROW][COL]);

//噩梦难度
void GameNightmare(int deep[ROW][COL], char face[ROW][COL]);

可以自行运行测试,下面有测试图片以及一些问题的解决办法,在在第七大段。

二、面板

要想扫雷,首先要有可视化的面板,能显示相关的信息,例如显示出数字,表示周围八个格子中有几个雷。所以我们先实现面板,同时还要存储数据,存储雷的位置,以及记录玩家操作的位置。所以我们要定义两个数组,一个用来存储雷的位置和数字,一个用来打印面板和存储玩家操作位置。

	int deep[ROW][COL];//深层,用来记录布置好的地雷和数字,及埋藏在下层的内容
	char face[ROW][COL];//表面,用来打印和记录玩家操作,表层,对玩家操作进行记录

1、游戏菜单

同时我们还要有游戏菜单供玩家选择难度和退出游戏。两个菜单,一个外层一个内层。

//用来打印菜单
void GameMenu(int x)
{
	switch(x)
	{
	case 1://外层菜单
		printf("----------------------------\n");
		printf("------ 1 for start ---------\n");
		printf("------ 0 for exit ----------\n");
		printf("----------------------------\n");
		break;
	case 2://内层菜单
		printf("----------------------------\n");
		printf("------ 1 for Easy ----------\n");
		printf("------ 2 for Medium --------\n");
		printf("------ 3 for Expert --------\n");
		printf("------ 4 for Nightmare -----\n");
		printf("------ 0 for back ----------\n");
		printf("----------------------------\n");
		break;
	default :
		printf("ERROR!\n");
		break;
	}
}

同时配合switch语句实现退出或开始游戏与难度选择:

GameMenu(1);//外菜单打印
scanf("%d", &menu1);//接收选择
switch(menu1)
{
case 0://退出游戏
	printf("你已退出游戏!\n");
	break;
case 1://内层菜单,选择难度
	GameMenu(2);//内层菜单打印
	scanf("%d", &menu2);//接收选择
	switch(menu2)
	{
	case 0://返回上一界面
		break;
	case 1:
		GameEasy(deep, face);//简单难度
		break;
	case 2:
		GameMedium(deep, face);//中等难度
		break;
	case 3:
		GameExpert(deep, face);//大师难度
		break;
	case 4:
		GameNightmare(deep, face);//噩梦难度
		break;
	default:
		printf("ERROR!\n");
		break;
	}
	break;
default :
	printf("ERROR!\n");
	break;
}

2、初始始化面板

在定义了两个数组用来存储数据后,我们还要对这两个数组初始化,初始化的内容是对于整型数组直接初始化为0,方便后面数字打印;字符型数组初始化为 _ 用来代表没有被揭示的地块。

//用来初始化深层数组,difficulty用来传难度,不同难度初始化大小不同
void DeepBoardIntial(int deep[ROW][COL], int difficulty)
{
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			deep[i][j] = 0;//初始化为0,以便之后填充数字
		}
	}
}

//用来初始化表面数组,difficulty用来传难度,不同难度初始化大小不同
void FaceBoardIntial(char face[ROW][COL],int difficulty)
{
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			face[i][j] = '_';//初始化为 _ ,表示未揭示的格子
		}
	}
}

3、面板打印

为了使面板可见,我们还需要一个面板打印函数,并且在两个数组发生变化时也能打印变化过的面板。也就是在玩家操作后数组内容进行了更新,打印的内容也要进行更新。

(1)表格打印

这里只是用来打印表格,使界面更美观。

//打印可视化面板
void BoardPrint(int deep[ROW][COL], char face[ROW][COL],int difficulty)
{
	int i = 0, j = 0;
	printf("|");
	for (j = 0; j < difficulty; j++)
	{
		printf("(%-2d|", j + 1);
	}
	printf("\n");
	printf("|");
	for (j = 0; j < difficulty; j++)
	{
		printf("___|");
	}
	printf("___");
	printf("\n");
	for (i = 0; i < difficulty; i++)
	{
		printf("|");
		for (j = 0; j < difficulty; j++)
		{
			ContentPrint(deep,face,i,j);//只有这个是内容打印,其他是打印表格,为了更加美观
		}
		printf("(%-2d", i + 1);
		printf("\n");
		printf("|");
		for (j = 0; j < difficulty; j++)
		{
			printf("___|");
		}
		printf("___");
		printf("\n");
	}
}

(2)内容打印

这个是打印内容,实现扫雷过程中内容更新后的打印。

//打印内容,对应打印可视化面板,这个是打印内容
void ContentPrint(int deep[ROW][COL], char face[ROW][COL], int i, int j)
{
	if (face[i][j] == 'x')//只要是玩家揭示的,直接打印deep中的内容(如果是炸弹,通过IsGameWin函数判断,就直接失败了,不会打印)
	{
		printf(" %d |", deep[i][j]);
	}
	else if (face[i][j] == 'L')//这里实现的是连续揭示,原版的一种操作,连续解释的赋值为 L ,方便实现当玩家探索一个没有雷的空块时,程序应该自动揭示与该空块相邻的所有空块,直到遇到数字(即与雷相邻的块)。这个特性是原版扫雷游戏的关键特点,加快游戏进程
	{
		if (deep[i][j] == 0)//只要数字是零,则直接打印空格,实现原版的周围八个格没有雷则打印空格
		{
			printf("   |");
		}
		else
		{
			printf(" %d |", deep[i][j]);//数字不是零则打印这个数字
		}
	}
	else
	{
		printf(" %c |",face[i][j]);//没有揭示的格子直接打印 _ 表示未揭示的格子
	}
}

两个函数配合完成打印工作。

三、游戏功能

1、地雷随机生成

//随即放置地雷
void RandomMineGenerate(int deep[ROW][COL],int difficulty,int minesnum)
{
	int x = 0;
	int y = 0;
	int i = 0;
	srand((unsigned int)time(NULL));//设置随机种子
	for(i = 0;i < minesnum;i++)
	{
		x = rand() % difficulty;//产生0~8的数字,表示随机的行
		y = rand() % difficulty;//产生0~8的数字,表示随机的列
		if(deep[x][y] != MINE)//确保这个位置不是雷,只要不是已经是地雷的格子,则放一个地雷,防止重复放置导致的地雷数目减少
		{
			deep[x][y] = MINE;//将这个随机生成的坐标设为雷
		}
		else//如果是雷,则重新生成
		{
			i--;//i--可以实现此次作废,再来生成一次的效果
		}
	}
}

利用rand函数随机产生坐标将这个坐标设为地雷。

2、装填数字

根据这个格子周围八个格子有几个地雷,就把这个格子设为数字几。

//装填数字,计算非雷格子中应该是数字几,来表示周围雷的个数,装填在数组中
void FillinNum(int deep[ROW][COL],int difficulty)
{
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			if (deep[i][j] == MINE)//如果坐标(i,j)是雷,则将雷旁边的八个格子都加一
			{
				if (CheckIfValid(i - 1,j - 1,difficulty) && deep[i - 1][j - 1] != MINE )//判断格子是否是雷,并且判断坐标是否有效,格子有效且不是地雷才能加一
				{
					deep[i - 1][j - 1]++;
				}
				if (CheckIfValid(i - 1, j, difficulty) && deep[i - 1][j] != MINE)
				{
					deep[i - 1][j]++;
				}
				if (CheckIfValid(i - 1, j + 1, difficulty) && deep[i - 1][j + 1] != MINE)
				{
					deep[i - 1][j + 1]++;
				}
				if (CheckIfValid(i, j - 1, difficulty) && deep[i][j - 1] != MINE)
				{
					deep[i][j - 1]++;
				}
				if (CheckIfValid(i, j + 1, difficulty) && deep[i][j + 1] != MINE)
				{
					deep[i][j + 1]++;
				}
				if (CheckIfValid(i + 1, j - 1, difficulty) && deep[i + 1][j - 1] != MINE)
				{
					deep[i + 1][j - 1]++;
				}
				if (CheckIfValid(i + 1, j, difficulty) && deep[i + 1][j] != MINE)
				{
					deep[i + 1][j]++;
				}
				if (CheckIfValid(i + 1, j + 1, difficulty) && deep[i + 1][j + 1] != MINE)
				{
					deep[i + 1][j + 1]++;
				}
			}
		}
	}
}

3、检查是否胜利

//检查是否胜利,0为输,1为赢,2为继续
int IsGameWin(int deep[ROW][COL], char face[ROW][COL], int row, int col, int difficulty)
{
	if (deep[row][col] == MINE && face[row][col] == 'x')//只要是雷且玩家点击,返回0,即输
	{
		return 0;
	}
	int i = 0, j = 0;
	for (i = 0; i < difficulty; i++)
	{
		for (j = 0; j < difficulty; j++)
		{
			if (deep[i][j] != MINE && face[i][j] == '_')//只要还有非雷格子没探索,返回2,就继续
			{
				return 2;
			}
		}
	}
	return 1;//没有踩雷,且没有非雷格子未探索,返回1,则赢
}

检查是否胜利,或者是否失败,以及游戏是否要继续。

4、连续揭示

连续揭示,原版的一种操作,连续解释的赋值为 L ,方便实现当玩家探索一个没有雷的空块时,程序应该自动揭示与该空块相邻的所有空块,直到遇到数字(即与雷相邻的块)。这个特性是原版扫雷游戏的关键特点,可以加快游戏进程。避免玩家只能一个坐标一个坐标探索浪费太多时间。

//连续揭示,点的是周围没有雷的格子,即数字零,周围就会连续揭示,实现原版操作
//连续揭示,原版的一种操作,连续解释的赋值为 L ,方便实现当玩家探索一个没有雷的空块时,程序应该自动揭示与该空块相邻的所有空块,直到遇到数字(即与雷相邻的块)。这个特性是原版扫雷游戏的关键特点,加快游戏进程
void LinkChange(int deep[ROW][COL], char face[ROW][COL], int i, int j,int difficulty)
{
	//由于下面使用了递归,必须加入一些条件使得递归不会一直递归下去
	if (!CheckIfValid(i, j, difficulty))//只要超出雷区范围,直接返回,函数返回值为void,直接return,不带任何值
	{
		return;
	}
	if (face[i][j] == 'L')//已经设置为连续揭示标志 L 的则直接返回
	{
		return;
	}
	if (deep[i][j] > 0 && deep[i][j] < 9)//在数字0旁边的非零数字,也设置为 L 并且返回
	{
		face[i][j] = 'L';
		return;
	}
	if (deep[i][j] == 9)//是地雷则直接返回
	{
		return;
	}
	if (deep[i][j] == 0)//一个位置为0,将这个位值设为 L 并且探索它周围八个格子,进行递归
	{
		face[i][j] = 'L';
		LinkChange(deep, face, i - 1, j - 1, difficulty);
		LinkChange(deep, face, i - 1, j, difficulty);
		LinkChange(deep, face, i - 1, j + 1, difficulty);
		LinkChange(deep, face, i, j - 1, difficulty);
		LinkChange(deep, face, i, j + 1, difficulty);
		LinkChange(deep, face, i + 1, j - 1, difficulty);
		LinkChange(deep, face, i + 1, j, difficulty);
		LinkChange(deep, face, i + 1, j + 1, difficulty);
	}
}

5、检查坐标是否有效

//检查坐标是否有效
int CheckIfValid(int row, int col,int difficulty)
{
	if (row >= 0 && row < difficulty && col >= 0 && col < difficulty)//检查坐标是否在雷区内
	{
		return 1;//在雷区内为有效,返回1为有效
	}
	return 0;//不在雷区内为无效,返回0为无效
}

四、游戏难度部分

1、简单难度

简单难度的格子为9*9大小,有9个地雷。

//简单难度
void GameEasy(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 9);//简单难度格子为 9 * 9 大小
	FaceBoardIntial(face, 9);

	RandomMineGenerate(deep, 9);//随机生成地雷

	FillinNum(deep, 9);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 9);//打印
		while(1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1,9) && face[row - 1][col - 1] != 'x')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 9) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face,row - 1,col - 1,9);//检查是否胜利或失败以及游戏是否继续
		if(check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if(deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1,9);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if(check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

2、中等难度

中等难度大小为16*16,有32个地雷。

//中等难度
void GameMedium(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 16);//中等难度格子为 16 * 16 大小
	FaceBoardIntial(face, 16);

	RandomMineGenerate(deep, 16,32);//随机生成地雷

	FillinNum(deep, 16);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 16);//打印
		while (1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1, 16) && face[row - 1][col - 1] != 'x' && face[row - 1][col - 1] != 'L')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 16) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face, row - 1, col - 1, 16);//检查是否胜利或失败以及游戏是否继续
		if (check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if (deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1, 16);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if (check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

3、大师难度

大师难度格子为30*30,有90个地雷。

//大师难度
void GameExpert(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 30);//大师难度格子为 30 * 30 大小
	FaceBoardIntial(face, 30);

	RandomMineGenerate(deep, 30,90);//随机生成地雷

	FillinNum(deep, 30);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 30);//打印
		while (1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1, 30) && face[row - 1][col - 1] != 'x' && face[row - 1][col - 1] != 'L')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 30) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face, row - 1, col - 1, 30);//检查是否胜利或失败以及游戏是否继续
		if (check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if (deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1, 30);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if (check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

4、噩梦难度

噩梦难度格子为50*50,地雷为250个。

//噩梦难度
void GameNightmare(int deep[ROW][COL], char face[ROW][COL])
{
	DeepBoardIntial(deep, 50);//噩梦难度格子为 50 * 50 大小
	FaceBoardIntial(face, 50);

	RandomMineGenerate(deep, 50, 250);//随机生成地雷

	FillinNum(deep, 50);//装填数字

	int row = 0, col = 0;//用来接收玩家输入行列

	int check = 0;//检查是否胜利,0为失败,1为胜利,2为继续

	do
	{
		system("cls");//清屏
		BoardPrint(deep, face, 50);//打印
		while (1)
		{
			printf("输入行列>");
			scanf("%d %d", &row, &col);
			if (CheckIfValid(row - 1, col - 1, 50) && face[row - 1][col - 1] != 'x' && face[row - 1][col - 1] != 'L')//有效且是没被揭开的则输入成功
			{
				face[row - 1][col - 1] = 'x';
				break;//输入成功则直接退出循环
			}
			else if (CheckIfValid(row - 1, col - 1, 50) && (face[row - 1][col - 1] == 'x' || face[row - 1][col - 1] == 'L'))//输入的坐标为已经揭示的格子,则重新输入
			{
				printf("已经揭示的格子,请不要重复操作!重新输入!\n");
			}
			else//不在范围内,重新输入
			{
				printf("范围错误!重新输入!\n");
			}
		}
		check = IsGameWin(deep, face, row - 1, col - 1, 50);//检查是否胜利或失败以及游戏是否继续
		if (check == 2)//只要游戏继续,就判断是否连续揭示
		{
			if (deep[row - 1][col - 1] == 0)//揭示的格子是空格(即格子是0,周围八个格子没有地雷)则尝试连续揭示
			{
				LinkChange(deep, face, row - 1, col - 1, 50);//对于这个输入的格子进行连续揭示
			}
		}
	} while (check == 2);//只要check为2则继续,则循环继续,则游戏继续,check为1或0(即赢或输)是退出循环

	if (check == 1)//check为1时胜利
	{
		printf("你赢了!\n");
	}
	else if (check == 0)//check为0时失败
	{
		printf("你输了!\n");
	}
	else//错误
	{
		printf("ERROR!\n");
	}
}

五、主函数部分

主函数集成游戏的功能。

int main()
{
	int deep[ROW][COL];//深层,用来记录布置好的地雷和数字,及埋藏在下层的内容
	char face[ROW][COL];//表面,用来打印和记录玩家操作,表层,对玩家操作进行记录
	int menu1 = 0;//外层菜单,0为退出游戏,1为进入游戏
	int menu2 = 0;//内层菜单,0为返回上一步,1为简单难度,2为中等难度,3为大师难度
	do
	{
		GameMenu(1);//外菜单打印
		scanf("%d", &menu1);//接收选择
		switch(menu1)
		{
		case 0://退出游戏
			printf("你已退出游戏!\n");
			break;
		case 1://内层菜单,选择难度
			GameMenu(2);//内层菜单打印
			scanf("%d", &menu2);//接收选择
			switch(menu2)
			{
			case 0://返回上一界面
				break;
			case 1:
				GameEasy(deep, face);//简单难度
				break;
			case 2:
				GameMedium(deep, face);//中等难度
				break;
			case 3:
				GameExpert(deep, face);//大师难度
				break;
			case 4:
				GameNightmare(deep, face);//噩梦难度
				break;
			default:
				printf("ERROR!\n");
				break;
			}
			break;
		default :
			printf("ERROR!\n");
			break;
		}
	} while (menu1);//只要非零就一直循环,进行游戏,为0则退出游戏
	return 0;
}

六、头文件

头文件声明函数。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 50//宏定义,方便更改
#define COL 50
#define MINE 9//宏定义,定义9为雷

//菜单打印
void GameMenu(int x);

//深层数组初始化
void DeepBoardIntial(int deep[ROW][COL],int difficulty);

//表面数组初始化
void FaceBoardIntial(char face[ROW][COL],int difficulty);

//连续揭示打印
void LinkChange(int deep[ROW][COL], char face[ROW][COL], int i, int j,int difficulty);

//实际打印实现
void ContentPrint(int deep[ROW][COL], char face[ROW][COL], int i, int j);

//面板打印
void BoardPrint(int deep[ROW][COL], char face[ROW][COL],int difficulty);

//随机生成雷
void RandomMineGenerate(int deep[ROW][COL], int difficulty,int minesnum);

//检查是否胜利
int IsGameWin(int deep[ROW][COL], char face[ROW][COL], int row, int col, int difficulty);

//填入数字
void FillinNum(int deep[ROW][COL], int difficulty);

//检查输入坐标是否有效
int CheckIfValid(int row, int col, int difficulty);

//简单难度
void GameEasy(int deep[ROW][COL], char face[ROW][COL]);

//中等难度
void GameMedium(int deep[ROW][COL], char face[ROW][COL]);

//大师难度
void GameExpert(int deep[ROW][COL], char face[ROW][COL]);

//噩梦难度
void GameNightmare(int deep[ROW][COL], char face[ROW][COL]);

七、一些问题和解决办法

1、打印显示问题

在游玩专家难度及以上的难度时,或者在游玩你自己改进的难度时(你可以通过更改宏ROW和COL的大小实现更大的格子范围),会发现打印出现下列状况:

打印出来的格子错位了。

这个问题可以通过全屏控制台解决,若还不行的话,可能是格子范围太大,可以通过使用Ctrl + 鼠标滚轮来对控制台缩放,Ctrl + 鼠标滚轮下滑可以缩放控制台,使得格子复位。在你不能看到完整的雷区时也可以使用这个方法。

2、输入设置

默认输入坐标是:

			scanf("%d %d", &row, &col);

输入坐标时中间要加一个空格或回车分开,例如

中间不能加其他字符,加其他字符会出错,你也可以改为:

			scanf("%d,%d", &row, &col);

这样就只能用 , 进行分隔了,不能用其他字符分隔了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1346924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springcloud Alibaba使用Canal将Mysql数据实时同步到Redis保证缓存的一致性

目录 1. 背景 2. Windows系统安装canal 3.Mysql准备工作 4. 公共依赖包 5. Redis缓存设计 6. mall-canal-service 1. 背景 canal [kənl] &#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费。其诞…

微服务应用配置解决方案介绍

目录 一、传统服务配置面临的问题 1.1 本地静态配置 1.2 配置格式不统一 1.3 生产事故 1.4 配置修改困难 1.5 缺少安全审计和版本控制能⼒ 二、应用配置的使用场景 2.1 动态调整日志级别 2.2 配置项组合更新 2.3 开关驱动开发 2.4 金丝雀(灰度)发布 三、应用配置解决…

【Redis-08】Redis主从复制的实现原理

在Redis中&#xff0c;可以通过slaveof命令或者设置slaveof选项实现两台Redis服务器的主从复制&#xff0c;比如我们有两个Redis机器&#xff0c;地址分别是 127.0.0.1:6379 和 127.0.0.1:6380&#xff0c;现在我们在前者上面执行&#xff1a; 127.0.0.1:6379 > SLAVEOF 12…

Docker九 | Swarm mode

目录 Swarm基本概念 节点 服务和任务 创建Swarm集群 创建管理节点 增加工作节点 查看集群 部署服务 新建服务 查看服务 服务伸缩 增加服务 减少服务 删除服务 Swarm基本概念 节点 节点分为管理节点(manager)和工作节点(worker) 管理节点 管理节点用于Swarm集群的…

使用 GPT4V+AI Agent 做自动 UI 测试的探索

一、背景 从 Web 诞生之日起&#xff0c;UI 自动化就成了测试的难点&#xff0c;到现在近 30 年&#xff0c;一直没有有效的手段解决Web UI测试的问题&#xff0c;尽管发展了很多的 webdriver 驱动&#xff0c;图片 diff 驱动的工具&#xff0c;但是这些工具的投入产出比一直被…

windows go环境安装 swag

windows 下载依赖包 go get github.com/swaggo/swag/cmd/swag编译swag cd $GOPATH\pkg\mod\github.com\swaggo\swagv1.16.2\cmd\swagps: go env 获取 GOPATH位置 go installps: 此时 $GOPATH\bin下出现了 swag.exe 项目根目录下执行swag 初始化 swag init生成结果

【Java基础系列】body参数前后端不一致

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

动态规划 | 鸡蛋问题 | 元旦假期来点“蛋”题

文章目录 鸡蛋掉落 - 两枚鸡蛋题目描述动态规划解法问题分析程序代码 鸡蛋掉落题目描述问题分析程序代码复杂度分析 鸡蛋掉落 - 两枚鸡蛋 题目描述 原题链接 给你 2 枚相同 的鸡蛋&#xff0c;和一栋从第 1 层到第 n 层共有 n 层楼的建筑。 已知存在楼层 f &#xff0c;满足 …

微信小程序开发系列-10组件间通信01

微信小程序开发系列目录 《微信小程序开发系列-01创建一个最小的小程序项目》 《微信小程序开发系列-02注册小程序》 《微信小程序开发系列-03全局配置中的“window”和“tabBar”》 《微信小程序开发系列-04获取用户图像和昵称》 《微信小程序开发系列-05登录小程序》 《…

图文证明 泰勒公式展开

泰勒公式 泰勒公式简单来说就是,可以用一个N次多项式来表示出一个连续可导的函数 f(x) 是一个用函数在某点的信息描述其附近取值的公式 第一步 思考 这是一个sin(x)的图像 用函数在原点的信息描述其附近取值 用一阶导数贴合: 直接用切线来贴合就好 画一个点(0,sin(0)除的切…

内网常规攻击路径

点击星标&#xff0c;即时接收最新推文 随着网络技术的发展&#xff0c;企业内部网络架构的变化&#xff0c;网络设备多样性的增加&#xff0c;面对内网攻击&#xff0c;防御体系逐渐阶梯化&#xff0c;通过不同维度的防御联动&#xff0c;将攻击拒之门外。对于突破网络边界后进…

docker 私有仓库搭建,将镜像上传至私有仓库,从私有仓库拉取镜像

Docker 私有仓库 一、私有仓库搭建 # 1、拉取私有仓库镜像 docker pull registry # 2、启动私有仓库容器 docker run -id --nameregistry -p 5000:5000 registry # 3、打开浏览器 输入地址http://私有仓库服务器ip:5000/v2/_catalog&#xff0c;看到{"repositories&quo…

八个理由:从java8升级到Java17

目录 前言 1. 局部变量类型推断 2.switch表达式 3.文本块 4.Records 5.模式匹配instanceof 6. 密封类 7. HttpClient 8.性能和内存管理能力提高 前言 从Java 8 到 Java 20&#xff0c;Java 已经走过了漫长的道路&#xff0c;自 Java 8 以来&#xff0c;Java 生态系统…

DevExpress 皮肤改变触发后触发的事件,用来保存皮肤配置

代码&#xff1a; private UserLookAndFeel userLookAndFeel; public MainGeneral() {InitializeComponent();// 创建 UserLookAndFeel 实例userLookAndFeel new UserLookAndFeel(this);// 订阅 StyleChanged 事件userLookAndFeel.StyleChanged UserLookAndFeel_StyleChange…

学习体系结构 - AArch64内存管理

学习体系结构 - AArch64内存管理 Learn the architecture - AArch64 memory management Version 1.2 个人的英语很一般&#xff0c;对拿不准的翻译校准在后面添加了英文原文。 1、 概述 本指南介绍了AArch64中的内存转换&#xff0c;这是内存管理的关键。它解释了如何将虚拟地…

ACW741.斐波那契额数列

输入整数 N&#xff0c;求出斐波那契数列中的第 N项是多少。 斐波那契数列的第 0项是 0&#xff0c;第 1项是 1&#xff0c;从第 2 项开始的每一项都等于前两项之和。输入格式 第一行包含整数 T&#xff0c;表示共有T个测试数据。接下来 T行&#xff0c;每行包含一个整数 N。输…

Python高级用法:生成器(generator)

生成器&#xff08;generator&#xff09; 生成器是一种返回生成序列的方法&#xff0c;与直接使用列表等方式返回序列的方式不同的是&#xff0c;他的生成可以是无限的。 生成器可以与next搭配使用&#xff0c;可以被看作是一种特殊的迭代器。 yield语句 yield一般与循环相…

研究:同样的C++模板在多个cpp里出现,编译器是否要重复生成?

2023年就要过去&#xff0c;马上要跨如2024年。祝大家在新的一年&#xff0c;有个好收成。 一直以来不是很确定&#xff1a; 同样的的模板&#xff0c;在各个cpp分别出现&#xff0c;编译器要实现几份&#xff1f; 研究一下。 用命令行的编译方法&#xff0c;参考&#xff1a…

mxxWechatBot微信机器人V2使用教程(图文)最全最详细

大家伙&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 先看这里 mxxWechatBot功能列表一、前言二、适用人群三、准备工作四、获取账号五、下载资料 六、安装相关软件七、启动客户端八、注入并启动微信九、机器人的基本配置十、自定义接口开发 …

数据库系统概论SQL编程题合集(包含期末题、考研初试题以及复试题)

二、现有数据库casemanage中表结构如下图 1&#xff09;请编写sql语句对年龄进行升序排列 select * from afinfo order by birth;2&#xff09;请编写sql语句查询对“徐”姓开头的人员名单 select * from afinfo where name like 徐%;3&#xff09;请编写sql语句修改“陈晓”…