C++ · 手把手教你写一个扫雷小游戏

news2024/11/28 19:33:09

Hello,大家好,我是余同学。这两个月真是太忙了,无暇给大家更新文章…

暑假不是写了个扫雷小游戏吗(Link)?考虑到很多同学对代码没有透彻的理解,那么,这篇文章,我们来详细分析一下代码.

我们分为三个部分来讲:生成雷区,生成雷区数字刷新与判断


Part.1 生成雷区

随机数

首先,我们的雷区不能是定义好的矩阵,肯定得用随机数生成。
用随机数的话,就出现了一个问题:

  • C++有一个生成随机数的奇妙特性(也就是在不写srand(time(NULL));的情况下)

这个特性是什么样的呢?
我们来看下示例:

#include <bits/stdc++.h>
using namespace std;

int main ()
{
	//srand(time(NULL));
	int random=rand()%10;
	cout<<random;
    return 0;
}

运行结果:
第一次:
1.1

第二次:
1.2

可以看到, 虽然是"随机数",但是,程序每次输出的数却是一样的,这是怎么回事?

程序每次生成的数来源于一个随机数种子,如果我们不改变它的话,那么程序就会一直使用这个种子,从而导致每次生成的随机数都一样

因此,我们要使用随机数种子
其具体原理即是利用每次运行的时间互不相同,生成的随机数也不同
srand(time(NULL));

可以使用rand()%x生成随机数,也可以使用宏定义,即使用define

#define random(x) rand()%(x)

那么,我们看看效果吧
第一次输出:
2.1
第二次输出:
2.2
也就是说,如果我们要生成一个从ab区间的随机数,可以用以下指令:

int number=a+rand()%b; //随机数生成区间为:a ~ a+b-1
int number=rand()%b;   //随机数生成区间为:1 ~ b-1

随机数搞定了,接下来,就是考虑生成扫雷矩阵的事情了

生成雷区

现在,我们面临的最大问题就是:在不使用字符串的情况下,如何用0~9这十个数字实现数字与雷的分别

其实,实现很简单,我使用的方法是:1~8作为数字,0作为附近9格无雷标志(其实还是数字),9作为雷

那么,我们的矩阵是 10×10 的,只要通过循环生成 100 个随机数就行了

看代码吧:

#include<bits/stdc++.h>
/*
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <ctime>
#include <iomanip>
*/
#define random(x) 1+rand()%(x)
using namespace std;
int ui[12][12],b[12][12]; //多开一些没有坏处,原因后面会讲

int main(){
	srand(time(NULL)); //random seed, srand(time(0));
	//system("color 1B");
	system("title MineSweeper");
	int cnt=10; //地雷个数
	
	while(cnt){
		int x=random(10);//a+rand()%b = [a, a+b-1]
		int y=random(10);
		if(!ui[x][y]){//if(ui[x][y]==0){
			ui[x][y]=9;
			cnt--;
		}
	}
	return 0;
}

忘记说了,我设了两个二维数组,其中,ui数组的功能是:存储整个雷区;数组b的功能则是:存储每个方格的状态(详见Part.3

至此,我们的第一部分结束。

如果有的同学疑惑上面的代码没有输出时,那是因为我们只写了生成雷区的代码,并没有写生成雷区旁数字的代码,详细请看Part.2 生成雷区数字


Part.2 生成雷区数字

要完成这一部分,我们首先得了解地雷旁数字的生成规律:

每个数字代表周围8格内的地雷数量

还是上图片:
3.1
这样,我们的逻辑就清晰了,只要用双重循环遍历二维数组b的每一项,判断这个点是否为地雷,如果是,就跳过这个点,继续向下遍历;否之,计算出该点周围8个方格的总雷数(我们暂且定义为sum),sum就是这个点的数值

来把这一部分的代码实现吧

for(int i=1;i<=10;i++){
	for(int j=1;j<=10;j++){
		int sum=0; //统计周围地雷数量
		if(ui[i][j]!=9){ //该点不为雷
			/*
			下面的这些坐标具体位置详见上图
			*/
			if(ui[i-1][j-1]==9) sum++;//sum=!(a[i-1][j-1]-9)+!(a[i-1][j]-9)...
			if(ui[i-1][j]==9) sum++;
			if(ui[i-1][j+1]==9) sum++;
			if(ui[i][j-1]==9) sum++;
			if(ui[i][j+1]==9) sum++;
			if(ui[i+1][j-1]==9) sum++;
			if(ui[i+1][j]==9) sum++;
			if(ui[i+1][j+1]==9) sum++;
			ui[i][j]=sum;
		}
	}
}

现在,我们就知道了为什么前面的两个二维数组都要开大一点了:

因为二维数组的索引是从0开始的,而我们使用1作为起始索引(具体见上方代码两个for循环中),就是为了避免在边缘上的方块无法获取到周围地雷数,从而导致程序出bug的原因

然后,代码中的8个 if 语句都是统计周围地雷数的,如果你想简单亿点的话,把if语句替换成这一行:

sum=!(ui[i-1][j-1]-9)+!(ui[i-1][j]-9)+!(ui[i-1][j+1]-9)+
!(ui[i][j-1]-9)+!(ui[i][j+1]-9)+!(ui[i+1][j-1]-9)+!(ui[i+1][j]-9)+!(ui[i+1][j+1]-9);

这里我分做两行写,是怕有的同学看不清,大家在实际替换中删掉换行符就可以了

这一部分完整代码:

#include<bits/stdc++.h>
#include "windows.h"
/*
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <ctime>
#include <iomanip>
*/
#define random(x) 1+rand()%(x)
using namespace std;

int ui[12][12],b[12][12]; 
int main(){
	srand(time(NULL)); //random seed
	//system("color 1B");
	system("title MineSweeper");
	int cnt=10;//cout<<"Booms:";cin>>cnt;
	while(cnt){
		int x=random(10);//a+rand()%b = [a, a+b-1]
		int y=random(10);
		if(!ui[x][y]){//if(ui[x][y]==0){
			ui[x][y]=9;
			cnt--;
		}
	}
	
	for(int i=1;i<=10;i++){
		for(int j=1;j<=10;j++){
			int sum=0;
			if(ui[i][j]!=9){
				if(ui[i-1][j-1]==9) sum++;//sum=!(a[i-1][j-1]-9)+!(a[i-1][j]-9)...
				if(ui[i-1][j]==9) sum++;
				if(ui[i-1][j+1]==9) sum++;
				if(ui[i][j-1]==9) sum++;
				if(ui[i][j+1]==9) sum++;
				if(ui[i+1][j-1]==9) sum++;
				if(ui[i+1][j]==9) sum++;
				if(ui[i+1][j+1]==9) sum++;
				/*sum=!(ui[i-1][j-1]-9)+!(ui[i-1][j]-9)+!(ui[i-1][j+1]-9)+
				!(ui[i][j-1]-9)+!(ui[i][j+1]-9)+!(ui[i+1][j-1]-9)+
				!(ui[i+1][j]-9)+!(ui[i+1][j+1]-9);*/
				ui[i][j]=sum;
				
			}
		}
	}
	
	/*for(int i=1;i<=10;i++){
		for(int j=1;j<=10;j++){
			cout<<ui[i][j]<<' '; //output the numbers
		}
		cout<<endl;
	}*/
	return 0;
}

大家把最后一段的注释符删掉,就可以看到我们的矩阵了
test1

但是,我们到现在才做完整个项目的一半,我们还没有写判断操作符的代码,这就要留到Part 3来讲了


Part 3. 状态更新与判断输入

刷新屏幕

我们先来讲刷新屏幕

为什不先写判断输入的代码呢?
因为我们得让程序先把扫雷的矩阵输出出来

我们看看这张图片
minesweeper
这是原版的扫雷界面,通过观察每个方格,可以发现,每个方格都会出现三种状态:已翻开(包括空格和数字,用1表示)、未翻开(包括数字和地雷)和旗子(用户标雷处)

那么,我们可以用"#"表示未翻开的区域,用"P"表示旗子(🚩),用0~9这十个数字表示已翻开区域

但是,井号(#)和旗子(P)都属于字符串类型,我们开的是数组类型int整型,存储不了字符串类型的字符,所以,我们不能把#P赋值给二维数组ui里的某一项,而是得直接输出

逻辑:双重for循环遍历每个方格,如果该方块状态为未翻开,输出#;如果此方块状态为已翻开,直接输出二维数组ui里的这一项;如果此方块已被插旗,则输出P

怎么感觉我说这么多都是废话
看看代码实现吧:

for(int i=1;i<=10;i++){ 
	for(int j=1;j<=10;j++){ //遍历每个方格
		if(b[i][j]==0){ //如果此方块状态为未翻开
				cout<<"#"<<' '; //则输出#
			}else if(b[i][j]==1){ //如果此方块状态为已翻开
				cout<<ui[i][j]<<' '; //直接输出就行
			}else if(b[i][j]==2){ //如果此方块已被插旗
				cout<<"P"<<' '; //输出P(已插旗)
			}
		}cout<<endl;

判断输入

先来定义一下这个游戏的规则:

游戏一开始首先会打印一个10×10的井号(#)方阵,表示扫雷区,接下来让用户输入一个操作命令,再输入横纵坐标,表示要操作的方格。

将雷全部扫完即为胜利,否之,踩到雷即为失败


操作符:

  • q代表翻开坐标处的井号,再输入xy坐标,表示翻开该方格
  • p代表在坐标处插旗,再输入xy坐标,表示在这个方格上插旗(也就是标雷)
  • c代表取消坐标位的旗,再输入xy坐标,表示取消在该位置插旗

坐标判断依据:

上方所述的x,y坐标的具体位置:第x行第y个(从左往右数)
比如这个矩阵(3*3):

  • 5 9 8
  • 2 0 3
  • 8 6 7

x=2y=3 时,表示的数字为3


理解了上面这些逻辑,我们就有了一个大体的思路:
设置状态变量op(char类型)与xy(存储坐标)

  • 如果输入为q,如果该方块为地雷,直接输出You died!;如果为0~8的正常数字,将该方块状态设置为已翻开
if(op=='q'){
	if(ui[x][y]==9){
		cout<<"You died !";
		scanf("%d");
		return 0;
	}
	else{
		b[x][y]=1;
	}
}

然后,再设置变量kk1k为地雷正确位置(客观),k1为用户标雷位置(主观);作用:存储总地雷数,如果k==cnt(总雷数)k==k1的话,说明所有地雷已经扫完,且位置正确(没有把正常方格当成地雷)

  • 如果输入为p,将该方格设为P,状态设为2(标雷),k1自增;如果当前位置有雷,则说明用户判断正确,k自增
else if(op=='p'){
	k1++;
	if(ui[x][y]==9){
		k++;
	}	
	b[x][y]=2;
}
  • 如果输入为c,如果该位置状态为2(插旗),k1自减,如果该位置有地雷,k自减,然后将该格状态设置为0(未翻开);如果该位置没有插旗,用户想撤销(也就是作弊;当然,你也可以删掉这个if,享受当 老六 赢家的快乐),直接跳过(continue)
else if(op=='c'){
	if(b[x][y]==2){
		k1--;
		if(ui[x][y]==9){
			k--;
		}
		b[x][y]=0;
	}else{
		continue;
		}
	}
  • 如果所有地雷已标记(扫完),且位置正确,输出You win!
if(k==cnt1 && k==k1){
	cout<<"You win !";
	scanf("%d");
	return 0;
}

最后,这个判断是要循环实现的。贴上我修改过的完整代码:

#include<bits/stdc++.h>
#include "windows.h"
/*
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <ctime>
#include <iomanip>
*/
#define random(x) 1+rand()%(x)
//#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //用来检测按键的点击事件

using namespace std;

int ui[12][12],b[12][12]; 

int main(){
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); //移除FAST_EDIT模式(Windows10用户) 
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);

	srand(time(NULL)); //random seed
	//system("color 1B");
	system("title MineSweeper");
	int cnt;
	while(cnt){
		int x=random(10);//a+rand()%b = [a, a+b-1]
		int y=random(10);
		if(!ui[x][y]){//if(ui[x][y]==0){
			ui[x][y]=9;
			cnt--;
		}
	}
	cnt=10;
	for(int i=1;i<=cnt;i++){
		for(int j=1;j<=cnt;j++){
			int sum=0;
			if(ui[i][j]!=9){
				if(ui[i-1][j-1]==9) sum++;//sum=!(a[i-1][j-1]-9)+!(a[i-1][j]-9)...
				if(ui[i-1][j]==9) sum++;
				if(ui[i-1][j+1]==9) sum++;
				if(ui[i][j-1]==9) sum++;
				if(ui[i][j+1]==9) sum++;
				if(ui[i+1][j-1]==9) sum++;
				if(ui[i+1][j]==9) sum++;
				if(ui[i+1][j+1]==9) sum++;
				//sum=!(ui[i-1][j-1]-9)+!(ui[i-1][j]-9)+!(ui[i-1][j+1]-9)+!(ui[i][j-1]-9)+!(ui[i][j+1]-9)+!(ui[i+1][j-1]-9)+!(ui[i+1][j]-9)+!(ui[i+1][j+1]-9);
				ui[i][j]=sum;
				
			}
		}
	}
	
	/*for(int i=1;i<=10;i++){
		for(int j=1;j<=10;j++){
			cout<<ui[i][j]<<' '; //output the numbers
		}
		cout<<endl;
	}*/
	
	int k=0,k1=0;
	
	while(true){
		/*for(int i=1;i<=cnt1;i++){
			for(int j=1;j<=cnt1;j++){
			cout<<ui[i][j]<<' '; //output the numbers,cheat code(作弊代码)
		}
		cout<<endl;
	}cout<<endl; */
	
		for(int i=1;i<=cnt;i++){
			for(int j=1;j<=cnt;j++){
				if(b[i][j]==0){
					cout<<"#"<<' ';
				}else if(b[i][j]==1){
					cout<<ui[i][j]<<' ';
				}else if(b[i][j]==2){
					cout<<"P"<<' ';
				}
			}
			cout<<endl;
		}
		char op;
		cin>>op;
		int x,y;
		cin>>x>>y;
		system("cls");
		if(op=='q'){
			if(ui[x][y]==9){
				cout<<"You died !";
				scanf("%d");
				return 0;
			}
			else{
				b[x][y]=1;
			}
		}
		else if(op=='p'){
			k1++;
			if(ui[x][y]==9){
				k++;
			}	
			b[x][y]=2;
		}
		else if(op=='c'){
			if(b[x][y]==2){
				k1--;
				if(ui[x][y]==9){
					k--;
				}
				b[x][y]=0;
			}else{
				continue;
			}
		}
		if(k==cnt && k==k1){
			cout<<"You win !";
			scanf("%d");
			return 0;
		}
	}
    return 0;
} 

MineSweeper
但是,我们现在还有一个问题没有解决:当翻开的数周围8格为0(也就是空格)时,我们应该自动显示出来
下面的代码仅供参考,为测试版,如果有任何bug,请报告作者,谢谢!

#include<bits/stdc++.h>
#include "windows.h"
/*
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <ctime>
#include <iomanip>
*/
#define random(x) 1+rand()%(x)
//#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //用来检测按键的点击事件

using namespace std;

int ui[12][12],b[12][12]; 

int main(){
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); //移除FAST_EDIT模式(Windows10用户) 
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);

	srand(time(NULL)); //random seed
	//system("color 1B");
	system("title MineSweeper");
	int cnt=10;
	while(cnt){
		int x=random(10);//a+rand()%b = [a, a+b-1]
		int y=random(10);
		if(!ui[x][y]){//if(ui[x][y]==0){
			ui[x][y]=9;
			cnt--;
		}
	}
	cnt=10;
	for(int i=1;i<=cnt;i++){
		for(int j=1;j<=cnt;j++){
			int sum=0;
			if(ui[i][j]!=9){
				if(ui[i-1][j-1]==9) sum++;//sum=!(a[i-1][j-1]-9)+!(a[i-1][j]-9)...
				if(ui[i-1][j]==9) sum++;
				if(ui[i-1][j+1]==9) sum++;
				if(ui[i][j-1]==9) sum++;
				if(ui[i][j+1]==9) sum++;
				if(ui[i+1][j-1]==9) sum++;
				if(ui[i+1][j]==9) sum++;
				if(ui[i+1][j+1]==9) sum++;
				//sum=!(ui[i-1][j-1]-9)+!(ui[i-1][j]-9)+!(ui[i-1][j+1]-9)+!(ui[i][j-1]-9)+!(ui[i][j+1]-9)+!(ui[i+1][j-1]-9)+!(ui[i+1][j]-9)+!(ui[i+1][j+1]-9);
				ui[i][j]=sum;
				
			}
		}
	}
	
	/*for(int i=1;i<=10;i++){
		for(int j=1;j<=10;j++){
			cout<<ui[i][j]<<' '; //output the numbers
		}
		cout<<endl;
	}*/
	
	int k=0,k1=0;
	
	while(true){
		for(int i=1;i<=cnt;i++){
			for(int j=1;j<=cnt;j++){
			cout<<ui[i][j]<<' '; //output the numbers
		}
		cout<<endl;
	}cout<<endl; 
	
		for(int i=1;i<=cnt;i++){
			for(int j=1;j<=cnt;j++){
				if(b[i][j]==0){
					cout<<"#"<<' ';
				}else if(b[i][j]==1){
					cout<<ui[i][j]<<' ';
				}else if(b[i][j]==2){
					cout<<"P"<<' ';
				}
			}
			cout<<endl;
		}
		char op;
		cin>>op;
		int x,y;
		cin>>x>>y;
		system("cls");
		if(op=='q'){
			if(ui[x][y]==9){
				cout<<"You died !";
				scanf("%d");
				return 0;
			}
			else{
				if(ui[x-1][y-1]==0) b[x-1][y-1]=1;
				if(ui[x-1][y]==0) b[x-1][y]=1;
				if(ui[x-1][y+1]==0) b[x-1][y+1]=1;
				if(ui[x][y-1]==0) b[x][y-1]=1;
				if(ui[x][y]==0) b[x][y]=1;
				if(ui[x][y+1]==0) b[x][y+1]=1;
				if(ui[x+1][y-1]==0) b[x+1][y-1]=1;
				if(ui[x+1][y]==0) b[x+1][y]=1;
				if(ui[x+1][y+1]==0) b[x+1][y+1]=1;
				b[x][y]=1;
			}
		}
		else if(op=='p'){
			k1++;
			if(ui[x][y]==9){
				k++;
			}	
			b[x][y]=2;
		}
		else if(op=='c'){
			if(b[x][y]==2){
				k1--;
				if(ui[x][y]==9){
					k--;
				}
				b[x][y]=0;
			}else{
				continue;
			}
		}
		if(k==cnt && k==k1){
			cout<<"You win !";
			scanf("%d");
			return 0;
		}
	}
    return 0;
} 

对于一些非Windows设备,可以使用以下代码:

#include<bits/stdc++.h>
/*
#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <ctime>
#include <iomanip>
*/
#define random(x) 1+rand()%(x)

using namespace std;

int ui[12][12],b[12][12]; 

int main(){
	srand(time(NULL)); //random seed
	int cnt=10;
	while(cnt){
		int x=random(10);//a+rand()%b = [a, a+b-1]
		int y=random(10);
		if(!ui[x][y]){//if(ui[x][y]==0){
			ui[x][y]=9;
			cnt--;
		}
	}
	cnt=10;
	for(int i=1;i<=cnt;i++){
		for(int j=1;j<=cnt;j++){
			int sum=0;
			if(ui[i][j]!=9){
				if(ui[i-1][j-1]==9) sum++;//sum=!(a[i-1][j-1]-9)+!(a[i-1][j]-9)...
				if(ui[i-1][j]==9) sum++;
				if(ui[i-1][j+1]==9) sum++;
				if(ui[i][j-1]==9) sum++;
				if(ui[i][j+1]==9) sum++;
				if(ui[i+1][j-1]==9) sum++;
				if(ui[i+1][j]==9) sum++;
				if(ui[i+1][j+1]==9) sum++;
				//sum=!(ui[i-1][j-1]-9)+!(ui[i-1][j]-9)+!(ui[i-1][j+1]-9)+!(ui[i][j-1]-9)+!(ui[i][j+1]-9)+!(ui[i+1][j-1]-9)+!(ui[i+1][j]-9)+!(ui[i+1][j+1]-9);
				ui[i][j]=sum;
				
			}
		}
	}
	
	/*for(int i=1;i<=10;i++){
		for(int j=1;j<=10;j++){
			cout<<ui[i][j]<<' '; //output the numbers
		}
		cout<<endl;
	}*/
	
	int k=0,k1=0;
	
	while(true){
		for(int i=1;i<=cnt;i++){
			for(int j=1;j<=cnt;j++){
			cout<<ui[i][j]<<' '; //output the numbers
		}
		cout<<endl;
	}cout<<endl; 
	
		for(int i=1;i<=cnt;i++){
			for(int j=1;j<=cnt;j++){
				if(b[i][j]==0){
					cout<<"#"<<' ';
				}else if(b[i][j]==1){
					cout<<ui[i][j]<<' ';
				}else if(b[i][j]==2){
					cout<<"P"<<' ';
				}
			}
			cout<<endl;
		}
		char op;
		cin>>op;
		int x,y;
		cin>>x>>y;
		if(op=='q'){
			if(ui[x][y]==9){
				cout<<"You died !";
				scanf("%d");
				return 0;
			}
			else{
				if(ui[x-1][y-1]==0) b[x-1][y-1]=1;
				if(ui[x-1][y]==0) b[x-1][y]=1;
				if(ui[x-1][y+1]==0) b[x-1][y+1]=1;
				if(ui[x][y-1]==0) b[x][y-1]=1;
				if(ui[x][y]==0) b[x][y]=1;
				if(ui[x][y+1]==0) b[x][y+1]=1;
				if(ui[x+1][y-1]==0) b[x+1][y-1]=1;
				if(ui[x+1][y]==0) b[x+1][y]=1;
				if(ui[x+1][y+1]==0) b[x+1][y+1]=1;
				b[x][y]=1;
			}
		}
		else if(op=='p'){
			k1++;
			if(ui[x][y]==9){
				k++;
			}	
			b[x][y]=2;
		}
		else if(op=='c'){
			if(b[x][y]==2){
				k1--;
				if(ui[x][y]==9){
					k--;
				}
				b[x][y]=0;
			}else{
				continue;
			}
		}
		if(k==cnt && k==k1){
			cout<<"You win !";
			scanf("%d");
			return 0;
		}
	}
    return 0;
} 

这篇文章,作者写了三天,给个三连霸!

(转载需通知、注明原作者,并贴上原文链接)

这就是本篇文章的全部内容了,我们下期再见!


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

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

相关文章

【图像处理OpenCV(C++版)】——初学OpenCV

前言&#xff1a; &#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; &#x1f31f;&#x1f31f;&#x1f31f; 本专栏主要结合OpenCV和C来实现一些基本的图像处理算法并详细解释各参数含义&#xff0c;适用于平时学习、工作快…

百数低代码开发平台助力生产管理:制造管理系统

随着全球经济化与信息化&#xff0c;制造企业的生产管理系统的建立对于制造业企业的信息化以及生产的智能化具有重要的意义&#xff0c;同时也是促进现代工业进步和发展的基础条件之一。我国制造业属于传统行业&#xff0c;凭借生产规模大且劳动力资源丰富在全世界拥有着一定地…

[附源码]计算机毕业设计springboot旅游度假村管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Android 反编译入门(基于 Mac)

1 反编译基础 1.1 什么是反编译 定义&#xff1a;反编译就是将可执行程序转换为某种形式的高级编程语言的过程。 1.2 APK 文件的构成 首先&#xff0c;我们通过一张图来看看 APK 的整体组成&#xff1a; 可以看到&#xff0c;APK 主要由六个部分组成&#xff1a; Dex 文件…

什么值得一个头条?从世界杯看“头条”正确打开方式

“足球皇帝”贝肯鲍尔曾说&#xff1a;“在绿茵场上滚动的不是足球&#xff0c;而是黄金。” 卡塔尔世界杯不仅是球迷的盛宴&#xff0c;也是品牌的盛宴。绿茵场广告屏上&#xff0c;众多品牌纷纷现身。还有部分中国企业通过签约球队和球星等形式露面世界杯&#xff0c;共同挖…

【附源码】计算机毕业设计JAVA紫陶文化传播与学习交流网站

【附源码】计算机毕业设计JAVA紫陶文化传播与学习交流网站 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a;…

熤星传媒文化:抖音怎么切换到旧版本?

抖音现在也在不断地更新版本&#xff0c;但是很多小伙伴可能想知道一些新版本的功能&#xff0c;就随着了、系统去升级了&#xff0c;但是用着用着发现自己更喜欢旧版本的&#xff0c;那么抖音店铺又怎么去做店铺带货呢&#xff1f;跟着熤星传媒小编来一起看看吧&#xff01; 帐…

OWASP top10 的介绍

​ OWASP top10 的介绍 2021年版TOP 10产生三个新类别&#xff0c;且进行了一些整合 ​​ A01&#xff1a;失效的访问控制 ​ 从第五位上升称为Web应用程序安全风险最严重的类别&#xff0c;常见的CWE包括&#xff1a;将敏感信息泄露给未经授权的参与者、通过发送的数据泄…

07 CSS04

目标&#xff1a; 1、结构伪类选择器 2、伪元素 3、标准流 4、浮动 5、清除浮动 6、&#xff08;拓展&#xff09;BFC介绍 一、结构伪类选择器 1、作用与优势 作用&#xff1a;根据元素在HTML中的结构关系查找元素 优势&#xff1a;减少对于HTML中类的依赖&#xff0c;有…

[附源码]计算机毕业设计springboot家庭整理服务管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【MySQL】 MySQL亿级数据、主从架构,Sharding分片

数据库Mysql 内容管理MySQL填充亿级数据Insert into select存储过程loop insertLoadfile 导入CVS文件MySQL基准测试&#xff1a; sysbench、mysqlslapsysbenchmysqlslapSQL优化分页查询优化慢SQL日志工具mysqldumpslowMySQL主从复制MySQL主从复制 knowledgeMySQL二进制日志log_…

APS生产计划排产降低企业的生产运营成本

企业运营成本是企业管理的关键&#xff0c;也是企业加强管理&#xff0c;提高企业效益的重要途径&#xff0c;在多数企业的发展中&#xff0c;如何更有效地控制企业运营成本将显得极为突出和十分重要。 APS生产计划排产可以从“设备、物料、人力”三方面降低企业的运营成本&…

基于Go语言的网盘开发(GloudDisk)

&#xff08;记录一下自己做项目的过程&#xff09; 基于go-zero实现的简易的网盘系统&#xff0c;如果有小伙伴对这个项目感兴趣&#xff0c;可以去网上搜索一些资料。这里推荐一下我学习的来源&#xff1a;【项目实战】基于Go-zero、Xorm的网盘系统_哔哩哔哩_bilibili 确定…

AutoCAD Electrical 2022—项目中新建、添加、删除图纸

右键点击项目—选择新建图纸&#xff1b; 点击快捷图标&#xff0c;新建图形&#xff1b; 弹出对话框&#xff0c;在名称中输入图纸名称&#xff1b; 模板为图框的样式&#xff0c;位置代号&#xff0c;图纸保存的位置&#xff1b; 其他根据需要填写&#xff1b; 填写完点击…

JavaScript -- 02. 变量和数据类型

文章目录变量和数据类型1 数值(Number)1.1 普通数值1.2 其他进制的数字2 大整数&#xff08;BigInt&#xff09;3 字符串(String)3.1 基础表示3.2 转义字符3.3 模板字符串4 布尔值(Boolean)5 空值(Null)6 未定义&#xff08;Undefined&#xff09;7 符号&#xff08;Symbol&…

6-2 装载问题(分支限界)

6-2 装载问题&#xff08;分支限界&#xff09; 一、问题描述 有一批共个集装箱要装上2艘载重量分别为C1和C2的轮船&#xff0c;其中集装箱i的重量为Wi&#xff0c;且 采用下面的策略可得到最优装载方案&#xff1a; (1)将第一艘轮船尽可能装满; (2)将剩余集装箱装上第二艘轮…

基于rsync daemon 实现 sersync——sersync实现实时数据同步

1 sersync 介绍 sersync类似于inotify&#xff0c;同样用于监控&#xff0c;但它克服了inotify的缺点. inotify最大的不足是会产生重复事件&#xff0c;或者同一个目录下多个文件的操作会产生多个事件&#xff0c;例如&#xff0c;当监控目录中有5个文件时&#xff0c;删除目录…

[附源码]计算机毕业设计springboot考试系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

学习C语言的优质网站

1. 初衷 C语言是最原始的操作操作数据结构和算法的一门编程语言&#xff0c;没有高级语言的封装&#xff0c;最能锻炼个人的算法思维和能力。 2. 编程网站推荐 2.1 javatpoint https://www.javatpoint.com/static-in-c 2.2 includehelp https://www.includehelp.com/c/ 2.…

Hadoop学习笔记——HDFS

文章目录一、HDFS概述1.1、HDFS产出背景及定义1.1.1 HDFS产生背景1.1.2 HDFS定义1.2、HDFS优缺点1.2.1、HDFS优点1.2.2、HDFS缺点1.3、HDFS组成架构1.4、HDFS文件块大小1.5、限制二、HDFS的Shell操作2.1、基本语法2.2、命令大全2.3、常用命令实操2.3.1 准备工作2.3.2 上传一、H…