**
扫雷游戏完整教程及代码
**
扫雷是一个非常经典的windows游戏,相信每个人都玩过。我做的这个扫雷基本上继承了windows中扫雷的玩法。通过菜单栏中的新游戏,选择一个游戏难度,即可进入扫雷界面。单击任意一个按钮,就开始了游戏。
具体的规则和逻辑是:
1,鼠标左击则弹开一个雷区,如果是炸弹,则游戏结束,如果不是炸弹且其周围有炸弹,那么将会出现一个数字,指示玩家周围有几个炸弹。如果不是炸弹且周围也没有炸弹,那么则自动弹开周围所有的雷区,并按照上述规则做递归执行。这里用到了递归思想。
2,对一个数字区双击鼠标左击或者同时按下左键和右键时,可以自动为用户检查周围雷区,如果满足条件,则会自动弹开所有周围雷区。其中同时按下左键和右键这个功能,在VB中是没有此类事件的,其难点在于左键和右键的单击事件在vb中是单独的事件过程,而玩家在“同时”按下左键和右键时,其实并不是真正的同时,而是有一定的时间间隔的。这里我用了一个方法完美的完成了这个功能。大概逻辑就是,当用户按下一个左键或者右键时,那么记录此时的时间1,然后在按下另外一个右键或者左键时,记录时间2,如果时间1和时间2的间隔小于一个设定值时,那么认为玩家同时按下了左键和右键,具体代码见下方。
3,鼠标右键可以标记某个雷区,在三种状态中来回切换(不标记,标记,问号)
4,游戏中的排行榜功能,用到了文件操作,这里使用的是txt文本来记录玩家的记录。仅记录打破记录的时间和玩家姓名。
5,扫雷结束有三种方式:玩家主动退出、玩家扫雷失败、玩家扫雷成功。扫雷成功的判断条件是:当用户标记(即红旗)的数量与游戏中隐藏的炸弹数量一致时,判断其所有标记是否正确,如果正确则提示扫雷成功。
6,游戏难度分为4个等级,当时,我这里采用的是function函数,可以自定义任意难度,而不需要修改代码,只需要输入不同的参数即可,非常的方便。
7,第一个必定不是雷,新的扫雷游戏为了提升玩家体验,已经自动适配,让玩家点的第一个格子必定不是炸弹,且一定是一个空格子,因为空格子可以自动弹开周围的雷区。
下面看一下这个游戏的界面:
1,主界面
2,扫雷界面(中等难度)
3,扫雷界面(骨灰级难度)
4,扫雷失败时
5,扫雷成功并打破记录时
6,排行榜界面
下面看一下整个工程结构:
文件目录比较简单,需要注意的是,要在工程所在目录下建立一个image文件夹,用于存放用到的图片。并在工程所在目录同级下建立一个rank.txt文件,用来记录玩家排行榜。当然rank.txt文件不建立也没关系,因为代码中可以自动创建。
Image文件夹中需要准备以下这些图片和图标。这些都可以在网上找到。图标和图片不一定要和我的一样,但是命名必须一样,格式也要一样。图片大小也要差不多大小的。
工程包含两个窗体,如下所示:
接着我们分别来看一下两个窗体中的控件布置:
窗体1(form1)包含了菜单栏、一个frame2(其中包含两个标签和2个文本框),一个frmae1(其中包含一个按钮和一个标签),一个Image1图像,一个timer1
菜单栏设计如下:
Frame1框架中包含:
一个按钮和一个标签。Label3(0)和Command1(0)两个控件数组。控件数组是将其index属性值设置为非空,这里是设置的0,这样可以利用控件数组方便的控制控件的数量和大小位置。
Frame2框架中包含:
两个标签和2个文本框,名称分别是:Label1和Label2,Text1和Text2,分别用于显示游戏进行的时间和排雷的数量。
窗体2中,包含了一个frame1控件,和若干标签,标签名称见下图所示。
下面来看完整的代码:
窗体Form1的代码如下:
Option Explicit
Dim IndexMax% 'command1按钮编号索引
Dim a%() '对应每个command1的属性,-1表示是炸弹,0表示其周围没有炸弹,大于1表示周围有几个炸弹
Dim B$() '对应每个按钮的标记情况,flag表示旗子,""表示未标记," "表示周围没有炸弹且已被点击
Dim rows%, cols% '行数和列数
Dim bs% '炸弹数量(优化:可以将bombnums局部变量取消)
Dim lastGame As Integer '记录最近一次的游戏等级
Dim LoadFlag As Boolean '加载画面过程中的标记
Dim L As Single, r As Single, t As Single '用于控制同时按下鼠标左右键的参数
Dim firstClick As Boolean '标记为,标记是否首次单击
'窗体1加载
Private Sub Form_Load()
Image1.Top = 0
Image1.Left = 0
Image1.Height = 5000
Image1.Width = 5000
Image1.Stretch = True
Me.Icon = LoadPicture(App.Path & "/image/tile.ico")
Timer1.Interval = 1000
Timer1.Enabled = False
Call unloadWindows '调用卸载窗体控件的子程序
ReDim a(1) '初始化数组
ReDim B(1) '初始化数组
End Sub
'卸载窗体按钮
Function unloadWindows()
Dim i%
Image1.Visible = True
Image1.Picture = LoadPicture(App.Path & "/image/background.jpg")
If IndexMax > 1 Then
Frame1.Visible = False
For i = 1 To IndexMax
Unload Command1(i)
Unload Label3(i)
Next i
End If
IndexMax = 0
Frame1.Visible = False
Frame2.Visible = False
Frame1.Left = 200
Command1(0).Visible = False
Label3(0).Visible = False
Form1.Height = 5000
Form1.Width = 5000
Text1 = "0"
Timer1.Enabled = False
Erase a
Erase B
End Function
'开始初级难度游戏
Private Sub game1_Click()
rows = 9 '雷区横向数量
cols = 9 '雷区纵向数量
bs = 12 '炸弹数量
lastGame = 99 '标记
Call unloadWindows '调用卸载窗体控件的子程序(雷区)
Call creatWindow '调用创建窗体控件的子程序(雷区)
End Sub
'开始中级难度游戏
Private Sub game2_Click()
rows = 16
cols = 16
bs = 42
lastGame = 1616
Call unloadWindows
Call creatWindow
End Sub
'开始高级难度游戏
Private Sub game3_Click()
rows = 16
cols = 30
bs = 90
lastGame = 1630
Call unloadWindows
Call creatWindow
End Sub
'开始骨灰级难度游戏
Private Sub game4_Click()
rows = 25
cols = 40
bs = 180
lastGame = 2540
Call unloadWindows
Call creatWindow
End Sub
'创建窗体及按钮(创建雷区)
Function creatWindow()
Dim i%, j%
LoadFlag = True '加载标记位至为真,防止用户在加载过程中单击鼠标
Image1.Picture = LoadPicture("")
Image1.Visible = False
Load Label3(1)
Label3(1).Visible = True
Label3(1).BackColor = &HC0C0C0
Label3(1) = ""
Label3(1).Height = 400
Label3(1).Width = 400
Label3(1).Top = 230
Label3(1).Left = 50
Load Command1(1)
Command1(1).Visible = True
Command1(1).BackColor = RGB(58, 154, 254)
Command1(1).Caption = ""
Command1(1).Height = 400
Command1(1).Width = 400
Command1(1).Top = 150
Command1(<