⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 VC++实现的扫雷小游戏
💻 CPP
字号:
//---------------------------------------------------------------------------
//程  序  :  Windows扫雷
//作  者  :  蛮·com
//开发环境:  Borland C++ Builder 2006
//E-Mail  :  smallmenu@163.com
//日  期  :  2007年7月25日
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include "main.h"
#include "main2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

#define Block   15    //雷块大小
#define TWidth  13    //时间块宽
#define THeight 23    //时间块高

#define Unopen  10    //雷状态标记
#define Open    20
#define Unflag  30
#define Flag    40

int  Mopened;         //已挖开雷数
int  Mflag;           //已标记雷数
int  Mtimer;          //时间
bool Gamestate;       //游戏状态
bool Timestate;       //时间状态

int  BWidth  = 9;     //雷块宽高个数
int  BHeight = 9;
int  BNum    = 10;    //总雷数
int  *State  = NULL;  //雷区操作状态存储
int  *Mine   = NULL;  //雷区有无雷雷状态存储
int  left = 3,top = 3;//界面贴图边距

//矩形变量,存储贴图、被贴图区域的坐标矩形
TRect RBlock, RTime, RDest;

//位图变量,存储游戏所需载入的位图
Graphics::TBitmap *BBlock = NULL;
Graphics::TBitmap *BTime  = NULL;

//---------------------------------------------------------------------------
//自定义成员函数开始
//---------------------------------------------------------------------------

void TMainForm::InitMine()
{
	int x, y;
	int i, j;
	Gamestate = true;
	Timestate = false;
	Mopened = 0;
	Mflag  = 0;
	Mtimer = 0;

	//分配内存,载入位图文件,
	if (!BBlock)
	{
		BBlock = new Graphics::TBitmap;
		BBlock->LoadFromFile("Mine.bmp");
	}
	if (!BTime)
	{
		BTime  = new Graphics::TBitmap;
		BTime->LoadFromFile("Num.bmp");
	}
	if (Mine)
	{
		delete []Mine;
	}
	try
	{
		if (State)
		{
			delete []State;
		}
	}
	catch(...)
	{
	//**************此处抛出异常**************
	}
	Mine  = new int[BWidth * BHeight];
	State = new int[BWidth * BHeight];

	//随机数发生器,初始化变量并随机布雷
	randomize();
	for (i = 0; i < BWidth; i++)
	{
		for (j = 0; j < BHeight; j++)
		{
			Mine[BWidth*i + j] = 0;
			State[BWidth*i +j] = Unopen;
		}
	}
	for (i = 0; i < BNum; i++)
	{
		x = random(BWidth);
		y = random(BHeight);
		if (Mine[x*BWidth + y])
		{
			i--;
			continue;
		}
		else Mine[x*BWidth + y] = 1; 
	}

	//绘制界面,标记,时间
	DrawMine();
	DrawFlag(BNum);
	DrawTime(0);
}

void TMainForm::DrawMine()
{
	Image1->Canvas->Pen->Color = RGB(140, 140, 140);
	Image1->Canvas->Brush->Color = RGB(140, 140, 140);
	Image1->Canvas->Rectangle(0, 0, Image1->Width, Image1->Height);
	RBlock = Rect(0*Block, 0, 1*Block, Block);
	for (int i = 0; i < BWidth; i++)
	{
		for (int j = 0; j < BHeight; j++)
		{
			RDest = Rect(i*Block+left, j*Block+top,
					(i+1)*Block+left-1, (j+1)*Block+top-1);
			Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
		}
	}
}

int TMainForm::CountMine(int ix, int iy)
{
	int num = 0;

	//计算此处周围八个方向所包含的雷数
	for (int i = ix-1; i <= ix+1; i++)
	{
		for (int j = iy-1; j <= iy+1; j++)
		{
			if (i<0 || j<0 || i>BWidth-1 || j>BHeight-1 || (i==ix && j==iy))
				continue;
			else
			{
				if (Mine[i*BWidth + j])
					num++;
			}
		}
	}
	return num;
}

void TMainForm::OpenMine(int ix, int iy)
{
	int  num = CountMine(ix, iy);

	//雷状态为未挖开状态
	if (State[ix*BWidth + iy] == Unopen)
	{
		State[ix*BWidth + iy] = Open;
		RDest = Rect(ix*Block+left, iy*Block+top,
			(ix+1)*Block+left-1, (iy+1)*Block+top-1);

		//如果此处无雷
		if (!Mine[ix*BWidth + iy])
		{
			RBlock = Rect(1*Block, 0, 2*Block, Block);
			Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
			Mopened++;

			//如果该处该处四周均没有雷,递归调用,挖开四周八个方向的雷
			if (num)
			{
				RBlock = Rect((4+num)*Block, 0, (5+num)*Block, Block);
				Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
				Judge();
			}
			else
			{
				for (int i = ix-1; i <= ix+1; i++)
				{
					for (int j = iy-1; j <= iy+1; j++)
					{
						if (i<0 || j<0 || i>BWidth-1 ||
							j>BHeight-1 || (i==ix && j==iy))
							continue;
						else
							OpenMine(i, j);
					}
				}
			}
		}

		//此处有雷,游戏结束
		else
		{
			RBlock = Rect(3*Block, 0, 4*Block, Block);
			Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
			Gamestate = false;
			Judge();
		}
	}
	else
		return;
}

void TMainForm::FlagMine(int ix, int iy)
{
	//雷状态为未挖开状态
	if (State[ix*BWidth + iy] == Unopen)
	{
		Mflag++;
		State[ix*BWidth + iy] = Flag;
		RDest = Rect(ix*Block+left, iy*Block+top,
			(ix+1)*Block+left-1, (iy+1)*Block+top-1);
		RBlock = Rect(2*Block, 0, 3*Block, Block);
		Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);

		//绘制标记数
		DrawFlag(BNum - Mflag);
		Judge();
	}

	//雷状态为标记状态
	else if (State[ix*BWidth + iy] == Flag)
	{
		Mflag--;
		RBlock = Rect(0*Block, 0, 1*Block, Block);
		RDest = Rect(ix*Block+left, iy*Block+top,
			(ix+1)*Block+left-1, (iy+1)*Block+top-1);
		Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
		State[ix*BWidth + iy] = Unopen;
		DrawFlag(BNum - Mflag);
	}
	else
		return;
}
void TMainForm::AutoMine(int ix, int iy)
{
	int num = CountMine(ix, iy);
	int openmine = 0;

	//自动挖雷,如果该处四周包含雷全部标记,则自动挖开其他雷区
	if (State[ix*BWidth + iy] == Open)
	{
		for (int i = ix-1; i <= ix+1; i++)
		{
			for (int j = iy-1; j <= iy+1; j++)
			{
				if (i<0 || j<0 || i>BWidth-1 ||
				j>BHeight-1 || (i==ix && j==iy))
					continue;
				else
				{
					if (State[i*BWidth + j] == Flag)
						openmine++;
				}
			}
		}
	}
	if (num == openmine)
	{
		for (int i = ix-1; i <= ix+1; i++)
		{
			for (int j = iy-1; j <= iy+1; j++)
			{
				if (i<0 || j<0 || i>BWidth-1 ||
					j>BHeight-1 || (i==ix && j==iy))
					continue;
				else
					OpenMine(i, j);
			}
		}
	}
}

void TMainForm::DrawFlag(int flag)
{
	int l = 3, t =5;
	int num1, num2, num3;

	//分离标记的各位数,分别贴出
	if (flag >= 0)
	{
		num3 = flag % 10;
		num1 = flag / 100;
		num2 = (flag - num1*100) / 10;
		Image2->Canvas->Rectangle(0, 0, Image2->Width,
					Image2->Height);
		RBlock = Rect(num2*TWidth, 0, (num2+1)*TWidth, THeight);
		RDest = Rect(l+TWidth, t, l+TWidth*2, t+THeight);
		Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
		RBlock = Rect(num3*TWidth, 0, (num3+1)*TWidth, THeight);
		RDest = Rect(l+TWidth*2, t, l+TWidth*3, t+THeight);
		Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
		RBlock = Rect(num1*TWidth, 0, (num1+1)*TWidth, THeight);
		RDest = Rect(l, t, l+TWidth, t+THeight);
		Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
	}
	else
	{
		flag = flag * (-1);
		num3 = flag % 10;
		num1 = flag / 100;
		num2 = (flag - num1*100) / 10;
		Image2->Canvas->Rectangle(0, 0, Image2->Width,
					Image2->Height);
		RBlock = Rect(num2*TWidth, 0, (num2+1)*TWidth, THeight);
		RDest = Rect(l+TWidth, t, l+TWidth*2, t+THeight);
		Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
		RBlock = Rect(num3*TWidth, 0, (num3+1)*TWidth, THeight);
		RDest = Rect(l+TWidth*2, t, l+TWidth*3, t+THeight);
		Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
		RBlock = Rect(10*TWidth, 0, 11*TWidth, THeight);
		RDest = Rect(l, t, l+TWidth, t+THeight);
		Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
	}
}

void TMainForm::DrawTime(int time)
{
	int l = 3, t =5;
	int num1, num2, num3;
	num3 = time % 10;
	num1 = time / 100;
	num2 = (time - num1*100) / 10;
	RBlock = Rect(num2*TWidth, 0, (num2+1)*TWidth, THeight);
	RDest = Rect(Image2->Width-l-TWidth*2, t, Image2->Width-l-TWidth, t+THeight);
	Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
	RBlock = Rect(num3*TWidth, 0, (num3+1)*TWidth, THeight);
	RDest = Rect(Image2->Width-l-TWidth, t,
		Image2->Width-l, t+THeight);
	Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
	RBlock = Rect(num1*TWidth, 0, (num1+1)*TWidth, THeight);
	RDest = Rect(Image2->Width-l-TWidth*3, t,
		Image2->Width-l-TWidth*2, t+THeight);
  	Image2->Canvas->CopyRect(RDest, BTime->Canvas, RBlock);
}

void TMainForm::Judge()
{

	if (!Gamestate)
	{
		FalseDraw();
		Gamestate = false;
		Timestate = false;
	}
	else if (Mopened == BWidth*BHeight - BNum)
	{

		ShowMessage("You Win...");
		WinDraw();
		Gamestate = false;
		Timestate = false;
	}
}
void TMainForm::FalseDraw()
{
	for (int i = 0; i < BWidth; i++)
	{
		for (int j = 0; j<BHeight; j++)
		{
			//绘制界面上所有未挖开的雷区
			if ((Mine[i*BWidth + j] == 1) && (State[i*BWidth + j] == Unopen))
			{
				RBlock = Rect(3*Block, 0, 4*Block, Block);
				RDest = Rect(i*Block+left, j*Block+top,
					(i+1)*Block+left-1, (j+1)*Block+top-1);
				Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
			}
			//绘制界面上所有标记错误的雷区
			if (Mine[i*BWidth +j] !=1 && State[i*BWidth + j] == Flag)
			{
				RBlock = Rect(4*Block, 0, 5*Block, Block);
				RDest = Rect(i*Block+left, j*Block+top,
					(i+1)*Block+left-1, (j+1)*Block+top-1);
				Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
			}
		}
	}
}
void TMainForm::WinDraw()
{
	for (int i = 0; i < BWidth; i++)
	{
		for (int j = 0; j<BHeight; j++)
		{
			//绘制胜利情况下界面上所有未标记的雷区,自动标记上
			if ((Mine[i*BWidth + j] == 1) && (State[i*BWidth + j] == Unopen))
			{
				RBlock = Rect(2*Block, 0, 3*Block, Block);
				RDest = Rect(i*Block+left, j*Block+top,
					(i+1)*Block+left-1, (j+1)*Block+top-1);
				Image1->Canvas->CopyRect(RDest, BBlock->Canvas, RBlock);
			}
		}
	}
}
//---------------------------------------------------------------------------
//自定义成员函数结束
//---------------------------------------------------------------------------

TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
	InitMine();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::MAboutClick(TObject *Sender)
{
	MessageBox(MainForm->Handle,
	"蛮.com  'BCB 2006' 制作于 2007年7月 ", "关于 扫雷",MB_OK);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Image1MouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
	int  ix, iy;

	//游戏操作开始
	if (Gamestate)
	{
		ix = X / Block;
		iy = Y / Block;
		if (Button == mbLeft)
		{
			OpenMine(ix, iy);
		}
		else if (Button == mbRight)
		{
			FlagMine(ix, iy);
			DrawTime(Mtimer);
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::MStartClick(TObject *Sender)
{
	InitMine();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::MQuitClick(TObject *Sender)
{
	exit(0);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Timer1Timer(TObject *Sender)
{
	if (Timestate)
	{
		DrawTime(Mtimer++);
	}
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Image1MouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
	int ix = X / Block;
	int iy = Y / Block;

	//左右键自动挖雷处理
	if (Gamestate && Shift == TShiftState() << ssLeft << ssRight)
	{
		AutoMine(ix, iy);
	}
	if (Button == mbLeft && !Timestate)
		Timestate = true;
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::MJuniorClick(TObject *Sender)
{
	Change(9, 9, 10);
}
void TMainForm::Change(int w, int h, int n)
{

	//游戏等级改变,更改窗体和绘图区属性,重新开始
	BWidth = w;
	BHeight = h;
	BNum = n;
	Width = 160 + (w-9) * Block;
	Height = 260 + (h-9) * Block;
	Image1->Width= 140 + (w-9) * Block;
	Image1->Height= 140 + (h-9) * Block;
	Image2->Width= 140 + (w-9) * Block;
	Image1->Picture->Bitmap->Width= 140 + (w-9) * Block;
	Image1->Picture->Bitmap->Height= 140 + (h-9) * Block;
	Image2->Picture->Bitmap->Width= 140 + (w-9) * Block;
	InitMine();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::MSeniorClick(TObject *Sender)
{
	Change(16, 16, 40);
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::MAdvancedClick(TObject *Sender)
{
	Change(30, 16, 99);
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::MCustomClick(TObject *Sender)
{
	Form2->Show();
	Form2->Edit1->Text = IntToStr(BWidth);
	Form2->Edit2->Text = IntToStr(BHeight);
	Form2->Edit3->Text = IntToStr(BNum);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::MRecordClick(TObject *Sender)
{
	ShowMessage("此功能有待编写,^0^");	
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -