반응형

안녕하세요.

 

어쩌다 VBA로 간단한 퍼즐을 만들었습니다.

 

완성 파일 다운로드

8Puzzle.xlsm
0.03MB

 

흔히 8 퍼즐 또는 슬라이드 퍼즐로 부르는 것입니다.

사용자 정의 폼을 이용했고, 숫자 단추는 동적으로 생성했습니다.

동적으로 생성한 단추의 이벤트 처리를 위해 클래스 모듈도 추가했습니다.

 

코드를 설명하지는 않겠습니다.

 

Module1

Option Explicit
Option Base 1

Public Const W As Integer = 50  ' 명령단추 위치 지정
Public T(3, 3) As Integer       ' 정답 저장
Public T1(3, 3) As Integer      ' 현재 위치 저장
Public BX As Integer            ' 빈 값 X좌표
Public BY As Integer            ' 빈 값 Y좌표
Public MCheck As Boolean        ' 단추를 움직인적이 있는지 확인

Public Sub 실행()
    실행폼.Show
End Sub

Public Sub 옮기기(x As CommandButton)
    Dim i As Integer
    Dim j As Integer
    Dim c As Integer
    Dim d As Integer
    
    For i = 1 To 3
        For j = 1 To 3
            If T1(i, j) = Val(x.Caption) Then
                c = i
                d = j
                Exit For
            End If
        Next j
    Next i
    
    If c = (BX + 1) And (d = BY) Then
        T1(BX, BY) = x.Caption
        x.Top = BX * W
        BX = c
        BY = d
        T1(BX, BY) = 9
        MCheck = True
    ElseIf c = (BX - 1) And (d = BY) Then
        T1(BX, BY) = x.Caption
        x.Top = BX * W
        BX = c
        BY = d
        T1(BX, BY) = 9
        MCheck = True
    ElseIf (c = BX) And d = (BY + 1) Then
        T1(BX, BY) = x.Caption
        x.Left = BY * W
        BX = c
        BY = d
        T1(BX, BY) = 9
        MCheck = True
    ElseIf (c = BX) And d = (BY - 1) Then
        T1(BX, BY) = x.Caption
        x.Left = BY * W
        BX = c
        BY = d
        T1(BX, BY) = 9
        MCheck = True
    End If
    
    If MCheck Then
        실행폼.Label1.Caption = "움직였습니다"
        Call 확인하기
    End If
End Sub

Private Sub 확인하기()
    Dim i As Integer
    Dim j As Integer
    Dim Check As Boolean
    
    Check = True
    
    For i = 1 To 3
        For j = 1 To 3
            If T(i, j) <> T1(i, j) Then
                Check = False
            End If
        Next j
    Next i
    
    If Check Then
        MsgBox "퍼즐 해결"
        실행폼.초기화
    End If
End Sub

Class1

Public WithEvents cbEvent1 As MSForms.CommandButton

Private Sub cbEvent1_Click()
    옮기기 cbEvent1
End Sub

실행폼

Option Explicit
Option Base 1

Dim b(8) As MSForms.CommandButton
Dim cmdB1 As New Class1
Dim cmdB2 As New Class1
Dim cmdB3 As New Class1
Dim cmdB4 As New Class1
Dim cmdB5 As New Class1
Dim cmdB6 As New Class1
Dim cmdB7 As New Class1
Dim cmdB8 As New Class1

Sub 초기화()
    Dim i As Integer
    Dim j As Integer
    
    T(1, 1) = 1
    T(1, 2) = 2
    T(1, 3) = 3
    T(2, 1) = 8
    T(2, 2) = 9
    T(2, 3) = 4
    T(3, 1) = 7
    T(3, 2) = 6
    T(3, 3) = 5
    
    For i = 1 To 3
        For j = 1 To 3
            If T(i, j) <> 9 Then
                b(T(i, j)).Top = i * W
                b(T(i, j)).Left = j * W
            Else
                BX = i
                BY = j
            End If
            
            T1(i, j) = T(i, j)
        Next j
    Next i
    
    MCheck = False
    Label1.Caption = "움직일 단추를 선택하세요"
End Sub

Private Sub cmdInit_Click()
    Call 초기화
End Sub

Private Sub cmdShuffle_Click()
    Dim Temp1 As Integer
    Dim i As Integer
    Dim j As Integer
    Dim x As Integer
    Dim y As Integer
    
    Randomize
    
    Call 초기화
    
    x = 2
    y = 2
    
    For i = 1 To 500
        j = Rnd * (4 - 1) + 1
        
        Select Case j
            Case 1  ' 위로
                If x - 1 > 0 Then
                    Temp1 = T1(x - 1, y)
                    T1(x - 1, y) = T1(x, y)
                    T1(x, y) = Temp1
                    x = x - 1
                End If
            Case 2  ' 아래로
                If x + 1 < 4 Then
                    Temp1 = T1(x + 1, y)
                    T1(x + 1, y) = T1(x, y)
                    T1(x, y) = Temp1
                    x = x + 1
                End If
            Case 3  ' 왼쪽으로
                If y - 1 > 0 Then
                    Temp1 = T1(x, y - 1)
                    T1(x, y - 1) = T1(x, y)
                    T1(x, y) = Temp1
                    y = y - 1
                End If
            Case 4  ' 오른쪽으로
                If y + 1 < 4 Then
                    Temp1 = T1(x, y + 1)
                    T1(x, y + 1) = T1(x, y)
                    T1(x, y) = Temp1
                    y = y + 1
                End If
        End Select
                
    Next i
    
    For i = 1 To 3
        For j = 1 To 3
            If T1(i, j) <> 9 Then
                b(T1(i, j)).Top = i * W
                b(T1(i, j)).Left = j * W
            Else
                BX = i
                BY = j
            End If
        Next j
    Next i
End Sub

Private Sub UserForm_Initialize()
    Dim i As Integer
    
    For i = 1 To 8
        Set b(i) = Controls.Add("Forms.CommandButton.1", "B(" & i & ")")
        
        b(i).Width = W
        b(i).Height = W
        b(i).Caption = i
        b(i).Visible = True
    Next i
    
    Set cmdB1.cbEvent1 = b(1)
    Set cmdB2.cbEvent1 = b(2)
    Set cmdB3.cbEvent1 = b(3)
    Set cmdB4.cbEvent1 = b(4)
    Set cmdB5.cbEvent1 = b(5)
    Set cmdB6.cbEvent1 = b(6)
    Set cmdB7.cbEvent1 = b(7)
    Set cmdB8.cbEvent1 = b(8)
        
    Call 초기화
End Sub

필요하신 분들께 도움이 되기를 바랍니다.

반응형

'매크로&VBA' 카테고리의 다른 글

일정한 개수를 기준으로 나누고 합치기  (0) 2021.12.10
쉼표로 구분된 문자를 잘라서 계산하기  (0) 2021.04.26
배열  (0) 2021.03.10
명령문  (0) 2021.03.07
셀 배경색 기준으로 합계 구하기  (5) 2021.01.18

+ Recent posts