본 강의부터 본격적으로 미로만들기 알고리즘인 Hun And Kill을 구현해 봅시다.
이전 강의까지의 코드입니다.
Sub MakeMaze()
worksheets("Sheet2").Select
Dim map_size As Integer
Dim maze() As Boolean '동적배열 선언
map_size = worksheets("Sheet1").Cells(8,2).value
ReDim maze(map_size+2, map_size+2) '배열 크기 선언
'배열값 초기화
For i=1 To map_size+2
For j=1 To map_size+2
If i = 1 Or j = 1 Or i = map_size+2 Or j = map_size+2 Then
maze(i,j) = True
Else
maze(i,j) = False
End If
Next j
Next i
'셀을 정사각형으로 만들기
Range("A1:XFD1048576").ColumnWidth = 1.00
Range("A1:XFD1048576").RowHeight = 10.00
'조이스틱을 위한 셀 만들기
Range(Cells(1,1), Cells(3,3)).ColumnWidth = 0.1
Range(Cells(1,1), Cells(3,3)).RowHeight = 1.0
'필요없는 셀은 숨기기
Rows(map_size+6 & ":" & Rows.Count).EntireRow.Hidden = True
Range(Cells(4,map_size+6), Cells(map_size+5,Columns.Count)).EntireColumn.Hidden = True
'미로 테두리 그리기
Range(Cells(3+1, 3+1), Cells(3+map_size+2, 3+map_size+2)).Interior.ColorIndex = 3
Range(Cells(3+2, 3+2), Cells(3+map_size+1, 3+map_size+1)).Interior.ColorIndex = 0
Range(Cells(3+1, 3+1), Cells(3+map_size+2, 3+map_size+2)).Borders.Weight = xlThick
End Sub
Hunt And Kill이 알고리즘은 아래의 링크에 자세히 설명되어 있습니다.
2020/02/26 - [엑셀 vba 게임] - 엑셀 vba 미로만들기(1) - Hunt And Kill 알고리즘 설명
먼저 알고리즘의 첫번째인 임의의 칸을 설정해 봅시다
먼저 난수를 생성해 봅시다. 난수 생성 방법도 아래의 링크에서 자세한 설명을 찾아보실 수 있습니다.
2020/02/21 - [엑셀 vba 기초] - 엑셀 vba 랜덤한 수 생성하는 법
Sub MakeMaze()
Randomize '난수 Seed값 초기화
Dim row, col As Integer
''' 이전 강의의 코드(생략) '''
row = Int(Rnd * map_size) + 2
col = Int(Rnd * map_size) + 2
maze(row,col) = True
Cells(3+row, 3+col).Interior.ColorIndex = 6
End Sub
row와 col의 변수를 새로 생성하고 각 변수에 테두리를 제외한 셀에 해당하는 행과 열을 넣어야 합니다.
난수 생성의 범위 크기는 map_size이고 시작값은 테두리를 제외해야 하므로 1이 아닌 2를 사용해야 합니다.
만약 map_size가 5라면 2~6까지의 난수를, map_size가 10이라면 2~12까지의 난수를 생성해야 하기 때문입니다.
그 후에 랜덤으로 선택된 셀에서 부터 미로를 만들어 갈 것이므로 maze(row,col)의 값을 True로 설정해 줍니다.
또한 어떤 셀이 선택되었는지 알아보기 위해서 선택된 셀의 배경색을 노란색으로 바꿔줍니다
여기서 유의해야 할 점은 셀을 선택할 때에는 테두리 안의 미로를 선택해야 하므로 조이스틱크기인 3을 더한 Cells(3+row, 3+col)과 같이 표현해 줍니다.
이젠 노란색 셀을 움직여 봅시다.
Hunt And Kill의 첫번째 로직은 미로가 아닌 칸이 미로를 만들면서 나아갈 수 있을 때까지 나아가는 것입니다.
이를 코드로 구현해 봅시다.
Sub MakeMaze()
Randomize '난수 Seed값 초기화
Dim row, col As Integer
Dim move As Integer
''' 이전 강의의 코드(생략) '''
row = Int(Rnd * map_size) + 2
col = Int(Rnd * map_size) + 2
maze(row,col) = True
Cells(3+row, 3+col).Interior.ColorIndex = 6
Do Until maze(row-1, col) And maze(row+1, col) And maze(row, col-1) And maze(row, col+1)
''' 코드 작성 중...'''
Loop
End Sub
우선 움직일 방향을 정하는 move 변수를 생성해 줍니다.
그리고 Do Until Loop 반복문을 사용합니다.
maze(row-1, col)은 현재 선택된 미로의 위쪽 셀
maze(row+1,col)은 현재 선택된 미로의 아래쪽 셀
maze(row,col-1)은 현재 선택된 미로의 왼쪽 셀
maze(row,col+1)은 현재 선택된 미로의 오른쪽 셀
입니다.
그리고 maze()의 배열값이 True라면 그 칸은 이미 미로가 생성되었다는 뜻입니다.
따라서 Do Until Loop 반복문에 사용된 조건문은 현재 선택된 미로에서 더이상 나아갈 곳이 없다는 걸 의미합니다.
그럼 계속해서 코드를 작성해 봅시다.
코드가 길어지면 보기 어려우니 아래의 예제에서는 Do Until Loop 반복문의 안쪽 코드만 작성하겠습니다.
Do Until maze(row-1, col) And maze(row+1, col) And maze(row, col-1) And maze(row, col+1)
move = Int(Rnd * 4) + 1
Select Case move
Case 1 '위쪽으로 이동할 때
If maze(row-1, col) = False Then
Cells(3+row - 1, 3+col).Borders(xlEdgeBottom).LineStyle = xlNone
row = row - 1
End If
Case 2 '오른족으로 이동할 때
If maze(row, col+1) = False Then
Cells(3+row, 3+col + 1).Borders(xlEdgeLeft).LineStyle = xlNone
col = col + 1
End If
Case 3 '왼쪽으로 이동할 때
If maze(row, col-1) = False Then
cells(3+row, 3+col - 1).Borders(xlEdgeRight).LineStyle = xlNone
col = col - 1
End If
Case 4 '아래쪽으로 이동할 때
If maze(row+1, col) = False Then
Cells(3+row + 1, 3+col).Borders(xlEdgeTop).LineStyle = xlNone
row = row + 1
End If
End Select
maze(row,col) = True
Cells(3+row, 3+col).interior.ColorIndex = 6
Loop
move 변수에 1부터 4까지 중 난수를 입력해 줍니다. 그 후에 Select Case 문으로 move의 각 값에 맞는 코드를 실행해 줍니다.
move = 1 일 때를 보면,
move = 1 은 위쪽으로 이동을 뜻하므로 If maze(row-1, col) = False 를 통해 위쪽 셀이 미로인지 확인합니다.
maze()의 값이 False라면 미로가 아니라는 뜻이므로 우선 Cells().Borders(xlEdgeBottom).LineStyle = xlNone을 이용해 위쪽 셀의 아래쪽 테두리를 지워줍니다.
그 후에 row 값에서 1을 빼고 Select Case 문을 빠져나옵니다.
Select Case 문 밖에 있는 남은 코드를 실행함으로써 이동한 셀도 미로로 선택이 되고 셀 배경색도 노란색으로 바뀌게 됩니다.
위의 사진과 같이 미로의 생성 과정을 딜레이를 통해 보고싶다면 시간 지연을 이용하시면 됩니다.
시간 지연에 대한 자세한 설명은 아래 링크에 있습니다.
2020/02/22 - [엑셀 vba 기초] - 엑셀 vba 시간 지연(딜레이) 넣는 법
지금까지의 코드를 올리면서 이번 강의를 마치겠습니다.
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) '시간지연 코드
Sub MakeMaze()
Randomize
worksheets("Sheet2").Select
Dim map_size As Integer
Dim maze() As Boolean '동적배열 선언
Dim row, col As Integer
map_size = worksheets("Sheet1").Cells(8,2).value
ReDim maze(map_size+2, map_size+2) '배열 크기 선언
'배열값 초기화
For i=1 To map_size+2
For j=1 To map_size+2
If i = 1 Or j = 1 Or i = map_size+2 Or j = map_size+2 Then
maze(i,j) = True
Else
maze(i,j) = False
End If
Next j
Next i
'셀을 정사각형으로 만들기
Range("A1:XFD1048576").ColumnWidth = 1.00
Range("A1:XFD1048576").RowHeight = 10.00
'조이스틱을 위한 셀 만들기
Range(Cells(1,1), Cells(3,3)).ColumnWidth = 0.1
Range(Cells(1,1), Cells(3,3)).RowHeight = 1.0
'필요없는 셀은 숨기기
Rows(map_size+6 & ":" & Rows.Count).EntireRow.Hidden = True
Range(Cells(4,map_size+6), Cells(map_size+5,Columns.Count)).EntireColumn.Hidden = True
'미로 테두리 그리기
Range(Cells(3+1, 3+1), Cells(3+map_size+2, 3+map_size+2)).Interior.ColorIndex = 3
Range(Cells(3+2, 3+2), Cells(3+map_size+1, 3+map_size+1)).Interior.ColorIndex = 0
Range(Cells(3+1, 3+1), Cells(3+map_size+2, 3+map_size+2)).Borders.Weight = xlThick
row = Int(Rnd * map_size) + 2
col = Int(Rnd * map_size) + 2
maze(row,col) = True
Cells(3+row, 3+col).Interior.ColorIndex = 6
Do Until maze(row-1, col) And maze(row+1, col) And maze(row, col-1) And maze(row, col+1)
move = Int(Rnd * 4) + 1
Select Case move
Case 1 '위쪽으로 이동할 때
If maze(row-1, col) = False Then
Cells(3+row - 1, 3+col).Borders(xlEdgeBottom).LineStyle = xlNone
row = row - 1
End If
Case 2 '오른족으로 이동할 때
If maze(row, col+1) = False Then
Cells(3+row, 3+col + 1).Borders(xlEdgeLeft).LineStyle = xlNone
col = col + 1
End If
Case 3 '왼쪽으로 이동할 때
If maze(row, col-1) = False Then
cells(3+row, 3+col - 1).Borders(xlEdgeRight).LineStyle = xlNone
col = col - 1
End If
Case 4 '아래쪽으로 이동할 때
If maze(row+1, col) = False Then
Cells(3+row + 1, 3+col).Borders(xlEdgeTop).LineStyle = xlNone
row = row + 1
End If
End Select
maze(row,col) = True
Cells(3+row, 3+col).interior.ColorIndex = 6
Sleep(50) '시간지연 코드
Loop
End Sub
'엑셀 vba 게임' 카테고리의 다른 글
엑셀 vba 미로만들기(8) - Hunt And Kill 알고리즘 구현3 (1) | 2020.03.09 |
---|---|
엑셀 vba 미로만들기(7) - Hunt And Kill 알고리즘 구현2 (0) | 2020.03.07 |
엑셀 vba 미로만들기(5) - 미로 테두리 설정 (0) | 2020.02.29 |
엑셀 vba 미로만들기(4) - 배열 (0) | 2020.02.29 |
엑셀 vba 미로만들기(3) - 맵 구성하기 (0) | 2020.02.28 |
WRITTEN BY