vb.net使用GDI+实现扫雷小游戏
程序员文章站
2022-04-07 13:56:49
...
先说一下扫雷的规则:左键点开,右键用旗子标记(取消标记),一个方块上的数字代表周围九个格里有几颗雷! 比如,1,周围九个格里只有一颗雷,2 周围九个格里就有两颗雷,以此类推。通过单击即可挖开方块。 如果挖开的是地雷,则您输掉游戏。 如果方块上出现数字,则表示在其周围的八个方块*有多少颗地雷。
代码质量不是很好,懒得修改了,下面是代码
'Option Strict Off '关闭严格检查变量转换
Imports System.Media
Public Class 扫雷
'基于坐标系统
Dim MySpaceNumbers As Integer '空的位置
Dim one As Integer
Dim cubes(0, 0) As cube '定义二维数组
Dim FirstClick As Boolean = True
Dim tick As Long
Public Sub CubeOnMouseUp(sender As Object, e As MouseEventArgs) '如果点击的是
If e IsNot Nothing AndAlso e.Button = MouseButtons.Right Then '如果是第一次点击方块而且是用右击
If CType(sender, cube).state = cube.CubeStates.flag Then '如果说
Play_Music(New SoundPlayer(My.Resources.拔旗))
CType(sender, cube).state = cube.CubeStates.unClicked
ElseIf CType(sender, cube).state = cube.CubeStates.unClicked Then
CType(sender, cube).state = cube.CubeStates.flag
Play_Music(New SoundPlayer(My.Resources.插旗))
End If
ElseIf CType(sender, cube).state <> cube.CubeStates.flag And CType(sender, cube).state <> cube.CubeStates.space Then '如果没有旗子插上的话就会
If e IsNot Nothing Then '这个e是用户点击的时候e是不是nothing
'如果仅作递归用,就是nothing传值
If FirstClick OrElse My.Computer.Clock.TickCount - tick < 5000 Then
kill = kill + 1
Select Case kill '显示连杀的声音
Case 1
If FirstClick = True Then
Play_Music(New SoundPlayer(My.Resources.第一滴血))
tick = My.Computer.Clock.TickCount
End If
Case 2
Play_Music(New SoundPlayer(My.Resources.双杀))
Case 3
Play_Music(New SoundPlayer(My.Resources.三杀))
Case 4
Play_Music(New SoundPlayer(My.Resources.四杀))
Case 5
Play_Music(New SoundPlayer(My.Resources.五杀))
Case 6
Play_Music(New SoundPlayer(My.Resources.六杀))
Case 7
Play_Music(New SoundPlayer(My.Resources.接近神了))
Case 8
Play_Music(New SoundPlayer(My.Resources.超神1))
Case 9
Play_Music(New SoundPlayer(My.Resources.无人可挡))
Case 10
Play_Music(New SoundPlayer(My.Resources.大杀特杀))
End Select
Else
If kill > 1 Then '如果空格的扫除小于5秒就会shut down
Play_Music(New SoundPlayer(My.Resources.终结))
End If
kill = 0
tick = My.Computer.Clock.TickCount
End If
tick = My.Computer.Clock.TickCount
End If
'Play_Music("排雷成功")
Dim i As Integer = CType(sender, cube).x
Dim j As Integer = CType(sender, cube).y 'ij是代表点击了哪个方块
If CType(sender, cube).state = cube.CubeStates.space Then '如果当前方块是空的
showCubeNumber(sender) '就显示它的周围雷的个数
End If
If CType(sender, cube).LandMine = True Then '
If e IsNot Nothing Then ''说明是人点到了地雷
CType(sender, cube).state = cube.CubeStates.bomp
CType(sender, cube).ForeColor = Color.Red
Play_Music(New SoundPlayer(My.Resources.你已被击杀))
ShowAllBompAndAllCubeDisabeled()
MessageBox.Show("BOMP! " & vbCrLf & "GAME OVER!")
End If 'GAME OVER!
Else '如果触发到了没有地雷的方块
CType(sender, cube).state = cube.CubeStates.space '状态从未点到无雷.出现空白白色
If FindBompNumber(FindNearby(sender)) <> 0 Then
showCubeNumber(cubes(i, j)) '如果这个方块的周围有雷'就显示数字'就不参与递归了
GoTo 100
End If
For k As Integer = 1 To FindNearby(sender).GetUpperBound(0) '遍历3*3周围的方块,
If cubes(FindNearby(sender)(k).X, FindNearby(sender)(k).Y).checked = False And cubes(FindNearby(sender)(k).X, FindNearby(sender)(k).Y).LandMine = False Then
cubes(FindNearby(sender)(k).X, FindNearby(sender)(k).Y).checked = True
CubeOnMouseUp(cubes(FindNearby(sender)(k).X, FindNearby(sender)(k).Y), CType(Nothing, MouseEventArgs))
Continue For
End If
Next
End If
End If
100:
'当递归结束后执行下面的'判断结果
' Play_Music("蹦")
If e IsNot Nothing Then
MySpaceNumbers = 0
For Each item As cube In cubes
If item IsNot Nothing AndAlso item.state = cube.CubeStates.space Then
MySpaceNumbers += 1
End If
Next
If MySpaceNumbers = one * one - cube.BompCount Then
ShowAllBompAndAllCubeDisabeled()
Play_Music(New SoundPlayer(My.Resources.团灭))
MessageBox.Show("VICTORY!")
End If
End If
FirstClick = False
End Sub
''' <summary>
''' '把图片显示到响应的方块中,参数是要显示的是哪个方块
''' </summary>
''' <param name="sender"></param>
Sub showCubeNumber(sender As Object)
Dim sum As Integer = FindBompNumber(FindNearby(sender))
Dim image() As Image = {My.Resources._1, My.Resources.two, My.Resources.three, My.Resources.four, My.Resources.five, My.Resources.six, My.Resources.seven, My.Resources.eight}
If sum > 0 Then
CType(sender, cube).Image = image(sum - 1)
End If
End Sub
''' <summary>
''' '找到一个方块周围的地雷总数,参数是坐标
''' </summary>
''' <param name="xys"></param>
''' <returns></returns>
Function FindBompNumber(xys() As Point) As Integer '找到一个方块周围的地雷总数,参数是坐标
Dim i As Integer
Dim sum As Integer = 0
For i = 1 To UBound(xys)
If cubes(xys(i).X, xys(i).Y).LandMine = True Then
sum += 1
End If
Next
Return sum
End Function
''' <summary>
''' 显示所有的炸弹并点击不可用
''' </summary>
Sub ShowAllBompAndAllCubeDisabeled()
For Each item As cube In cubes
If item IsNot Nothing Then
item.Enabled = False
item.BackColor = Color.AntiqueWhite
If item.LandMine = True Then
item.state = cube.CubeStates.bomp
End If
End If
Next
End Sub
''' <summary>
''' '找十字周围的方块位置
''' </summary>
''' <param name="sender"></param>
''' <returns></returns>
Function FindNearby(sender As Object) As Point() '找十字周围的方块位置'用来对游戏进行递归
Dim i As Integer = CType(sender, cube).x
Dim j As Integer = CType(sender, cube).y
Dim tempArr(0) As Point
Dim xs() As Integer = {i - 1, i, i + 1, i - 1, i + 1, i - 1, i, i + 1}
Dim ys() As Integer = {j - 1, j - 1, j - 1, j, j, j + 1, j + 1, j + 1}
For k As Integer = 0 To 7
If in17(xs(k)) And in17(ys(k)) Then
ReDim Preserve tempArr(UBound(tempArr) + 1)
tempArr(UBound(tempArr)).X = xs(k)
tempArr(UBound(tempArr)).Y = ys(k)
End If
Next
Return tempArr
End Function
''' <summary>
''' 看看是不是在范围之内
''' </summary>
''' <param name="number"></param>
''' <returns></returns>
Function in17(number As Integer) As Boolean
If number >= 1 And number <= one Then
Return True
End If
Return False
End Function
''' <summary>
''' 开始游戏参数是方块的行数量
''' </summary>
''' <param name="number"></param>
Private Sub 开始(number As Integer) '开始游戏
kill = 0
one = number
If cubes.Length > 1 Then
For Each item As cube In cubes
Me.Controls.Remove(item) '再次游戏的时候就会清除原有的方块对象
Next
End If
one = number
ReDim cubes(one, one) '重新定义cubes数组.
Dim I As Integer
Dim J As Integer
cube.BompCount = 0 '所有的雷的数量
For I = 1 To one
For J = 1 To one
cubes(I, J) = New cube '实例化数组元素
'定义大小
cubes(I, J).Size = New Size With {.Height = 38 * 12 \ one, .Width = 38 * 12 \ one}
cubes(I, J).Enabled = True '可用
cubes(I, J).x = I '坐标游戏位置
cubes(I, J).y = J
cubes(I, J).SizeMode = PictureBoxSizeMode.StretchImage '拉伸图片适应图片框
cubes(I, J).Location = New Point With {.X = (J - 1) * 40 * 12 \ one, .Y = (I - 1) * 40 * 12 \ one + 30}
Me.Controls.Add(cubes(I, J)) '实际位置,并且窗体的控件集合增加新的cube
AddHandler cubes(I, J).MouseUp, AddressOf CubeOnMouseUp '为新的bube对象增加事件
Next
Next
End Sub
Private Sub Play_Music(ByVal Mname As SoundPlayer)
Mname.Play() '播放声音
End Sub
Private Sub start(sender As Object, e As EventArgs) Handles 困难1616ToolStripMenuItem.Click, 简单1010ToolStripMenuItem.Click, 高级2020ToolStripMenuItem.Click
开始(CInt(Mid(sender.ToString, 3, 2))) '困难简单或者高级
FirstClick = True
Play_Music(New SoundPlayer(My.Resources.战争前的宁静))
End Sub
Dim kill As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load '窗体加载的时候播放音乐
Play_Music(New SoundPlayer(My.Resources.全军出击))
' My.Computer.Audio.Play("I:\VB2010NET\vb.net学习\类和对象的学习\扫雷\扫雷\Resources\" & "背景音乐" & ".wav", AudioPlayMode.WaitToComplete)
End Sub
End Class
''' <summary>
''' 方块类
''' </summary>
Public Class cube
Inherits PictureBox '继承实体类图片框,因为为了后面方便接收点击事件
Private Shared m_Count As Integer
Private Shared m_BompCount As Integer
Public Shared ReadOnly Property Count() As Integer '总方块数(这是一个共享过程
Get
Return m_Count
End Get
End Property
Public Shared Property BompCount() As Integer '雷的总数量
Get
Return m_BompCount
End Get
Set(value As Integer)
m_BompCount = value
End Set
End Property
Public Enum CubeStates '方块的所有可能的状态
unClicked = 0
space = 1
bomp = 2
flag = 3
End Enum
Private m_state As CubeStates
Public Property state() As CubeStates '根据当前的状态来确定当前方块的图片
Get
Return m_state
End Get
Set(ByVal value As CubeStates)
m_state = value
If value = CubeStates.bomp Then
Me.Image = My.Resources.bomp
ElseIf value = CubeStates.space Then
Me.BackColor = Color.LightGreen
ElseIf value = CubeStates.flag Then
Me.Image = My.Resources.flag
ElseIf value = CubeStates.unClicked Then
Me.Image = Nothing
End If
End Set
End Property
Public Event StateChange()
''' <summary>
''' 当前的是不是地雷
''' </summary>
Private m_LandMine As Boolean
Public Property LandMine() As Boolean
Get
Return m_LandMine
End Get
Set(ByVal value As Boolean)
m_LandMine = value
End Set
End Property
Sub New() '构造函数
Randomize()
Select Case Int(Rnd() * 1.1) '这个数越大雷就越多'随机布雷
Case 0
Me.LandMine = False
Case 1
Me.LandMine = True
m_BompCount += 1
End Select
Me.BorderStyle = BorderStyle.FixedSingle
m_Count += 1
End Sub
Private m_x As Integer '位置x
Public Property x() As Integer
Get
Return m_x
End Get
Set(ByVal value As Integer)
m_x = value
End Set
End Property
Private m_y As Integer
Public Property y() As Integer
Get
Return m_y
End Get
Set(ByVal value As Integer)
m_y = value
End Set
End Property
Public Property checked() As Boolean '是否已经被遍历过了
End Class
小游戏,vb.net,动态生成控件,面向对象,扫雷
上一篇: 用C语言实现简单的扫雷游戏
下一篇: python异常处理(基础)