C++扫雷

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

int num;
int sx,sy;
struct Mine
{
	bool isMine;
	int n;
	bool isopened;
	bool iswrited;
}a[105][105];
struct Point
{
	int x,y;
}rd[10005];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

void memsetall();
void easy();
void middle();
void hard();
void custom();
void setPoint();
void dfs(int,int);
bool inArea(int,int);
void output();

#define toWhite SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE)
#define toRed SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED)
#define toGreen SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN)
#define toBlue SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE)
#define toYellow SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN)
#define toPink SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_BLUE)
#define toAqua SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_GREEN)

int main()
{
	srand(time(0));
	while(1)
	{
		memsetall();
		toYellow;
		printf("\n请输入你选择的难度:\n");
		toWhite;
		printf("> easy(10*10,8~12个雷)\n> middle(20*20,35~45个雷)\n> hard(30*30,65~80个雷)\n> custom(自定义)\n\n");
		string s;
		toAqua;cin>>s;toWhite;
		printf("\n");
		if(s=="easy")
		  easy();
		else if(s=="middle")
		  middle();
		else if(s=="hard")
		  hard();
		else if(s=="custom")
		  custom();
		else
		{
			toRed;
			printf("\n输入错误,请重新输入!\n\n");
			toWhite;
			continue;
		}
		while(1)
		{
			toYellow;
			printf("\n输入next重新开始游戏,输入close结束游戏\n\n");
			toAqua;
			string ss;
			cin>>ss;
			toWhite;
			if(ss=="next")
			{
				system("cls");
				break;
			}
			else if(ss=="close")
			  exit(0);
			else
			  toRed,printf("\n输入错误,请重新输入!\n");
			toWhite;
		}
	}
	return 0;
}

void memsetall()
{
	num=0,sx=0,sy=0;
	memset(a,0,sizeof a);
	memset(rd,0,sizeof rd);
	return ;
}
void easy()
{
	num=8+rand()%3;
	sx=10,sy=10;
	setPoint();
	toPink;
	printf("提前声名:?是未打开的格子,@是标记的格子\n\n");
	while(1)
	{
		output();
		int x=0,y=0,op=-1;
		while(1)
		{
			toYellow;
			printf("\n请输入格子编号(第i行第j列,要打开输出0,要标记输出1):\n");
			toWhite;
			printf("i:");
			toAqua;
			scanf("%d",&x);
			toWhite;
			printf("j:");
			toAqua;
			scanf("%d",&y);
			toWhite;
			printf("打开/标记:");
			toAqua;
			scanf("%d",&op);
			if(x>sx || y>sy || (op!=0 && op!=1))
			  toRed,printf("\n输入错误,请重新输入!\n");
			else if(a[x][y].isopened || (a[x][y].iswrited && op==1))
			  toRed,printf("\n无效输入,请重新输入!\n");
			else
			  break;
		}
		toWhite;
		printf("\n");
		if(op)
		  a[x][y].iswrited=true;
		else
		{
			if(a[x][y].isMine)
			{
				for(int i=1;i<=sx;i++)
				{
					for(int j=1;j<=sy;j++)
					{
						if(a[i][j].isMine)
						  toRed,printf("* ");
						else
						  toWhite,printf("%d ",a[i][j].n);
					}
					printf("\n");
				}
				toRed;
				printf("\n挑战失败!\n");
				return ;
			}
			a[x][y].isopened=true;
			if(a[x][y].n==0)
			  dfs(x,y);
		}
		int total=0;
		for(int i=1;i<=sx;i++)
			for(int j=1;j<=sy;j++)
				if(!a[i][j].isopened)
				  total++;
		if(total==num)
		  break;
	}
	for(int i=1;i<=sx;i++)
	{
		for(int j=1;j<=sy;j++)
		{
			if(a[i][j].isMine)
			  toGreen,printf("* ");
			else
			  toWhite,printf("%d ",a[i][j].n);
		}
		printf("\n");
	}
	toGreen;
	printf("\n挑战成功!\n");
	return ;
}

void middle()
{
	num=35+rand()%9;
	sx=20,sy=20;
	setPoint();
	toPink;
	printf("提前声名:?是未打开的格子,@是标记的格子\n\n");
	while(1)
	{
		output();
		int x=0,y=0,op=-1;
		while(1)
		{
			toYellow;
			printf("\n请输入格子编号(第i行第j列,要打开输出0,要标记输出1):\n");
			toWhite;
			printf("i:");
			toAqua;
			scanf("%d",&x);
			toWhite;
			printf("j:");
			toAqua;
			scanf("%d",&y);
			toWhite;
			printf("打开/标记:");
			toAqua;
			scanf("%d",&op);
			if(x>sx || y>sy || (op!=0 && op!=1))
			  toRed,printf("\n输入错误,请重新输入!\n");
			else if(a[x][y].isopened || (a[x][y].iswrited && op==1))
			  toRed,printf("\n无效输入,请重新输入!\n");
			else
			  break;
		}
		toWhite;
		printf("\n");
		if(op)
		  a[x][y].iswrited=true;
		else
		{
			if(a[x][y].isMine)
			{
				for(int i=1;i<=sx;i++)
				{
					for(int j=1;j<=sy;j++)
					{
						if(a[i][j].isMine)
						  toRed,printf("* ");
						else
						  toWhite,printf("%d ",a[i][j].n);
					}
					printf("\n");
				}
				toRed;
				printf("\n挑战失败!\n");
				return ;
			}
			a[x][y].isopened=true;
			if(a[x][y].n==0)
			  dfs(x,y);
		}
		int total=0;
		for(int i=1;i<=sx;i++)
			for(int j=1;j<=sy;j++)
				if(!a[i][j].isopened)
				  total++;
		if(total==num)
		  break;
	}
	for(int i=1;i<=sx;i++)
	{
		for(int j=1;j<=sy;j++)
		{
			if(a[i][j].isMine)
			  toGreen,printf("* ");
			else
			  toWhite,printf("%d ",a[i][j].n);
		}
		printf("\n");
	}
	toGreen;
	printf("\n挑战成功!\n");
	return ;
}

void hard()
{
	num=65+rand()%16;
	sx=30,sy=30;
	setPoint();
	toPink;
	printf("提前声名:?是未打开的格子,@是标记的格子\n\n");
	while(1)
	{
		output();
		int x=0,y=0,op=-1;
		while(1)
		{
			toYellow;
			printf("\n请输入格子编号(第i行第j列,要打开输出0,要标记输出1):\n");
			toWhite;
			printf("i:");
			toAqua;
			scanf("%d",&x);
			toWhite;
			printf("j:");
			toAqua;
			scanf("%d",&y);
			toWhite;
			printf("打开/标记:");
			toAqua;
			scanf("%d",&op);
			if(x>sx || y>sy || (op!=0 && op!=1))
			  toRed,printf("\n输入错误,请重新输入!\n");
			else if(a[x][y].isopened || (a[x][y].iswrited && op==1))
			  toRed,printf("\n无效输入,请重新输入!\n");
			else
			  break;
		}
		toWhite;
		printf("\n");
		if(op)
		  a[x][y].iswrited=true;
		else
		{
			if(a[x][y].isMine)
			{
				for(int i=1;i<=sx;i++)
				{
					for(int j=1;j<=sy;j++)
					{
						if(a[i][j].isMine)
						  toRed,printf("* ");
						else
						  toWhite,printf("%d ",a[i][j].n);
					}
					printf("\n");
				}
				toRed;
				printf("\n挑战失败!\n");
				return ;
			}
			a[x][y].isopened=true;
			if(a[x][y].n==0)
			  dfs(x,y);
		}
		int total=0;
		for(int i=1;i<=sx;i++)
			for(int j=1;j<=sy;j++)
				if(!a[i][j].isopened)
				  total++;
		if(total==num)
		  break;
	}
	for(int i=1;i<=sx;i++)
	{
		for(int j=1;j<=sy;j++)
		{
			if(a[i][j].isMine)
			  toGreen,printf("* ");
			else
			  toWhite,printf("%d ",a[i][j].n);
		}
		printf("\n");
	}
	toGreen;
	printf("\n挑战成功!\n");
	return ;
}

void custom()
{
	while(1)
	{
		toYellow;
		printf("请输入地雷范围(n行m列)(n<=50且m<=50):\n");
		toWhite;
		printf("n:");
		toAqua;
		scanf("%d",&sx);
		toWhite;
		printf("m:");
		toAqua;
		scanf("%d",&sy);
		if(sx>50 || sy>50)
		{
			toRed;
			printf("\n范围超限,请重新输入!\n\n");
		}
		else
		  break;
	}
	while(1)
	{
		toYellow;
		printf("\n请输入地雷个数(<=2500):");
		toAqua;
		scanf("%d",&num);
		if(num>2500)
		{
			toRed;
			printf("\n范围超限,请重新输入!\n");
		}
		else
		  break;
	}
	printf("\n");
	toWhite;
	setPoint();
	toPink;
	printf("提前声名:?是未打开的格子,@是标记的格子\n\n");
	while(1)
	{
		output();
		int x=0,y=0,op=-1;
		while(1)
		{
			toYellow;
			printf("\n请输入格子编号(第i行第j列,要打开输出0,要标记输出1):\n");
			toWhite;
			printf("i:");
			toAqua;
			scanf("%d",&x);
			toWhite;
			printf("j:");
			toAqua;
			scanf("%d",&y);
			toWhite;
			printf("打开/标记:");
			toAqua;
			scanf("%d",&op);
			if(x>sx || y>sy || (op!=0 && op!=1))
			  toRed,printf("\n输入错误,请重新输入!\n");
			else if(a[x][y].isopened || (a[x][y].iswrited && op==1))
			  toRed,printf("\n无效输入,请重新输入!\n");
			else
			  break;
		}
		toWhite;
		printf("\n");
		if(op)
		  a[x][y].iswrited=true;
		else
		{
			if(a[x][y].isMine)
			{
				for(int i=1;i<=sx;i++)
				{
					for(int j=1;j<=sy;j++)
					{
						if(a[i][j].isMine)
						  toRed,printf("* ");
						else
						  toWhite,printf("%d ",a[i][j].n);
					}
					printf("\n");
				}
				toRed;
				printf("\n挑战失败!\n");
				return ;
			}
			a[x][y].isopened=true;
			if(a[x][y].n==0)
			  dfs(x,y);
		}
		int total=0;
		for(int i=1;i<=sx;i++)
			for(int j=1;j<=sy;j++)
				if(!a[i][j].isopened)
				  total++;
		if(total==num)
		  break;
	}
	for(int i=1;i<=sx;i++)
	{
		for(int j=1;j<=sy;j++)
		{
			if(a[i][j].isMine)
			  toGreen,printf("* ");
			else
			  toWhite,printf("%d ",a[i][j].n);
		}
		printf("\n");
	}
	toGreen;
	printf("\n挑战成功!\n");
	return ;
}

void setPoint()
{
	for(int i=1;i<=num;i++)
	{
		int ttx,tty;
		bool found=true;
		while(found)
		{
			ttx=1+rand()%sx;
			tty=1+rand()%sy;
			found=false;
			for(int j=1;j<i;j++)
				if(rd[j].x==ttx && rd[j].y==tty)
				{
					found=true;
					break;
				}
		}
		rd[i].x=ttx,rd[i].y=tty;
		a[ttx][tty].isMine=true;
	}
	for(int i=1;i<=sx;i++)
		for(int j=1;j<=sy;j++)
		{
			if(a[i][j].isMine)
			  continue;
			int tmp=0;
			if(a[i-1][j].isMine)
			  tmp++;
			if(a[i+1][j].isMine)
			  tmp++;
			if(a[i][j+1].isMine)
			  tmp++;
			if(a[i][j-1].isMine)
			  tmp++;
			if(a[i-1][j+1].isMine)
			  tmp++;
			if(a[i-1][j-1].isMine)
			  tmp++;
			if(a[i+1][j-1].isMine)
			  tmp++;
			if(a[i+1][j+1].isMine)
			  tmp++;
			a[i][j].n=tmp;
		}
	return ;
}

void dfs(int x,int y)
{
	a[x][y].isopened=true;
	for(int i=0;i<4;i++)
	{
		int nX,nY;
		nX=x+dir[i][0];
		nY=y+dir[i][1];
		if(a[nX][nY].n!=0 && !a[nX][nY].isopened)
		  a[nX][nY].isopened=true;
		if(a[nX][nY].n==0 && !a[nX][nY].isopened && inArea(nX,nY))
		  dfs(nX,nY);
	}
	return ;
}

bool inArea(int x,int y)
{
	return x>0 && x<=sx && y>0 && y<=sy;
}

void output()
{
	for(int i=1;i<=sx;i++)
	{
		for(int j=1;j<=sy;j++)
		{
			if(!a[i][j].isopened && a[i][j].iswrited)
			  toPink,printf("@ ");
			else if(!a[i][j].isopened)
			  toGreen,printf("? ");
			else
			  toWhite,printf("%d ",a[i][j].n);
		}
		printf("\n");
	}
	return ;
}