Home > 语言编程 > 使用VB.Net GDI+编程编写的3D魔方游戏程序

使用VB.Net GDI+编程编写的3D魔方游戏程序

最近学习了.net下的GDI+编程,下面小秀一下成果,使用GDI+编写的桌面魔方程序,今天把源代码放上,欢迎大家下载,如果机器上有.net环境的话可以直接运行bin目录下的MagicCube.exe进行游戏。

源代码下载地址
http://www.lidaren.com/code/magiccube/magiccube.zip

下面方式几个重要的算法程序
1,魔方正面九宫格90度翻转,这个只要细心观察翻转前和翻转后的魔方,你就可以得到答案
左转90度:以(0,0)(2,2)为对称轴翻转后,再以(1,0)(1,2)为对称轴翻转
右转90度:以(0,2)(2,0)为对称轴翻转后,再以(1,0)(1,2)为对称轴翻转
算法如下:

'正方形数据交换
    Private Sub RevertRectangleLeft(ByVal id As Integer)
 
        '要实现左转90度
        '先对角线转置
        Dim i, j As Integer
        For i = 1 To Me.DIMCOUNT - 1
            For j = 0 To i - 1
                '交换数据
                Dim temp As Integer
                temp = Me.Matrix3D(id)(i)(j)
                Me.Matrix3D(id)(i)(j) = Me.Matrix3D(id)(j)(i)
                Me.Matrix3D(id)(j)(i) = temp
            Next
        Next
        ''后水平翻转
        For i = 0 To Me.DIMCOUNT - 1
            '交换数据
            Dim temp As Integer
            temp = Me.Matrix3D(id)(0)(i)
            Me.Matrix3D(id)(0)(i) = Me.Matrix3D(id)(Me.DIMCOUNT - 1)(i)
            Me.Matrix3D(id)(Me.DIMCOUNT - 1)(i) = temp
        Next
    End Sub
 
    '正方形数据交换
    Private Sub RevertRectangleRight(ByVal id As Integer)
 
        '要实现右转90度
        '先对角线转置
        Dim i, j As Integer
        For i = 0 To Me.DIMCOUNT - 1
            For j = 0 To Me.DIMCOUNT - 1 - i - 1
                '交换数据
                Dim temp As Integer
                temp = Me.Matrix3D(id)(i)(j)
                Me.Matrix3D(id)(i)(j) = Me.Matrix3D(id)(Me.DIMCOUNT - 1 - j)(Me.DIMCOUNT - 1 - i)
                Me.Matrix3D(id)(Me.DIMCOUNT - 1 - j)(Me.DIMCOUNT - 1 - i) = temp
            Next
        Next
        ''后水平翻转
        For i = 0 To Me.DIMCOUNT - 1
            '交换数据
            Dim temp As Integer
            temp = Me.Matrix3D(id)(0)(i)
            Me.Matrix3D(id)(0)(i) = Me.Matrix3D(id)(Me.DIMCOUNT - 1)(i)
            Me.Matrix3D(id)(Me.DIMCOUNT - 1)(i) = temp
        Next
    End Sub

2,魔方正面的4个侧面的翻转,这个实现相对较难,方法也很多,CG这里使用了队列保存所有方块信息,然后再次存回数组的方式来实现,另外为了统一方向,CG使用了面相交边的参数来控制队列的进出,实现比较复杂,但是可以节省很多控件,如果大家有好的方法,欢迎分享

    ''' <summary>
    ''' 初始化各个面对应的边
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InitEdge()
        '+/- 10 + 100 + 1000 + X 用于记录对应变的交换方式
        '+/- 表示交换方式,顺序和逆序
        '10 表示 x 的位置 x = 0 或 x = DIMCOUNT
        '100 表示 y 的位置 y = 0 或 y = DIMCOUNT
        '1000 表示 xy的方向 =0 y++ =1000 x++
        Edge(0) = New Integer(3) {-12, 101, 1003, -1004}
        Edge(1) = New Integer(3) {-1002, -1005, -1003, -1000}
        Edge(2) = New Integer(3) {-15, 1, 0, 4}
        Edge(3) = New Integer(3) {-10, -11, 5, -14}
        Edge(4) = New Integer(3) {1102, 1100, 1103, 1105}
        Edge(5) = New Integer(3) {-13, -1001, 2, 1104}
    End Sub
 
    ''' <summary>
    ''' 边数据交换
    ''' </summary>
    ''' <param name="id"></param>
    ''' <remarks></remarks>
    Private Sub RevertEdgeRight(ByVal id As Integer)
        '获取边数据
        Dim edges() As Integer
        edges = Me.Edge(id)
        Dim x, y, z, d As Integer
        '临时队列数组
        Dim queue() As Integer
        queue = New Integer(4 * DIMCOUNT - 1) {}
 
        Dim edge1 As Integer
 
        Dim m, i, j As Integer
        Dim count As Integer = 0
 
        '存入临时数组
        For m = 0 To 3
 
            '需要交换边
            edge1 = edges(m)
 
            '获取交换行号与列号
            If Math.Floor(Math.Abs(edge1 / 1000)) = 1 Then
                z = 1
                edge1 = edge1 Mod 1000
            Else
                z = 0
            End If
 
            If Math.Floor(Math.Abs(edge1 / 100)) = 1 Then
                y = DIMCOUNT - 1
                edge1 = edge1 Mod 100
            Else
                y = 0
            End If
 
            If Math.Floor(Math.Abs(edge1 / 10)) = 1 Then
                x = DIMCOUNT - 1
                edge1 = edge1 Mod 10
            Else
                x = 0
            End If
 
            Dim sg = Math.Sign(edge1)
 
            If sg = 0 Then
                sg = 1
            End If
 
            '获取符号
            If sg = 1 Then
                d = 0
            Else
                d = 1
            End If
 
            '存入临时数组
            For i = 0 To DIMCOUNT - 1
                If z = 0 Then
                    queue(m * DIMCOUNT + i) = _
                        Me.Matrix3D(Math.Abs(edge1))(x)(d * (DIMCOUNT - 1) + sg * i)
                Else
                    queue(m * DIMCOUNT + i) = _
                        Me.Matrix3D(Math.Abs(edge1))(d * (DIMCOUNT - 1) + sg * i)(y)
                End If
            Next
        Next
        '交换后存回
        '存入临时数组
        For m = 0 To 3
            '需要交换边
            edge1 = edges(m)
            '获取交换行号与列号
            If Math.Floor(Math.Abs(edge1 / 1000)) = 1 Then
                z = 1
                edge1 = edge1 Mod 1000
            Else
                z = 0
            End If
            If Math.Floor(Math.Abs(edge1 / 100)) = 1 Then
                y = DIMCOUNT - 1
                edge1 = edge1 Mod 100
            Else
                y = 0
            End If
 
            If Math.Floor(Math.Abs(edge1 / 10)) = 1 Then
                x = DIMCOUNT - 1
                edge1 = edge1 Mod 10
            Else
                x = 0
            End If
            '获取符号
            Dim sg = Math.Sign(edge1)
 
            If sg = 0 Then
                sg = 1
            End If
            '获取方向
            'd =  Math.Sign(edge1) == 1 ? 0 : -1
            If sg = 1 Then
                d = 0
            Else
                d = 1
            End If
            '存回
            For i = 0 To DIMCOUNT - 1
                If z = 0 Then
                    Me.Matrix3D(Math.Abs(edge1))(x)(d * (DIMCOUNT - 1) + sg * i) = _
                        queue(((1 + m) Mod 4) * DIMCOUNT + i)
                Else
                    Me.Matrix3D(Math.Abs(edge1))(d * (DIMCOUNT - 1) + sg * i)(y) = _
                        queue(((1 + m) Mod 4) * DIMCOUNT + i)
                End If
            Next
        Next
    End Sub

3,绘制菱形,简单的点到点数组

    ''' <summary>
    ''' 增加菱形,用于魔方侧面
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub AddPolygons()
 
        '定义点阵数组
        Dim pts() As PointF
        '绘制上边矩形
        Dim i, j As Integer
        For i = 0 To DIMCOUNT - 1
            For j = 0 To DIMCOUNT - 1
                pts = AddPolygonPath1(New Point(POSTION.X + i * CUBEH + j * POLYH, _
                                            POSTION.Y - j * POLYH))
                '获取填充内容,并绘制
                GR.FillPolygon(Me.GetColorById(2, DIMCOUNT - 1 - j, i), pts)
                GR.DrawPolygon(OUTLINE, pts)
            Next
        Next
 
        '绘制左边矩形
        For i = 0 To DIMCOUNT - 1
            For j = 0 To DIMCOUNT - 1
                pts = AddPolygonPath2(New Point(POSTION.X + DIMCOUNT * CUBEH + i * POLYH, _
                                        POSTION.Y + j * CUBEH - i * POLYH))
                '获取填充内容,并绘制
                GR.FillPolygon(Me.GetColorById(4, j, i), pts)
                GR.DrawPolygon(OUTLINE, pts)
            Next
        Next
    End Sub
 
    ''' <summary>
    ''' 绘制横向菱形,通过起点参数,获取菱形四个定点坐标
    ''' </summary>
    ''' <remarks></remarks>
    Private Function AddPolygonPath1(ByVal pt As Point) As PointF()
        Dim pts(3) As PointF
        pts(0) = pt
        pts(1) = New Point(pt.X + POLYH, pt.Y - POLYH)
        pts(2) = New Point(pt.X + CUBEH + POLYH, pt.Y - POLYH)
        pts(3) = New Point(pt.X + CUBEH, pt.Y)
        Return pts
    End Function
 
    ''' <summary>
    ''' 绘制在竖向菱形,通过起点参数,获取菱形四个定点坐标
    ''' </summary>
    ''' <param name="pt"></param>
    ''' <remarks></remarks>
    Private Function AddPolygonPath2(ByVal pt As Point) As PointF()
        Dim pts(3) As PointF
        pts(0) = pt
        pts(1) = New Point(pt.X + POLYH, pt.Y - POLYH)
        pts(2) = New Point(pt.X + POLYH, pt.Y + CUBEH - POLYH)
        pts(3) = New Point(pt.X, pt.Y + CUBEH)
        Return pts
    End Function

下面是演示效果
3D魔方游戏

Categories: 语言编程 Tags: , ,
  1. No comments yet.
  1. No trackbacks yet.
You must be logged in to post a comment.