当前位置: 首页 > news >正文

C语言——扫雷

扫雷是一款经典的小游戏,那如何使用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);

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

相关文章:

C语言——扫雷

扫雷是一款经典的小游戏&#xff0c;那如何使用C语言实现一个扫雷游戏呢&#xff1f; 一、全部源码 直接把全部源码放在开头&#xff0c;如有需要&#xff0c;直接拿走。 源码分为三个文件&#xff1a; test.cpp/c 主函数的位置 #include "game.h"int main() {…...

计算机网络【DNS】

DNS 基本概述 与 HTTP、FTP 和 SMTP 一样&#xff0c;DNS 协议也是应用层的协议&#xff0c;DNS 使用客户-服务器模式运行在通信的端系统之间&#xff0c;在通信的端系统之间通过下面的端到端运输协议来传送 DNS 报文。但是 DNS 不是一个直接和用户打交道的应用。DNS 是为因特…...

Windows实现MySQL5.7主从复制(详细版)

使用免安装版本&#xff08;官网下载地址&#xff09; 在Windows上安装两种MySQL服务并同时开启服务 1.下载配置 打开解压文件所在位置&#xff0c;就新建一个配置文件my.ini。 2.主库安装 主库的my.ini配置文件如下&#xff1a; [mysqld] #设置主库端口&#xff0c;注意须是…...

AI 绘画 | Stable Diffusion 视频生成重绘

前言 本篇文章教会你如何使用Stable Diffusion WEB UI,实现视频的人物,或是动物重绘,可以更换人物或者动物,也可以有真实变为二次元。 视频展示 左边是原视频,右边是重绘视频原视频和Ai视频画面合并 教程 这里需要用到Stable Diffusion WEB UI的扩展插件ebsynth_utility…...

使用easyexcel对导出表格添加合计行

文章目录 一、背景二、实现1、写法一2、写法二 三、遇到的问题四、参考 一、背景 近期开发的一个新功能需要导出和前端展示样式一致的统计表格&#xff0c;而前端使用的elementui的table组件&#xff0c;show-summary属性选择后可以自动计算。后端导出时其他单元格与返回前端展…...

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;提供增量数据订阅和消费。其诞…...

Python入门学习篇(十四)——模块文件操作

1 模块 1.1 理解 包: python中带有__init__.py文件的文件夹 模块: 文件名(不包含.py后缀),如python官方的time.py中time就是模块1.2 示例代码 import datetime# 调用datetime模块中的datetime类的now()方法 t datetime.datetime.now() # 格式化输出日期和时间 strftime(&qu…...

【数据结构】排序之交换排序(冒泡 | 快排)

交换目录 1. 前言2. 交换排序3. 冒泡排序3.1 分析3.2 代码实现 4. 快速排序4.1 hoare版本4.1.1 分析4.1.2 hoare版本代码 4.2 挖坑法4.2.1 分析4.2.2 挖坑法代码实现 4.3 前后指针版本4.3.1 分析4.3.2 前后指针版本代码实现 1. 前言 在之前的博客中介绍了插入排序&#xff0c;…...

AI电商时代开始:阿里能否反杀拼多多

“AI电商时代刚刚开始&#xff0c;对谁都是机会&#xff0c;也是挑战。” 针对阿里员工对于拼多多财报和电商等的讨论&#xff0c;马云在阿里内网罕见地参与了谈论并发言。 阿里巴巴一向雷厉风行&#xff0c;已打响了AI电商的“第一炮”。 根据《晚点LatePost》报道&#xff…...

STC8H系列单片机入门教程之NVC系列语音播报模块(九)

一、模块简述 ● 模组支持3.3V和5V单片机供电系统 ● 标准2.54MM间距排针与外部连接 ● 支持喇叭0.5W/8欧 ● 适合用于超声波距离、电子秤重量、时钟时间、温度、球赛比分等语音播报 二、引脚说明 序号 名称 说明 1 VCC 电源正&#xff08;3.3V-5V&#…...

认识计算机网络——计算机网络的组成

计算机网络是由多个计算机和网络设备组成的系统&#xff0c;通过通信协议实现数据传输和信息交换。它是现代社会信息技术的重要支撑&#xff0c;广泛应用于各个领域。本文将介绍计算机网络的主要组成部分&#xff0c;包括硬件设备、软件协议和网络服务。 一、硬件设备 计算机网…...

数据的复制

基本概念 数据的复制指的是通过网络链接的多台机器保留相同的副本 为什么要进行数据的复制 使得用户和数据在地理上比较接近&#xff0c;因为大数据要求我们将计算安排在数据存放的位置和我们基本的内存模型不是很一样 &#xff0c;比如磁盘调入内存之类的。即使系统的一部分…...

【辐射场】3D Gaussian Splatting

三维高斯…喷喷 \, 3D Gaussian Splatting&#xff0c;下文简称3DGS&#xff0c;是好一段时间以来在三维内容创作和三维重建领域比较有热度的一项技术。 它属于基于图像的三维重建方法&#xff0c;意思就是你对现实物体或者场景拍照片&#xff0c;就能给你训练成一个场景模型&a…...

冒泡排序--------(C每日一题)

冒泡排序&#xff1a; 每次将相邻的两个数比较,将小的调到前头--升序 冒泡排序一个结论&#xff1a; n个数要进行n-1轮比较&#xff0c;第j轮要进行n-j次两两比较 循环体代码&#xff1a; int main() {int i, j,n,a[10],t;//n是几个数比较for(j1;j<n-1;j)//控制轮次for…...

每日一练:LeeCode-347. 前 K 个高频元素(中) - 【优先级队列】

本文是力扣LeeCode-347. 前 K 个高频元素 学习与理解过程&#xff0c;本文仅做学习之用&#xff0c;对本题感兴趣的小伙伴可以出门左拐LeeCode。 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输…...

<蓝桥杯软件赛>零基础备赛20周--第11周--贪心

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周。 在QQ群上答疑&#x…...

PowerShell Instal 一键部署TeamCity

前言 TeamCity 是一个通用的 CI/CD 软件平台,可实现灵活的工作流程、协作和开发实践。允许在您的 DevOps 流程中成功实现持续集成、持续交付和持续部署。 系统支持 Centos7,8,9/Redhat7,8,9及复刻系列系统支持 Windows 10,11,2012,2016,2019,2022高版本建议使用9系列系统…...

将“渴望“乐谱写入AT24C02并读出播放

#include <reg51.h> // 包含51单片机寄存器定义的头文件 #include <intrins.h> //包含_nop_()函数定义的头文件 #define OP_READ 0xa1 // 器件地址以及读取操作,0xa1即为1010 0001B #define OP_WRITE 0xa0 // 器件地址以及写…...

Vue独立组件开发-动态组件

文章目录 一、前言二、实现三、优化四、总结五、最后 一、前言 在开发中&#xff0c;你经常会遇到这么一种情况&#xff1a;根据条件动态地切换某个组件&#xff0c;或动态地选择渲染某个组件。 Vue 提供了另外一个内置的组件 <component> 和 is 特性&#xff0c;可以更…...

前端八股文(HTML篇)

目录 1.什么是DOCTYPE,有何用呢&#xff1f; 2.说说对html语义化的理解 3.src和href的区别&#xff1f; 4.title与h1的区别&#xff0c;b与strong的区别&#xff0c;i与em的区别&#xff1f; 5.什么是严格模式与混杂模式&#xff1f; 6.前端页面有哪三层构成&#xff0c;分…...

RivaGAN 水印项目

git地址 https://github.com/DAI-Lab/RivaGAN Dockerfile (/tools下文件为git下的文件) ############################################### # 使用 NVIDIA CUDA 10.0 开发环境作为基础镜像 FROM kaldiasr/kaldi:gpu-ubuntu18.04-cuda10.0 # 设置非交互式安装模式以避免某些命…...

Games101作业5

1.实现Renderer.cpp 中的 Render()&#xff1a;为每个像素生成光线 这里你需要为每个像素生成一条对应的光 线&#xff0c;然后调用函数 castRay() 来得到颜色&#xff0c;最后将颜色存储在帧缓冲区的相 应像素中。 我们要做的就是将屏幕空间下的坐标最后转换到世界空间的坐标…...

Golang解决跨域问题【OPTIONS预处理请求】

Golang解决跨域问题 前置知识&#xff1a;跨域问题产生条件及原因 跨域是是因为浏览器的同源策略限制&#xff0c;是浏览器的一种安全机制&#xff0c;服务端之间是不存在跨域的。 所谓同源指的是两个页面具有相同的协议、主机和端口&#xff0c;三者有任一不相同即会产生跨域…...

复试 || 就业day05(2023.12.31)算法篇

文章目录 前言找不同最长回文串找到所有数组中消失的数字下一个更大元素 I键盘行 前言 &#x1f4ab;你好&#xff0c;我是辰chen&#xff0c;本文旨在准备考研复试或就业 &#x1f4ab;文章题目大多来自于 leetcode&#xff0c;当然也可能来自洛谷或其他刷题平台 &#x1f4ab…...

Spring-4-代理

前面提到过&#xff0c;在Spring中有两种类型的代理&#xff1a;使用JDK Proxy类创建的JDK代理以及使用CGLIB Enhancer类创建的基于CGLIB的代理。 你可能想知道这两种代理之间有什么区别&#xff0c;以及为什么 Spring需要两种代理类型。 在本节中&#xff0c;将详细研究代理…...

设计模式:抽象工厂模式(讲故事易懂)

抽象工厂模式 定义&#xff1a;将有关联关系的系列产品放到一个工厂里&#xff0c;通过该工厂生产一系列产品。 设计模式有三大分类&#xff1a;创建型模式、结构型模式、行为型模式 抽象工厂模式属于创建型模式 上篇 工厂方法模式 提到工厂方法模式中每个工厂只生产一种特定…...

C语言中的Strict Aliasing Rule

文章目录 前言没有警告不代表没有问题目前的应对方法 前言 很久没写了&#xff0c;水一篇。 最近有个代码在gcc 4.8.5上编译失败。编译失败的提示是&#xff1a; error: dereferencing type-punned pointer will break strict-aliasing rules [-Werrorstrict-aliasing]查了下…...

单字符检测模型charnet使用方法,极简

Git链接 安装按照上面的说明&#xff0c;说下使用。 把tools下面的test做了一点修改&#xff0c;可以读取一张图片&#xff0c;把里面的单个字符都检测和识别出来。 然后绘制到屏幕上。 import torch from charnet.modeling.model import CharNet import cv2, os import num…...

Erlang、RabbitMQ下载与安装教程(windows超详细)

目录 安装Erlang 1.首先安装RabbitMQ需要安装Erlang环境 2.点击下载好的.exe文件进行傻瓜式安装,一直next即可 3.配置Erlang环境变量 安装RabbitMQ 1.给出RabbitMQ官网下载址&#xff1a;Installing on Windows — RabbitMQ&#xff0c;找到 2.配置RabbitMQ环境变量&#xff0…...

2023年终总结丨很苦,很酷!

文章目录 个人简介丨了解博主写在前面丨博主介绍年终总结丨博主成就年终总结丨博主想说年终总结丨学习芝士年终总结丨未来展望写在后面丨新年快乐 个人简介丨了解博主 主页地址&#xff1a;https://blog.csdn.net/m0_68111267 荣誉身份 ⭐2022年度CSDN 社区之星 Top6 ⭐2023年…...

鸿蒙 DevEco Studio 3.1 入门指南

本文主要记录开发者入门&#xff0c;从软件安装到项目运行&#xff0c;以及后续的学习 1&#xff0c;配置开发环境 1.1 下载安装包 官网下载链接 点击立即下载找到对应版版本 下载完成&#xff0c;按照提示默认安装即可 1.2 下载SDK及工具链 运行已安装的DevEco Studio&…...

ubuntu多用户环境dockerbug,卸载重装docker流程

之前不小心误操作删除重装docker&#xff0c;结果删除没成功&#xff0c;更没法重装&#xff0c;每次apt install都会报一个docker错误&#xff0c;虽然不影响软件的常规安装&#xff5e;但是现在还是需要装一个完整docker&#xff0c;还是选择删除一下&#xff0c;重点是关闭服…...

微信小程序开发系列-09自定义组件样式特性

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

数据结构 模拟实现LinkedList单向不循环链表

目录 一、链表的简单介绍 二、链表的接口 三、链表的方法实现 &#xff08;1&#xff09;display方法 &#xff08;2&#xff09;size得到单链表的长度方法 &#xff08;3&#xff09;addFirst头插方法 &#xff08;4&#xff09;addLast尾插方法 &#xff08;5&#xf…...

2023-12-24 LeetCode每日一题(收集足够苹果的最小花园周长)

2023-12-24每日一题 一、题目编号 1954. 收集足够苹果的最小花园周长二、题目链接 点击跳转到题目位置 三、题目描述 给你一个用无限二维网格表示的花园&#xff0c;每一个 整数坐标处都有一棵苹果树。整数坐标 (i, j) 处的苹果树有 |i| |j| 个苹果。 你将会买下正中心坐…...

Oracle 19c OCP 1z0 082考场真题解析第17题

考试科目&#xff1a;1Z0-082 考试题量&#xff1a;90 通过分数&#xff1a;60% 考试时间&#xff1a;150min 本文为云贝教育郭一军guoyJoe原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 17. Which three …...

掌握这十几个Python库才是爬虫界的天花板,没有你搞不定的网站!实战案例:Python全网最强电影搜索工具,自动生成播放链接

掌握这十几个Python库才是爬虫界的天花板,没有你搞不定的网站!实战案例:Python全网最强电影搜索工具,自动生成播放链接。 用来爬虫的十几个Python库。只要正确选择适合自己的Python库才能真正提高爬虫效率,到达高效爬虫目的。 1.PyQuery from pyquery import PyQuery as …...

模型 KANO卡诺模型

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。需求分析。 1 卡诺模型的应用 1.1 餐厅需求分析故事 假设你经营一家餐厅&#xff0c;你想了解客户对你的服务质量的满意度。你可以使用卡诺模型来收集客户的反馈&#xff0c;并分析客户的…...

启明智显开源项目分享|基于Model 3c芯片的86中控面板ZX3D95CM20S-V11项目软硬件全开源

前言&#xff1a; 本文为4寸 480*480 RGB接口IPS全面触屏的86中控面板&#xff08;RT-ThreadLVGL&#xff09;软硬件开源干货内容&#xff0c;该项目是综合性非常强的RTOS系列项目&#xff01;项目主控芯片使用 Model 3c&#xff0c;整体实现了简化版本的86中控面板的功能需求…...

Kind创建k8s - JAVA操作控制

kind 简介kind 架构安装 Kind (必备工具)docker官网kubectl官网kind官网校验安装结果 关于kind 命令 安装一个集群查看当前 Kubernetes 集群中的节点信息。查看当前命名空间下中的Pod&#xff08;容器实例&#xff09;的信息。使用 kind create cluster 安装&#xff0c;关于安…...

Qt sender()函数

sender函数原型&#xff1a; QObject *sender() const; 如果在由信号激活的插槽中调用该函数&#xff0c;返回指向发送信号的对象的指针&#xff0c;否则返回0&#xff0c;该指针仅在从该对象的线程上下文调用此函数的槽执行期间有效。 主要代码如下&#xff1a; 其中运用了Q…...

Java开发框架和中间件面试题(6)

目录 61.什么是Spring Batch&#xff1f; 62.请举例解释Required与Qualifier注解&#xff1f; 61.什么是Spring Batch&#xff1f; Spring batch是一个轻量级的&#xff0c;完善的批处理框架&#xff0c;他主要的目的在于帮助企业建立健壮&#xff0c;高效的批处理应用。Spri…...

附录E SQL入门之SQL保留字

本专栏目录 第1课 SQL入门之了解SQL 第2课 SQL入门之检索数据 第3课 SQL入门之排序检索数据 第4课 SQL入门之过滤数据 第5课 SQL入门之高级数据过滤 第6课 SQL入门之用通配符进行过滤 第7课 SQL入门之创建计算字段 第8课 SQL入门之使用数据处理函数 第9课 SQL入门之汇总数据 第…...

thinkphp6.0升级到8.0

目录 一&#xff1a;升级过程 二&#xff1a;报错处理 最近写的项目需要使用thinkphp8.0&#xff0c;之前的老项目需要从php6.0升级到8.0&#xff0c;特此记录下升级过程。 一&#xff1a;升级过程 查看版本&#xff1a; php think version,我目前的版本是6.1.4 生成thin…...

机器学习(一) -- 概述

系列文章目录 机器学习&#xff08;一&#xff09; -- 概述 机器学习&#xff08;二&#xff09; -- 数据预处理 未完待续…… 目录 系列文章目录 前言 一、机器学习定义&#xff08;是什么&#xff09; 二、机器学习的应用&#xff08;能做什么&#xff09; 三、***机器…...

SpringBoot定时监听RocketMQ的NameServer

问题分析 自己在测试环境部署了RocketMQ&#xff0c;发现namesrv很容易挂掉&#xff0c;于是就想着监控&#xff0c;挂了就发邮件通知。查看了rocketmq-dashboard项目&#xff0c;发现只能监控Broker&#xff0c;遂放弃这一路径。于是就从报错的日志入手&#xff0c;发现最终可…...

电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理

在数字化时代&#xff0c;采购管理也正经历着前所未有的变革。全过程数字化采购管理成为了企业追求高效、透明和规范的关键。该系统通过Spring Cloud、Spring Boot2、Mybatis等先进技术&#xff0c;打造了从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通过…...

各部门请注意,VELO维乐潮流骑士尼莫出街啦,快来加入吧!

VELO潮流骑士丨车界“小学生”尼莫&#xff0c;下面是来自她的自诉&#xff1a;      大家好&#xff01;我是尼莫&#xff0c;一枚骑车届的“小学生”&#xff0c;我爱上骑车已经有一年的时间啦&#xff01;在这一年的时间里&#xff0c;骑车改变了我很多&#xff1a;爱上…...

Flutter配置Android和IOS允许http访问

默认情况下&#xff0c;Android和IOS只支持对https的访问&#xff0c;如果需要访问不安全的连接&#xff0c;也就是http&#xff0c;需要做以下配置。 Android 在res目录下的xml目录中(如果不存在&#xff0c;先创建xml目录)&#xff0c;创建一个xml文件network_security_con…...

[设计模式 Go实现] 创建型~抽象工厂模式

抽象工厂模式用于生成产品族的工厂&#xff0c;所生成的对象是有关联的。 如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。 比如本例子中使用RDB和XML存储订单信息&#xff0c;抽象工厂分别能生成相关的主订单信息和订单详情信息。 如果业务逻辑中需要替换使用的时候…...