📄 unit_main.pas
字号:
randx,randy:integer;
i,j:integer;
i_bombCount:integer;
tempGridArray:TGridArray ;
//在生成数字的过程中使用
LargeUpGridArray:array[0..g_MaxCol+1 ,0..g_MaxRow+1 ] of integer;
begin
tempGridArray .LocalTotalCols :=s_DownGridArray .LocalTotalCols ;
tempGridArray .LocalTotalRows :=s_DownGridArray .LocalTotalRows ;
//如果是重新开局的游戏,则直接将上次的雷区的情况赋值给新的雷区信息。
if isGameofRestart then
for I := 1 to s_DownGridArray .LocalTotalCols do
for j:= 1 to s_DownGridArray .LocalTotalRows do
begin
//声明:重新开局后,不能保证鼠标的第一次按键不是雷,原因不言而喻
s_DownGridArray .Grid [i][j] :=LastDownGridArray.grid[i][j];
//该退出了.
exit;
end;
//如果不是重新开局,则按原顺序执行。。。
for I := 1 to s_DownGridArray .LocalTotalCols do
for j:= 1 to s_DownGridArray .LocalTotalRows do
begin
s_DownGridArray .Grid [i][j] :=0;
tempGridArray .Grid [i][j]:=0;
end;
//
i_bombCount :=BombCount ;
randomize; //播随机种子
while i_BombCount <> 0 do
//严格意义上讲.这里需要有一个变量来控制 While 循环的次数,以免死循环,有些格子就是
//得不到,但是在这里,由于雷数毕竟不是很多,所以,就没有考虑..
begin
randx:=random(s_DownGridArray .LocalTotalCols )+1;
randy:=random(s_DownGridArray .LocalTotalRows )+1;
if (s_DownGridArray .Grid [randx][randy]=0) //没有被标过雷
and (random(2)=1) //随机的几率
and (not((randx=localx )and (randy =localy ))) //确保当前按下的那个方块不会是雷
then
begin
s_DownGridArray .Grid [randx][randy]:=10;
i_BombCount :=i_BombCount -1;
end;
end;
for i := 0 to s_DownGridArray .LocalTotalCols+1 do
for j:= 0 to s_DownGridArray .LocalTotalRows+1 do
LargeUpGridArray [i][j]:=0;
for I := 1 to s_DownGridArray .LocalTotalCols do
for j:= 1 to s_DownGridArray .LocalTotalRows do
LargeUpGridArray [i][j]:=s_DownGridArray .grid [i][j];
for i:= 1 to s_DownGridArray .LocalTotalCols do
for j:= 1 to s_DownGridArray .LocalTotalRows do
if s_DownGridArray .grid[i][j]<> 10 then
tempGridArray .grid[i][j]:= LargeUpGridArray[i-1][j-1]
+ LargeUpGridArray[i][j-1]
+ LargeUpGridArray[i+1][j-1]
+ LargeUpGridArray[i-1][j]
+ LargeUpGridArray[i+1][j]
+ LargeUpGridArray[i-1][j+1]
+ LargeUpGridArray[i][j+1]
+ LargeUpGridArray[i+1][j+1];
for I := 1 to s_DownGridArray .LocalTotalCols do
for j:= 1 to s_DownGridArray .LocalTotalRows do
s_DownGridArray .grid [i][j] :=LargeUpGridArray [i][j];
//得到DownGridArray中除了雷以外的数字区域.(0~8)
for i:= 1 to s_DownGridArray .LocalTotalCols do
for j:= 1 to s_DownGridArray .LocalTotalRows do
begin
// "-10" 是转换到0~8 的算法.
s_DownGridArray .grid[i][j]:=s_DownGridArray .grid[i][j]+ (tempGridArray .grid[i][j] div 10);
LastDownGridArray.grid[i][j]:=s_DownGridArray .grid[i][j];
end;
end;
{
isColorForce 是用来判断是否是一定要重新画.在改变"颜色"菜单的内容时才会时 True,其余的都是 False
}
procedure TFrm_Main.DrawBackGround(const d_UpGridArray:TGridArray ; const isColorForce:boolean);
var
i,j:integer;
procedure Drawimage(const argCol,argRow:integer;argimage:integer);
var
num:integer;
comImage:TImage;
begin
//考虑颜色选项的状态
if not isHaveColor then
begin
argimage := argimage +100;
comImage :=Image_gray_block
end else
comImage :=Image_Color_block ;
case argimage of
111,11 :num :=1 ; //没有被按下方块
112,12 :num :=16 ; //被展开的没有数字的方块
113,13 :num :=16 ;
121,21 :num :=15 ; //数字-1
122,22 :num :=14 ; //数字-2
123,23 :num :=13 ; //数字-3
124,24 :num :=12 ; //数字-4
125,25 :num :=11 ; //数字-5
126,26 :num :=10 ; //数字-6
127,27 :num :=9 ; //数字-7
128,28 :num :=8 ; //数字-8
131,31 :num :=2 ; //标有旗帜的方块
132,32 :num :=3; //没有被按下的标有问好的方块
133,33 :num :=7 ; //被按下的标有问好的方块
141,41 :num :=6 ; //显示出来的雷
142,42 :num :=4 ; //被炸开了的雷
143,43 :num :=5 ; //因标错了而炸开的雷
else exit;
end;
Image_BackGround .Canvas .CopyRect(rect((argCol -1)*g_BlockWidth ,
(argRow -1)*g_BlockHeight ,argCol*g_BlockWidth ,argRow *g_BlockHeight ),
comImage .Canvas ,rect(0,(num -1) * g_BlockHeight ,g_BlockWidth ,num * g_BlockHeight));
end;
begin
for i := 1 to UpGridArray .LocalTotalCols do
for j := 1 to UpGridArray .LocalTotalRows do
//如果有不同显示的雷区或是强行要重画的情况下需要重画数字区域
if (LastUpGridArray .Grid [i][j] <> d_UpGridArray .Grid [i][j]) or isColorForce then
begin
drawimage(i,j,d_UpGridArray.grid[i][j]);
// LastUpGridArray 供可能发生的"重新开始本局"事件时用到.
LastUpGridArray .Grid [i][j] := d_UpGridArray .Grid[i][j];
end;
end;
procedure TFrm_Main.DrawHead(const Count:integer;d_Dir:TDisplayDir );
var
d_i:integer;
d_Count:integer;
BombCountArr:array[1..3] of integer;
comimage:Timage;
num:integer;
begin
if Count >= 0 then
d_Count :=Count
else
d_Count :=abs(Count);
if Count >999 then
d_Count :=999;
for d_i:=3 downto 1 do
begin
BombCountArr [d_i]:=d_Count mod 10;
d_Count:=d_Count div 10
end;
if Count < 0 then
BombCountArr [1]:= -1;
for d_i:=1 to 3 do
begin
if not isHaveColor then
begin
BombCountArr [d_i] :=BombCountArr [d_i]+100;
comimage := image_gray_num;
end else
comimage := Image_Color_Num;
case BombCountArr [d_i] of
-1,99:num:=1 ; //数字- 负号
0,100:num:=12 ; //数字- 0 (以下是 1-9)
1,101:num:=11 ;
2,102:num:=10 ;
3,103:num:=9 ;
4,104:num:=8 ;
5,105:num:=7 ;
6,106:num:=6 ;
7,107:num:=5 ;
8,108:num:=4 ;
9,109:num:=3 ;
else exit;
end;
if not isHaveColor then
BombCountArr [d_i] :=BombCountArr [d_i] - 100;
case d_Dir of
d_left:
Image_Dis_BombCount .Canvas .CopyRect(rect((d_i-1)*g_NumWidth ,
0 ,d_i*g_NumWidth ,g_NumHeight ),comimage.Canvas ,
rect(0,(num-1)*g_NumHeight ,g_NumWidth ,num * g_NumHeight ));
d_right:
Image_Dis_Time .Canvas .CopyRect (rect((d_i-1)*g_NumWidth ,
0,d_i*g_NumWidth ,g_NumHeight ),comimage.Canvas ,
rect(0,(num-1)* g_NumHeight ,g_NumWidth ,num * g_NumHeight ));
else exit;
end;
end
end;
{
重点是四连通算法的实现..
}
procedure SeekBlackBlock(s_DownGridArray:TGridArray;var s_UpGridArray:TGridArray;s_Col,s_Row:integer);
var
HeadBlock,myBlock,newBlock:BlockPointer ;
i,j:integer;
s_tempGridArray:TGridArray ;
PointerOutX,PointerOutY:integer;
//初始化指针连表,带头结点
procedure initPointer();
var
i_i,i_j:integer;
begin
new(myBlock);
myBlock ^.BlockX :=0;
myBlock ^.BlockY :=0;
myBlock ^.preBlock :=nil;
myBlock ^.nextBlock :=nil;
HeadBlock :=myBlock ;
for i_i := 1 to s_DownGridArray .LocalTotalCols do
for i_j:= 1 to s_DownGridArray .LocalTotalRows do
s_tempGridArray .Grid [i_i][i_j]:=0;
end;
//入栈操作
procedure push(h_BlockX,h_BlockY:integer);
begin
new(newBlock);
newBlock ^.BlockX :=h_BlockX ;
newBlock ^.BlockY :=h_BlockY ;
newBlock ^.preBlock :=myBlock ;
newBlock ^.nextBlock :=nil;
myBlock ^.nextBlock :=newBlock ;
myBlock :=myBlock ^.nextBlock ;
end;
//出栈操作
procedure pop(var p_BlockX,p_BlockY:integer);
begin
p_BlockX :=myblock ^.BlockX ;
p_BlockY :=myBlock ^.BlockY ;
myBlock :=myBlock ^.preBlock ;
Dispose (myBlock ^.nextBlock );
myBlock ^.nextBlock :=nil;
end;
//只要处理部分
procedure ChangeUpGridArray();
var
c_i,c_j:integer;
begin
for c_i:= -1 to 1 do
for c_j:= -1 to 1 do
//判断越界
if ((PointerOutX +c_i )>=1 ) and ((PointerOutX +c_i) <= s_DownGridArray .LocalTotalCols )
and ((PointerOutY +c_j)>=1) and ((PointerOutY +c_j)<= s_DownGridArray .LocalTotalRows) then
// 判断在DownGridArray中不是雷的块将它显示出来
if (s_DownGridArray .grid[PointerOutX +c_i ][PointerOutY + c_j] <> 10)
and ((s_UpGridArray .grid[PointerOutX +c_i][PointerOutY +c_j] =11)
or (s_UpGridArray .grid[PointerOutX +c_i][PointerOutY +c_j] =13)
or (s_UpGridArray .grid[PointerOutX +c_i][PointerOutY +c_j] =33)
or (s_UpGridArray .grid[PointerOutX +c_i ][PointerOutY +c_j] = 32)) then
begin
// 判断条件是用来处理DownGridArray 中 "0" 与UpGridArray 中 "12"的关系
if s_DownGridArray .grid[PointerOutX +c_i ][PointerOutY + c_j] = 0 then
s_UpGridArray .grid[PointerOutX +c_i ][PointerOutY +c_j]:= 12
else
begin
//20 为DownGridArray 中数字与 UpGridArray 中数字的差量
s_UpGridArray .grid[PointerOutX +c_i ][PointerOutY +c_j]:=
s_DownGridArray .grid[PointerOutX +c_i ][PointerOutY + c_j]+ 20;
end;
BlockOpenCount :=BlockOpenCount +1;
end;
end;
begin
initPointer ;
push(s_Col ,s_Row );
while HeadBlock ^.nextBlock <> nil do
begin
pop(PointerOutX ,PointerOutY );
ChangeUpGridArray ;
for i:=-1 to 1 do
for j:= -1 to 1 do
begin
if not( (i=0 ) and (j= 0)) then
if ((PointerOutX +i )>=1 ) and ((PointerOutX +i) <= s_DownGridArray .LocalTotalCols )
and ((PointerOutY +j)>=1) and ((PointerOutY +j)<= s_DownGridArray .LocalTotalRows) then
if (s_tempGridArray .Grid [PointerOutX +i][PointerOutY +j] = 0)
and (s_DownGridArray .grid[PointerOutX +i][PointerOutY +j] = 0) then
begin
s_tempGridArray .Grid [PointerOutX +i][PointerOutY +j] := 1;
push(PointerOutX +i,PointerOutY +j);
end;
end;
end;
end;
procedure TFrm_Main.GameWin(w_DownGridArray:TGridArray ;var w_UpGridArray:TGridArray);
var
w_i,w_j:integer;
New_Name:string;
begin
Timer_Display .Enabled :=False;
//将没有展开的方块标为雷,即插上红旗.
for w_i:= 1 to w_DownGridArray .LocalTotalCols do
for w_j:= 1 to w_DownGridArray .LocalTotalRows do
if (w_UpGridArray .grid[w_i][w_j]=11) or (w_UpGridArray .grid[w_i][w_j]=32) then
w_UpGridArray .grid[w_i][w_j] := 31;
if isHaveSound then
sndPlaySound(pchar(comdir+g_ResourceName +g_Sound_GameWin),SND_ASYNC );
DrawBackGround(w_UpGridArray,false);
DrawHead(0,d_left );
ChgSpbtnGlyph(f_glass);
//打破记录并且级别不是自定义级别,则需要显示打破记录,输入大名的对话框
if (TotalTime < LocalScore) and (UserLevel <> v_UserDefine) then
begin
Application.CreateForm(TFrm_HeroName , Frm_HeroName );
Frm_HeroName .showmodal;
New_Name :=Unit_HeroName.New_Name;
Unit_Hero.InputScore(UserLevel,TotalTime ,New_Name);
Application.CreateForm(TFrm_Hero, Frm_Hero);
Frm_Hero.ShowModal ;
end;
isGameOver :=true;
isGameWin :=true;
//屏蔽 暂停 菜单
Menu_Pause_Resume.Enabled :=false;
GameStatus :=s_win;
ChangeStatusBar(UserLevel ,UserTotalCols,UserTotalRows, UserBombCount,GameStatus,LocalScore,LanguageType);
end;
procedure TFrm_Main.GameLost(l_DownGridArray:TGridArray ;var l_UpGridArray:TGridArray;l_Col,l_Row:TOverColAndRow);
var
l_i,l_j:integer;
begin
Timer_Display .Enabled :=False;
if isHaveSound then
sndPlaySound(pchar(comdir+g_ResourceName +g_Sound_GameLost),SND_ASYNC );
//根据传进来的数组的值将那些是雷而没有标的块用42-爆炸的雷表示
for l_i:=1 to 8 do
if l_Col [l_i] <> 0 then
begin
l_UpGridArray .grid[l_Col [l_i]][l_Row [l_i]] := 42;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -