欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vb.net使用GDI+实现扫雷小游戏

程序员文章站 2022-04-07 13:56:49
...

vb.net使用GDI+实现扫雷小游戏

先说一下扫雷的规则:左键点开,右键用旗子标记(取消标记),一个方块上的数字代表周围九个格里有几颗雷! 比如,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,动态生成控件,面向对象,扫雷