IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 扫雷小游戏 -> 正文阅读

[游戏开发]扫雷小游戏

一个简单的扫雷小游戏,可以用键盘控制光标来对格子进行操作。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<conio.h>

#define KONG 0  //方块被消除后不显示数字的格子
#define KONG_WITH_NUMBER 3  //方块被消除后显示数字的格子
#define WALL 2  //围住方块的四周格子,不可消除
#define BOX 1	//待操作的方块
#define LEFT  75
#define RIGHT 77
#define UP 72
#define DOWN 80
#define ESC 27

struct Face
{
	int data[18][18];	
}face;
struct Mode
{
	int FACE_Y;
	int FACE_X;
	int BOMBNUMBER;	//炸弹数量
}mode;
struct BOOM
{
	int data[18][18];//为1时该位置是炸弹,为0时不是炸弹
}boom;
struct MARK
{
	int data[18][18];//为1时该位置标记为炸弹,为0时没有标记
	int number;//记录标记的数量
}mark;
struct DISPLAY
{
	int data[18][18];//为1时该位置显示数字,为0时不显示
}display;

int menu();
void Start_Game();
void Inter_Face();
void Cursor(int c);	//改光标可见状态
void gotoxy(int x,int y);	//坐标跳转
void display_number(int x,int y);
void markbox(int x,int y);
int bomb_number(int x,int y);
void setbomb(int x,int y,int z);
void win();
void gameover();
void setzero();

int main()
{
	int gamemode;
	system("title 扫雷");    //设置cmd窗口标题
	system("mode con lines=16 cols=35");    //设置cmd窗口高度、宽度
	system("color f0");
	gamemode=menu();
	if(gamemode==1)
	{
		mode.BOMBNUMBER=12;
		mode.FACE_Y=9;
		mode.FACE_X=9;
	}
	else
	{
		mode.BOMBNUMBER=42;
		mode.FACE_Y=16;
		mode.FACE_X=16;
	}
	Cursor(1);   
	Inter_Face();
	srand(time(NULL));	//main函数中设置srand((unsigned)time(NULL));时,影响的将是所有的rand
	while (1)
	{
		Start_Game();
	}
	return 0;
}

int menu()  //生成开始菜单。
{
	char a;
	int b;
	while(1)
	{
		system("cls");
		Cursor(0);
		gotoxy(0,0);
		printf("+++++++++++++++++++++++++++++++++++\n");
		printf("+                                 +\n");
		printf("+                                 +\n");
		printf("+           扫雷小游戏            +\n");
		printf("+                                 +\n");
		printf("+                                 +\n");
		printf("+           请选择难度            +\n");
		printf("+                                 +\n");
		printf("+          1、简单模式            +\n");
		printf("+                                 +\n");
		printf("+          2、困难模式            +\n");
		printf("+                                 +\n");
		printf("+    请输入序号(1/2)来开始游戏  +\n");
		printf("+                                 +\n");
		printf("+++++++++++++++++++++++++++++++++++\n");
		a=getch();
		if(a=='1')
		{
			b=1;
			break;
		}
		else if(a=='2')
		{
			b=2;
			break;
		}
	}
	return b;
}

void Start_Game()
{
	int m,n,numb=0;
	char ch;
	setzero();
	setbomb(0,0,0);  //总体设置炸弹,不需用到这些参数,随便写三个数,只要第三个不是1就行。
	m=(mode.FACE_X%2==0?mode.FACE_X:mode.FACE_X+1);  //要使m为偶数,否则方块设置会有问题。
	n=mode.FACE_X/2;
	gotoxy(m,n);
	while(1)
	{
		Cursor(1);  //使光标一直可见,不会因为不恰当的输入而突然消失。
		fflush(stdin);
		ch=getch();
		switch(ch)    //对光标进行移动
		{
		case LEFT:
			m-=2;
			gotoxy(m,n);
			break;
		case RIGHT:
			m+=2;
			gotoxy(m,n);
			break;
		case UP:
			n-=1;
			gotoxy(m,n);
			break;
		case DOWN:
			n+=1;
			gotoxy(m,n);
			break;
		case 'd':
		case 'D':
			numb++;
			if(numb==1 && boom.data[m/2][n]==1)
			{
				setbomb(m,n,1);
				display_number(m,n);
			}
			else if(boom.data[m/2][n]==1)
				gameover();
			else if(face.data[m/2][n]==BOX)
				display_number(m,n);
			break;
		case 'a':
		case 'A':
			markbox(m,n);
			break;
		case ESC:
			system("cls");
			gotoxy(0,0);
			printf("---游戏结束!---\n");
			exit(0);
            break;
		default:
			Cursor(1); 
			break;
		}
		win();
	}
}

void setzero()  //清空信息。
{
	int m,n;
	for(m=1;m<mode.FACE_Y+1;m++)  //再次开始游戏前,先把原本的标记信息清空。
		for(n=1;n<mode.FACE_X+1;n++)
			mark.data[m][n]=0;
	mark.number=0;//标记数量置零。
	for(m=1;m<mode.FACE_Y+1;m++)  //再次开始游戏前,先把原本的炸弹清空。
		for(n=1;n<mode.FACE_X+1;n++)
			boom.data[m][n]=0;
}

void win()  //判断是否胜利。
{
	int m,n,numb1=0,numb2=0,flag=0;
	char ch;
	for(m=1;m<mode.FACE_Y+1;m++)  //判断是否标记出所有的炸弹。
	{	for(n=1;n<mode.FACE_X+1;n++)
		{
			if(boom.data[m][n]==1)
				if(mark.data[m][n]==1)
					numb1++;
		}
	}
	for(m=1;m<mode.FACE_Y+1;m++)  //判断是否排除出所有不是炸弹的格子。
	{	for(n=1;n<mode.FACE_X+1;n++)
		{
			if(face.data[m][n]!=KONG_WITH_NUMBER)
					numb2++;
		}
	}
	if(numb1==mode.BOMBNUMBER || numb2==mode.BOMBNUMBER)
	{
		gotoxy(0,mode.FACE_Y+4);
		printf("\033[30m------成功啦!游戏结束------");
		while(flag==0)
		{
			gotoxy(0,mode.FACE_Y+5);
			printf("是否开启新游戏?(y/n): \b");
			scanf("%c", &ch);
			if (ch == 'Y' || ch == 'y')
			{
				flag=1;
				system("cls");    // 重新开始游戏前,清屏
				main();
			}
			else if (ch == 'N' || ch == 'n')
			{
				flag=1;
				exit(0);
			}
			else
			{
				gotoxy(0,mode.FACE_Y+6);
				printf("输入错误,请重新输入!");
			}
		}
	}
}

void setbomb(int x,int y,int z)  //设置炸弹。
{
	int i,m,n,a,b;
	if(z==1)  //第一次就碰到炸弹的话,为了游戏体验,贴心地把第一个炸弹移走。
	{
		a=x/2; b=y;
		m=rand()%mode.FACE_Y; n=rand()%mode.FACE_X;  //随机产生炸弹所在的位置。
		while(boom.data[m+1][n+1]==1)  //如果该位置已有炸弹,则寻找其他位置。
		{
			m=rand()%mode.FACE_Y;
			n=rand()%mode.FACE_X;
		}
		boom.data[m+1][n+1]=1;
		boom.data[a][b]=0;  //第一次的位置变成没有炸弹的状态。
	}
	else
	{
		for(i=0;i<mode.BOMBNUMBER;i++)    //设置炸弹
		{	
			m=rand()%mode.FACE_Y; n=rand()%mode.FACE_X;  //随机产生炸弹所在的位置。
			while(boom.data[m+1][n+1]==1)   //如果该位置已有炸弹,则寻找其他位置。
			{
				m=rand()%mode.FACE_Y;
				n=rand()%mode.FACE_X;
			}
			boom.data[m+1][n+1]=1; 
		}
	}
}	

void markbox(int x,int y)  //标记格子。
{
	int m=x/2,n=y;
	if(face.data[m][n]==BOX)
	{
		if(mark.data[m][n]==0)
		{
			mark.data[m][n]=1;
			mark.number++;  //使显示的标记数量加1。
			gotoxy(2*mode.FACE_X+16,2);  //改变显示的标记数量。 
			printf("\033[1;35m""%2d",mark.number);  //%2d的使用,这样从两位数变一位数时才不会乱。
			gotoxy(x+2,y);
			printf("\b\b");
			printf("\033[1;34m""■");  //"\033[1;34m"让其之后的全部字符显示为浅蓝色。"\033[m"让颜色的效果消去。
			gotoxy(x,y);
		}
		else if(mark.data[m][n]==1)
		{
			mark.data[m][n]=0;
			mark.number--;
			gotoxy(2*mode.FACE_X+16,2);  //改变显示的标记数量。 
			printf("\033[1;35m""%2d",mark.number);  
			gotoxy(x+2,y);
			printf("\b\b");
			printf("\033[1;33m""■");  
			gotoxy(x,y);
		}
	}
}

void gameover()  //失败,游戏结束。
{
	int m,n,flag=0;
	char ch;
	for(m=1;m<mode.FACE_Y+1;m++)  //让所有炸弹显示出来,代表结束。
	{	for(n=1;n<mode.FACE_X+1;n++)
		{
			if(boom.data[m][n]==1)
			{	
				gotoxy(2*(m+1),n);
				printf("\b\b");
				printf("\033[31m●\033[37m");  //"\033[31m●\033[37m"让其之后的全部字符显示为红色。
			}
		}
	}
	gotoxy(0,mode.FACE_Y+4);
	printf("\033[30m------失败啦!游戏结束------");
	while(flag==0)
	{
		gotoxy(0,mode.FACE_Y+5);
		printf("是否开启新游戏?(y/n): \b");
		scanf("%c", &ch);
		if (ch == 'Y' || ch == 'y')
		{
			flag=1;
			system("cls");    // 重新开始游戏前,清屏
			main();
		}
		else if (ch == 'N' || ch == 'n')
		{
			flag=1;
			exit(0);
		}
		else
		{
			gotoxy(0,mode.FACE_Y+6);
			printf("输入错误,请重新输入!");
		}
	}
}

int bomb_number(int x,int y)  //判断中心格周围8个格中炸弹的数目。
{
	int  m=x/2,n=y,i,j,count=0;
	for(i=m-1;i<m+2;i++)
	{	for(j=n-1;j<n+2;j++)	
		{		if(boom.data[i][j]==1)
						count++;
		}
	}
	return count;
}

void display_number(int x,int y)  //消除方块后非炸弹格显示数字。
{
	int  m=x/2,n=y,i,j,count=0;
	if(mark.data[m][n]==1)  //显示数字后的格子当成失去标记。
	{	
		mark.data[m/2][n]=0;
		mark.number--;
	}
	gotoxy(2*mode.FACE_X+16,2);  //改变显示的标记数量。 
	printf("\033[1;35m""%2d",mark.number);  
	gotoxy(x,y);
	if(face.data[m][n]==BOX && boom.data[m][n]==0)  //递归时判断是否为没扫过的格或炸弹位置。
	{
		count=bomb_number(x,y);
		if(count==0)
		{
			face.data[m][n]=KONG;
			gotoxy(x+2,y);
			printf("\033[1;35m""\b\b");
			printf("  ");
			gotoxy(x,y);
			for(i=m-1;i<m+2;i++)
			{	
				for(j=n-1;j<n+2;j++)
				{
					if(i>0 && i<=mode.FACE_Y && j>0 && j<=mode.FACE_X)
					{	if(i!=m ||j!=n)
							display_number(2*i,j);}
				}
			}
		}
		else
		{
			face.data[m][n]=KONG_WITH_NUMBER;
			gotoxy(x+2,y);
			printf("\033[1;35m""\b\b");
			printf(" %d",count);
			gotoxy(x,y);
		}
	}
}

void gotoxy(int x,int y)    //坐标跳转
{
	COORD coord;	//COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标。
	coord.X = x;
	coord.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);                            //SetConsoleCursorPosition是一个API(应用程序编程接口),可以设置控制台窗口中光标的位置。
}

void Inter_Face()    //初始化界面
{
	int i,j;
	system("cls");
	if(mode.FACE_X==16)
	{
		system("mode con lines=24 cols=60");    //设置cmd窗口高度、宽度
		gotoxy(2*mode.FACE_X+6,1);
		printf("\033[1;35m""炸弹数量:%d",mode.BOMBNUMBER);
		gotoxy(2*mode.FACE_X+6,2);
		printf("标记数量:%d",mark.number);  //但是这里的标记数量不会一直改变。
		gotoxy(2*mode.FACE_X+6,4);
		printf("ESC键:退出游戏");
		gotoxy(2*mode.FACE_X+6,6);
		printf("键盘↑键:光标上移");
		gotoxy(2*mode.FACE_X+6,7);
		printf("键盘↓键:光标下移");
		gotoxy(2*mode.FACE_X+6,8);
		printf("键盘←键:光标左移");
		gotoxy(2*mode.FACE_X+6,9);
		printf("键盘→键:光标右移");
		gotoxy(2*mode.FACE_X+6,11);
		printf("键盘a键:标记炸弹");
		gotoxy(2*mode.FACE_X+15,12);
		printf("再按取消");
		gotoxy(2*mode.FACE_X+6,14);
		printf("键盘d键:消除方块");
	}
	else if(mode.FACE_X==9)
	{
		system("mode con lines=17 cols=43");    //设置cmd窗口高度、宽度
		gotoxy(2*mode.FACE_X+6,1);
		printf("\033[1;35m""炸弹数量:%d",mode.BOMBNUMBER);
		gotoxy(2*mode.FACE_X+6,2);
		printf("标记数量:%d",mark.number);
		gotoxy(2*mode.FACE_X+6,4);
		printf("ESC键:退出游戏");
		gotoxy(2*mode.FACE_X+6,6);
		printf("方向键:光标移动");
		gotoxy(2*mode.FACE_X+6,8);
		printf("键盘a键:标记炸弹");
		gotoxy(2*mode.FACE_X+15,9);
		printf("再按取消");
		gotoxy(2*mode.FACE_X+6,10);
		printf("键盘d键:消除方块");
	}
	gotoxy(0,0);
	for(i=0;i<mode.FACE_Y+2;i++)
	{
		for(j=0;j<mode.FACE_X+2;j++)
		{
			if(i==0 || i==mode.FACE_Y+1 || j==0 || j==mode.FACE_X+1)
			{
				face.data[i][j]=WALL;
				printf("\033[1;35m""■");
			}
			else
			{
				face.data[i][j]=BOX;
				printf("\033[1;33m""■");
			}
		}
		gotoxy(0,1+i);//让光标跳到每列的最左边
	}
}

void Cursor(int c)    //改变光标可见状态。
{
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);	//GetStdHandle是一个Windows API函数。它用于从一个特定的标准设备(标准输入、标准输出或标准错误)中取得一个句柄(用来标识不同设备的数值)。
	CONSOLE_CURSOR_INFO cci;	
	GetConsoleCursorInfo(hOut, &cci);	
	cci.bVisible = c;	//赋值0为隐藏,赋值1为可见
	SetConsoleCursorInfo(hOut, &cci);
}

?

?

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-05 17:40:59  更:2021-08-05 17:41:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/26 9:06:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码