📄 main.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 + -