姓名: 班级: 学号:
难度:☆☆☆☆
知识点:控件数组 绘图 菜单 文本文件的读写 多模块程序设计 资源文件的使用
1. 题目
“扫雷”是windows下的经典小游戏。如下图所示,一个由M行N列小方格组成的雷区影藏着K颗地雷(M N和K可以事先设置)。用户根据判断确定哪个方格有雷,哪个方格无雷。使用鼠标左键单击无雷方格将其翻开会在该方格内显示一个数字(1~8),该数字表示这个方格周围相邻的8个方格内共有多少克雷。如果左键单击方格内未显示数字,表示方格周围没有雷,程序自动将周围的方格翻起直至遇到周围有雷的方格为止。
在方格内数字的提示下,用户判断某个位置有雷,使用鼠标右键单击将有雷方格标记出来(显示小红旗)
当所有有雷的方格打上了标志,所有无雷的方格都被翻起,表明扫雷成功。如果中途使用左键单击了有雷方格,则被“炸死”,扫雷失败。
功能:
(1)启动程序后,显示初始界面,游戏共有3种预定义的难度级别,分别是初级(9行9列10颗雷),中级(16行16列40颗雷)和高级(30行16列99颗雷),通过“游戏”菜单中的菜单项可以选择不同难度。
使用自定义菜单命令打开自定义对话框,可以自行定义雷区的行数,列数及雷数。
(2)雷区正上方是一个“小脸”图标,不同状态下,小脸显示出微笑,惊讶,痛苦和胜利等表情。任何情况下单击小脸,可以重新开始游戏。
笑脸左边以LED(发光二极管)方式显示了当前雷区中未被标记出来的雷数,右面是游戏进行的秒数。计时是在用户第一次单机雷区的方块时开始的。
(3)是用右键单击一个方格将其标记为有雷(插上小旗)之后,不能再使用左键单击它,但可以再用右键单击。右键再单机一次方格上显示“?”号(表示暂时不确定),再单击第二次,恢复为普通样子。
使用左键可以单机除了标记为有雷之外的所有未翻开的方格(包括标记为“?”号的)
(4)如果一个方格内显示的数字为N(1~8)且其周围已有N个方格被标记为有雷,这时可以同时单击鼠标左键和右键将方格周围所有的其它格子翻开。这样就不必一个一个去单击了。
不过,如果标记为有雷的方格中有标记错的,这是会被“炸死”。 (5)扫雷失败时程序用图标显示所有有雷的位置,并将标记错了的和“炸了的”用和显示。
(6)扫雷成功时,如果没有打破该难度级别的记录,显示“胜利”消息框;如果破了纪录,显示输入框提示输入用户名。
通过“扫雷英雄榜”菜单命令可以显示“扫雷英雄榜”对话框,其中列出了预设的3个难度级别的记录保持者。
2. 框架结构图
流程规划大致上可以分为三个部分,分别为:画面初始、游戏者按下第一个方块和为
非地雷方块时展开。画面初始时,以游戏者最后一次设定的地雷区大小为范围画出地雷区,但此时并未产生地雷。当游戏者按下第一个方块时产生地雷资料并启动定时器,为何在游戏者按下第一个方块才产生地雷资料呢?其主要的用意在于不要让游戏者第一次就踩到地雷,这样在某种程度上可以提高游戏者游玩的气氛。接着就是如何判断按下的方块是非地雷时的处理,这也是整个游戏的技术核心,我们可以通过递归的观念来检查周边的方块是否含有地
雷及是否继续往外翻开。流程规划如图1所示:
图1整体流程规划图
开始(初始化程序) 选择游戏等级 等待按键 左键 是 同时 右键 是 第一次按下 否 如果一个方格内显示的数字与其周围被标记为有雷方格相同,将方格周围所有的其它格子翻开 等待按键 标记小旗或“?”或恢复方格 启动计时器 是否为雷 否 是 游戏结束 否 翻开方格并检查是否标记所有雷 是 游戏胜利是否破纪录 否 结束是否重新开始 是 是 保存成绩 图1整体流程规划图
3. 原程序(注释) 1.模块窗口代码
Option Explicit
'下面类型定义了游戏区中每个格子可能的状态
Enum Board_Status '定义枚举类型 COMMON = 0
FLAG = 1 MARK = 2 DIEBOMB = 3 NOBOMB = 4 BOMB = 5
MARKDOWN = 6 NUM8 = 7 NUM7 = 8 NUM6 = 9 NUM5 = 10 NUM4 = 11 NUM3 = 12 NUM2 = 13 NUM1 = 14 DOWN = 15 End Enum
'下面类型定义了小脸可能的状态
Enum Face_Status '定义枚举类型 SMILEDOWN = 0 COOL = 1 CRY = 2
SURPRISE = 3 SMILE = 4 End Enum
'下面的类型定义了游戏区中一个格子的当前状态
Type TBOMB '自定义类型 isBomb As Boolean '是否为地雷 board As Board_Status '当前状态 End Type
Type TPOINT '自定义类型TPOINT,定义点的坐标 x As Integer y As Integer End Type
Public picBoard(0 To 15) As StdPicture '15种显示内容 Public picnum(0 To 10) As StdPicture '11种数字 Public picFace(0 To 4) As StdPicture '5种表情图片
Public wFace As TPOINT '保存小脸的位置 Public arrBomb() As TBOMB '保存雷区状态 Public bDrawFace As Boolean
Public nFace As Integer
Public nBombs As Integer '地雷总数 Public nLeftBombs As Integer '剩余雷数
Public nRows As Integer, nCols As Integer '雷区的行数和列数
Public nLevel As Integer '难度:1~4(分别对应初级、中级、高级和自定义)
Public nTime As Integer '时间
Public bMark As Boolean
Public nOldRow As Integer, nOldCol As Integer '前一个行数和列数
Public bStarted As Boolean '开始标志
Public bLButton As Boolean, bRButton As Boolean '左右键按下状态 Public uname(0 To 2) As String, uscore(0 To 2) As Integer '英雄榜记录
Sub DrawBoard(col As Integer, ln As Integer, board As Board_Status) '在雷区的指定行列绘制指定的内容
Main.PaintPicture picBoard(board), (col + 1) * 16 - 4, 40 + (ln + 1) * 16, 16, 16 End Sub Sub DrawNum(nnum As Integer, ntype As Integer) '绘制数字,nnum 参数为数字内容;ntype参数:1绘制雷数(左边),2绘制时间(右边) Dim x As Integer, i As Integer Dim strNum, strChr As String
If ntype = 1 Then x = 17
If ntype = 2 Then x = Main.Width / Screen.TwipsPerPixelX - 60 '返回水平(TwipsPerPixelX)度量的对象的每一像素中的缇数。
If nnum < 0 Then
strNum = Format(nnum, \"00\") Else
strNum = Format(nnum, \"000\") End If
For i = 1 To 3
strChr = Mid(strNum, i, 1) If strChr >= \"0\" And strChr <= \"9\" Then '绘制0-9
Main.PaintPicture picnum(Val(strChr)), x, 15, 13, 26
Else '绘制\"-\"
Main.PaintPicture picnum(10), x, 15, 13, 26 End If x = x + 13 Next
End Sub
Sub DrawNineBoard(col As Integer, ln As Integer) Dim i As Integer, j As Integer For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then
If arrBomb(i, j).board = COMMON Then DrawBoard i, j, DOWN If arrBomb(i, j).board = MARK Then DrawBoard i, j, MARKDOWN End If Next Next End Sub
Sub DrawFace(face As Integer) '画脸形
Main.PaintPicture picFace(face), wFace.x, wFace.y, 24, 24 End Sub
Sub GameOver()
Dim i As Integer, j As Integer For i = 1 To nCols
For j = 1 To nRows
If arrBomb(i, j).isBomb And (Not arrBomb(i, j).board = FLAG) Then '是雷没插旗显示雷
arrBomb(i, j).board = BOMB DrawBoard i, j, BOMB End If
If (Not arrBomb(i, j).isBomb) And arrBomb(i, j).board = FLAG Then '不是雷插旗的显示无雷
arrBomb(i, j).board = NOBOMB DrawBoard i, j, NOBOMB End If Next Next
nFace = CRY
DrawFace nFace '画哭脸
Main.Timer.Enabled = False End Sub
Sub OnGameNew() '开始新游戏
Dim i As Integer, j As Integer Dim ln As Integer, col As Integer
Main.Timer.Enabled = False
Select Case (nLevel)
Case 0 '初级 nCols = 9 nRows = 9 nBombs = 10
Case 1 '中级 nCols = 16 nRows = 16 nBombs = 40
Case 2 '高级 nCols = 30 nRows = 16 nBombs = 99 End Select
ReDim arrBomb(0 To nCols, 0 To nRows)
Main.Width = 30 * Screen.TwipsPerPixelX + 16 * Screen.TwipsPerPixelX * nCols
Main.Height = 100 * Screen.TwipsPerPixelY + 13 * Screen.TwipsPerPixelY + 16 * Screen.TwipsPerPixelY * nRows
'返回水平 (TwipsPerPixelX) 或垂直 (TwipsPerPixelY) 度量的对象的每一像素中的缇数。
bLButton = False bRButton = False bStarted = False bDrawFace = False nFace = SMILE nOldCol = 0 nOldRow = 0
nLeftBombs = nBombs
For i = 0 To nCols - 1
For j = 0 To nRows - 1
arrBomb(i, j).isBomb = False arrBomb(i, j).board = COMMON Next Next i = 0
Do While i < nBombs '随机生成nBombs个地雷 col = Int(Rnd * 100) Mod nCols ln = Int(Rnd * 100) Mod nRows
If arrBomb(col, ln).isBomb = False Then
arrBomb(col, ln).isBomb = True '防止重复 i = i + 1 End If Loop
wFace.x = Main.Width / (2 * Screen.TwipsPerPixelX) - 13 wFace.y = 15
nTime = 0
End Sub
Sub Check() '检查是否胜利,并显示胜利消息 Dim WIN As Boolean Dim i, j As Integer
WIN = True
For i = 0 To nCols - 1 For j = 0 To nRows - 1
If arrBomb(i, j).board = COMMON Or arrBomb(i, j).board = MARK Then WIN = False '存在既没插旗又没翻开的格子
If arrBomb(i, j).isBomb = False And arrBomb(i, j).board = FLAG Then WIN = False '插旗的有不是雷 Next Next
If Not WIN Then Exit Sub End If
nFace = COOL DrawFace nFace
Main.Timer.Enabled = False
If nLevel < 3 Then
If uscore(nLevel) > nTime Or uscore(nLevel) = 0 Then '破本难度的记录
uscore(nLevel) = nTime
uname(nLevel) = InputBox(\"胜利了,恭喜你破了本难度的记录!\" & Chr(10) & Chr(13) & \"请留下大名:\扫雷\无名侠\")
If uname(nLevel) = \"\" Then uname(nLevel) = \"匿名\" Else
MsgBox \"胜利了,恭喜你!\扫雷\" 'vbOKOnly + vbInformation End If Else
MsgBox \"胜利了,恭喜你!\扫雷\" End If
End Sub
Sub Kick(col As Integer, ln As Integer) '递归过程,判断一个位置的周围的雷数 Dim sum As Integer
Dim i As Integer, j As Integer
If col < 0 Or ln < 0 Or col >= nCols Or ln >= nRows Then Exit Sub
If arrBomb(col, ln).isBomb = True Then '如果踩上地雷 GameOver
arrBomb(col, ln).board = DIEBOMB DrawBoard col, ln, DIEBOMB Exit Sub End If
sum = 0 i = 0 j = 0
For i = col - 1 To col + 1 '计算周围共有地雷数 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then If arrBomb(i, j).isBomb Then sum = sum + 1
End If End If Next Next
arrBomb(col, ln).board = 15 - sum '记下并显示周围地雷数 DrawBoard col, ln, 15 - sum
If sum = 0 Then '如果周围没有地雷, For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If i >= 0 And j >= 0 And i < nCols And j < nRows Then
If ((Not (i = col And j = ln)) And (arrBomb(i, j).board = COMMON)) Then 未翻操作开的格子进行 Kick i, j End If End If Next Next End If
End Sub
Sub SaveRecord() '保存英雄榜记录 Dim i As Integer Dim v As Variant
v = GetAllSettings(\"main\ If Not IsEmpty(v) Then
DeleteSetting \"main\ '删除现有记录 End If
For i = 0 To 2
SaveSetting \"main\ Next End Sub
2.主窗口代码 Option Explicit
Private Sub mnuAbout_Click() Form4.Show 1, Me End Sub
Private Sub mnu1_Click()
mnu1.Checked = True '显示选中状态
'对 mnu2.Checked = False mnu3.Checked = False mnu4.Checked = False
nCols = 8 nRows = 8 nBombs = 10
nLevel = 0 '初始为初级 OnGameNew Form_Paint End Sub
Private Sub mnuExit_Click() Unload Me End Sub
Private Sub mnu2_Click() mnu1.Checked = False mnu2.Checked = True mnu3.Checked = False mnu4.Checked = False
nCols = 16 nRows = 16 nBombs = 40 nLevel = 1 OnGameNew Form_Paint End Sub
Private Sub mnu3_Click() mnu1.Checked = False mnu2.Checked = False mnu3.Checked = True mnu4.Checked = False
nCols = 30 nRows = 16 nBombs = 99 nLevel = 2 OnGameNew Form_Paint End Sub
Private Sub mnu4_Click()
'中级 '高级 Form2.Show 1, Me End Sub
Private Sub mnuStart_Click() OnGameNew Form_Paint End Sub
Private Sub mnuhero_Click() '显示排行榜对话框 Form3.Show 1, Me End Sub
Private Sub Form_Load() Dim i As Integer
For i = 0 To 15
Set picBoard(i) = LoadResPicture(100 + i, 0) Next
For i = 0 To 10
Set picnum(i) = LoadResPicture(120 + i, 0) Next
For i = 0 To 4
Set picFace(i) = LoadResPicture(140 + i, 0) Next
ReDim arrBomb(0 To 9, 0 To 9) 列)
Call OnGameNew Call Form_Paint Call ReadRecord End Sub
Public Sub Form_Paint()
Dim i As Integer, j As Integer Dim w As Long, h As Long
Dim oldForecolor, oldFillcolor As ColorConstants
w = ScaleWidth - 1 部坐标的宽度和高度。
'加载雷区图片 '加载数字图片 '加载脸形图片 '默认为初级(10行10'ScaleWidth,ScaleHeight是控件内 h = ScaleHeight - 1
oldForecolor = ForeColor oldFillcolor = FillColor
FillColor = RGB(198, 195, 198) 'RGB函数返回一个颜色 FillColor指填充色
ForeColor = RGB(198, 195, 198)
FillStyle = 0 '填充样式
Line (0, 0)-(w, 550), , BF 充矩形
Line (0, 550)-(120, (h - 120)), , BF Line (0, (h - 120))-(w, h), , BF
Line ((w - 110), 550)-(w, (h - 120)), , BF
ForeColor = RGB(255, 255, 255) DrawWidth = 1 小(单位为像素)
Line (w - 1, 0)-(0, 0) Line (0, 0)-(0, h) Line (w - 2, 1)-(1, 1) Line (1, 1)-(1, h - 1) Line (w - 3, 2)-(2, 2) Line (2, 2)-(2, h - 2)
Line (w - 9, 10)-(w - 9, 45) Line (w - 9, 45)-(9, 45)
Line (w - 10, 11)-(w - 10, 44) Line (w - 10, 44)-(10, 44) Line (w - 9, 53)-(w - 9, h - 9) Line (w - 9, h - 9)-(9, h - 9)
Line (w - 10, 54)-(w - 10, h - 10) Line (w - 10, h - 10)-(10, h - 10) Line (w - 11, 55)-(w - 11, h - 11) Line (w - 11, h - 11)-(11, h - 11)
ForeColor = RGB(132, 130, 132) DrawWidth = 1 Line (w, 1)-(w, h) Line (w, h)-(1, h)
Line (w - 1, 1)-(w - 1, h - 1) Line (w - 1, h - 1)-(2, h - 1) Line (w - 2, 2)-(w - 2, h - 2)
'有B画矩形 有F用边框颜色填 '文字或边框颜色
'边框宽度及点的大 '画直线 Line (w - 2, h - 2)-(3, h - 2) Line (w - 10, 9)-(9, 9) Line (9, 9)-(9, 45)
Line (w - 11, 10)-(10, 10) Line (10, 10)-(10, 44) Line (w - 10, 52)-(9, 52) Line (9, 52)-(9, h - 9) Line (w - 11, 53)-(10, 53) Line (10, 53)-(10, h - 10) Line (w - 12, 54)-(11, 54) Line (11, 54)-(11, h - 11)
FillColor = RGB(255, 255, 255) ForeColor = RGB(132, 130, 132)
Line (wFace.x - 1, wFace.y - 1)-(wFace.x + 25, wFace.y + 25)
ForeColor = oldForecolor '形成雷数显示LED FillColor = oldFillcolor '形成时间显示LED
DrawNum nLeftBombs, 1 DrawNum nTime, 2
DrawFace nFace
For i = 0 To nCols - 1 For j = 0 To nRows - 1
DrawBoard i, j, arrBomb(i, j).board '形成所有格子 Next Next
End Sub
Private Sub ReadRecord() '读入英雄榜记录 Dim i As Integer Dim v As Variant Dim s As String
v = GetAllSettings(\"main\ 'GetAllSettings 返回 Variant,其内容为字符串的二维数组,该二维数组包含指定区域中的所有注册表项设置及其对应值。
If IsEmpty(v) Then 'IsEmpty 用于判断一个变量是否已初始化
For i = 0 To 2
uname(i) = \"无名侠\" uscore(i) = 0 Next Exit Sub End If
For i = 0 To 2
If i >= LBound(v, 1) And i <= UBound(v, 1) Then uname(i) = v(i, 0) uscore(i) = v(i, 1) Else
uname(i) = \"无名侠\" uscore(i) = 0 End If Next End Sub
Private Sub Timer_Timer() '显示游戏时间 If nTime < 999 Then nTime = nTime + 1 DrawNum nTime, 2 End If End Sub
Private Sub Form_Unload(Cancel As Integer) Call SaveRecord End Sub
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single) Dim ln As Integer, col As Integer
If Button = 1 Then '如果点击的是鼠标左键
If x >= wFace.x And y >= wFace.y And x <= wFace.x + 24 And y <= wFace.y + 24 Then '如果在小脸上点击 bLButton = True bDrawFace = True
DrawFace SMILEDOWN Exit Sub End If
If nFace = CRY Or nFace = COOL Then Exit Sub '如果已炸死或胜利,则不反应
bLButton = True
DrawFace SURPRISE
If x <= 12 Or x >= 12 + 16 * nCols Or y <= 55 Or y >= 55 + 16 * nRows Then Exit Sub '如果点击在雷区外,则不反应
ln = Int((y - 40) / 16) - 1 '划分按钮
col = Int((x + 4) / 16) - 1
nOldRow = ln nOldCol = col '记录鼠标按下的按钮
If bRButton Then
DrawNineBoard col, ln '两键都按下翻开周围九个按钮 End If
If arrBomb(col, ln).board = MARK Then '如果点击?号,显示按下的?号 DrawBoard col, ln, MARKDOWN End If
If arrBomb(col, ln).board = COMMON Then '中果点击空白,显示按下的空白 DrawBoard col, ln, DOWN End If
ElseIf Button = 2 Then '按下鼠标右键时
If (nFace = CRY Or nFace = COOL) Then Exit Sub '如果已炸死或胜利,则不反应
If x < 12 Or x >= 12 + 16 * nCols Or y < 55 Or y >= 55 + 16 * nRows Then Exit Sub '如果点击在雷区外,则不反应 bRButton = True
ln = Int((y - 40) / 16) - 1 '划分按钮 col = Int((x + 4) / 16) - 1
If bLButton Then
DrawNineBoard col, ln '两键都按下翻开周围九个按钮
End If
If arrBomb(col, ln).board = COMMON Then arrBomb(col, ln).board = FLAG DrawBoard col, ln, FLAG nLeftBombs = nLeftBombs - 1
DrawNum nLeftBombs, 1
ElseIf arrBomb(col, ln).board = FLAG Then arrBomb(col, ln).board = MARK DrawBoard col, ln, MARK nLeftBombs = nLeftBombs + 1 DrawNum nLeftBombs, 1 Else
If arrBomb(col, ln).board = MARK Then arrBomb(col, ln).board = COMMON DrawBoard col, ln, COMMON End If End If End If End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single) Dim ln As Integer, col As Integer Dim i As Integer, j As Integer
If ((Not bLButton) And (Not bRButton)) Then '左右键都未按下移动鼠标不反应 Exit Sub End If
If bDrawFace Then
If x >= wFace.x And y >= wFace.y And x <= wFace.x + 24 And y <= wFace.y + 24 Then '鼠标在脸形上时显示Smiledown DrawFace SMILEDOWN Else
DrawFace nFace '鼠标移开恢复原来脸型 Exit Sub End If End If
If x <= 12 Or x >= 12 + 16 * nCols Or y <= 55 Or y >= 55 + 16 * nRows Then '鼠标移到雷区外翻开的按钮全部恢复 For i = nOldCol - 1 To nOldCol + 1 '(原因:两键都按下时翻开周围九个按钮需要全部恢复) For j = nOldRow - 1 To nOldRow + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then DrawBoard i, j, arrBomb(i, j).board End If Next
Next
nOldRow = 0 nOldCol = 0 Exit Sub End If
ln = Int((y - 40) / 16) - 1
col = Int((x + 4) / 16) - 1 '划分按钮
If (ln = nOldRow And col = nOldCol) Then Exit Sub '在同一按钮上移动鼠标不反应
DrawBoard nOldCol, nOldRow, arrBomb(nOldCol, nOldRow).board '恢复上一按钮
If bLButton And bRButton Then '两键都按下移动鼠标时
For i = nOldCol - 1 To nOldCol + 1
For j = nOldRow - 1 To nOldRow + 1
If Not ((i < 0) Or (j < 0) Or (i >= nCols) Or (j >= nRows)) Then '恢复翻开的九个按钮
DrawBoard i, j, arrBomb(i, j).board End If Next Next
If (Not (col < 0) Or (ln < 0) Or (col >= nCols) Or (ln >= nRows)) Then '翻开周围九个按钮
DrawNineBoard col, ln End If
ElseIf bLButton Then
If arrBomb(col, ln).board = COMMON Then DrawBoard col, ln, DOWN '只按左键移动鼠标翻开鼠标所在的按钮
If arrBomb(col, ln).board = MARK Then DrawBoard col, ln, MARKDOWN End If
nOldRow = ln nOldCol = col End Sub
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
Dim ln As Integer, col As Integer Dim i As Integer, j As Integer
Dim sumBomb As Integer, sumFlag As Integer
If Button = 1 Then DrawFace nFace
If x >= wFace.x And y >= wFace.y And x <= wFace.x + 24 And y <= wFace.y + 24 And bDrawFace Then '在脸形上重新开始游戏 OnGameNew Form_Paint Exit Sub End If
If bDrawFace Then '鼠标移开不在脸上 bDrawFace = False bLButton = False Exit Sub End If
bDrawFace = False
If ((x <= 12) Or (x >= 12 + 16 * nCols) Or (y <= 55) Or (y >= 55 + 16 * nRows)) Then '鼠标移到雷区外
bLButton = False Exit Sub End If
If nFace = CRY Or nFace = COOL Then Exit Sub '如果已炸死或胜利,则不反应
ln = Int((y - 40) / 16) - 1 col = Int((x + 4) / 16) - 1
If Not bStarted Then '第一次翻开一个按钮后开始计时 bStarted = True
Timer.Enabled = True End If
If bRButton Then '两件都按下时
sumBomb = 15 - arrBomb(col, ln).board '单击的方格周围雷的个数 sumFlag = 0 '已经标记的雷的个数 For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then If arrBomb(i, j).board = FLAG Then sumFlag = sumFlag + 1 End If End If
Next Next
If sumBomb = sumFlag Then '如果一个方格内显示的数字与其周围被标记为有雷方格相同,将方格周围所有的其它格子翻开 For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then
If arrBomb(i, j).board = COMMON Or arrBomb(i, j).board = MARK Then
Kick i, j End If End If Next Next End If
For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then DrawBoard i, j, arrBomb(i, j).board End If Next Next
ElseIf (((arrBomb(col, ln).board = COMMON) Or (arrBomb(col, ln).board = MARK)) And bLButton) Then '按下左键时,松开鼠标时翻开方格 Kick col, ln End If
bLButton = False
If nFace <> CRY Then Check '检查是否胜利,并显示胜利消息
ElseIf Button = 2 Then
If nFace = CRY Or nFace = COOL Then Exit Sub '如果已炸死或胜利,则不反应
bRButton = False ' bLButton = False
If x < 12 Or x >= 12 + 16 * nCols Or y < 55 Or y >= 55 + 16 * nRows Then Exit Sub '鼠标移到雷区外
ln = Int((y - 40) / 16) - 1 '划分方格 col = Int((x + 4) / 16) - 1
If bLButton Then '两件都按下时
sumBomb = 15 - arrBomb(col, ln).board '单击的方格周围雷的个数 sumFlag = 0 '已经标记的雷的个数 For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then If arrBomb(i, j).board = FLAG Then sumFlag = sumFlag + 1 End If End If Next Next
If sumBomb = sumFlag Then '如果一个方格内显示的数字与其周围被标记为有雷方格相同,将方格周围所有的其它格子翻开 For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then
If arrBomb(i, j).board = COMMON Or arrBomb(i, j).board = MARK Then
Kick i, j End If End If Next Next End If
For i = col - 1 To col + 1 For j = ln - 1 To ln + 1
If Not (i < 0 Or j < 0 Or i >= nCols Or j >= nRows) Then DrawBoard i, j, arrBomb(i, j).board End If Next Next Else End If
If nFace <> CRY Then Check '检查是否胜利,并显示胜利消息 End If End Sub
3.自定义窗口代码
Private Sub Command1_Click() Main.mnu1.Checked = False Main.mnu2.Checked = False Main.mnu3.Checked = False Main.mnu4.Checked = True
nRows = Val(Text1.Text)
nCols = Val(Text2.Text) nBombs = Val(Text3.Text)
nLevel = 3 OnGameNew Main.Form_Paint Unload Me End Sub
Private Sub Command2_Click() Unload Me End Sub
Private Sub Form_Load() Text1.Text = 20 Text2.Text = 20 Text3.Text = 20 End Sub
4。英雄榜窗口
Private Sub Command1_Click() Unload Me End Sub
Private Sub Command2_Click() uname(0) = \"无名侠\" uname(1) = \"无名侠\" uname(2) = \"无名侠\" uscore(0) = 0 uscore(1) = 0 uscore(2) = 0 Call SaveRecord
lbln1.Caption = uname(0) lbln2.Caption = uname(1) lbln3.Caption = uname(2) lblt1.Caption = uscore(0) lblt2.Caption = uscore(1) lblt3.Caption = uscore(2) End Sub
Private Sub Form_Load()
lbln1.Caption = uname(0) lbln2.Caption = uname(1) lbln3.Caption = uname(2) lblt1.Caption = uscore(0) lblt2.Caption = uscore(1)
lblt3.Caption = uscore(2) End Sub
4. 界面(测试)
(1)主页面 (2)自定义界面
(3)扫雷英雄榜界面 (4)关于扫雷界面
(5)菜单
测试界面
5. 困难与解决
1. GetAllSettings 函数
GetAllSettings 函数 从 Windows 注册表中返回应用程序项目的所有项设置及其相应值(开始是由 SaveSetting 产生)。语法GetAllSettings(appname, section)GetAllSettings 函数的语法具有下列命名参数:部分描述appname必要。字符串表达式,包含应用程序或工程的名称,并要求这些应用程序或工程有注册表项设置section必要。字符串表达式,包含区域名称,并要求该区域有注册表项设置。GetAllSettings 返回 Variant,其内容为字符串的二维数组,该二维数组包含指定区域中的所有注册表项设置及其对应值。说明如果 appname 或 section 不存在,则 GetAllSettings 返回未初始化的 Variant
2. DeleteSetting 语句
DeleteSetting 语句 在 Windows 注册表中,从应用程序项目里删除区域或注册表项设置。语法 DeleteSetting appname, section[, key]DeleteSetting 语句的语法具有下列命名参数:部分描述appname必需的。字符串表达式,包含应用程序或工程的名称,区域或注册表项用于这些应用程序或工程。section必要。字符串表达式,包含要删除注册表项设置的区域名称。如果只有 appname 和 section,则将指定的区域连同所有有关的注册表项设置都删除。key可选。字符串表达式,包含要删除的注册表项设置。说明如果提供了所有参数,则删除指定的注册表项设置。如果试图使用不存在的区域或注册表项设置上的 DeleteSetting 语句,则发生一个运行时错误 3. SaveSetting 语句
SaveSetting 语句在 Windows 注册表中保存或建立应用程序项目。语法SaveSetting appname, section, key, settingSaveSetting 语句的语法具有下列命名参数部分描述appname 必要。字符串表达式,包含应用程序或工程的名称,对这些应用程序或工程使用设置;section 必要。字符串表达式,包含区域名称,在该区域保存注册表项设置;key 必要。字符串表达式,包含将要保存的注册表项设置的名称;setting 必要。表达式,包含 key 的设置值。说明如果无论如何也不能保存注册表项设置,则将导致错误发生。
3. IsEmpty()函数
因篇幅问题不能全部显示,请点此查看更多更全内容