banner
李大仁博客

李大仁博客

天地虽大,但有一念向善,心存良知,虽凡夫俗子,皆可为圣贤。

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 は面が交差する辺のパラメータを使用してキューの出入りを制御しました。実装は比較的複雑ですが、多くのコントロールを節約できます。もし皆さんに良い方法があれば、ぜひ共有してください。

''' ''' 各面に対応する辺を初期化
''' 
''' 
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

''' ''' 辺データの交換
''' 
''' 
''' 
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、ひし形を描く、単純な点から点への配列

''' ''' ひし形を追加し、ルービックキューブの側面に使用
''' 
''' 
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

''' ''' 横向きのひし形を描く。起点パラメータを通じて、ひし形の4つの定点座標を取得
''' 
''' 
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

''' ''' 縦向きのひし形を描く。起点パラメータを通じて、ひし形の4つの定点座標を取得
''' 
''' 
''' 
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

以下はデモ効果です

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。