본 강의에서는 미로의 테두리들을 구성해 봅시다.

 

이전 강의까지 작성한 코드입니다.

 

Sub MakeMaze()
	worksheets("Sheet2").Select
	Dim map_size As Integer
	Dim maze() As Boolean '동적배열 선언
    
	map_size = worksheets("Sheet1").Cells(8,2).value
	ReDim maze(1 To map_size+2, 1 To 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
End Sub

 

먼저 이전 강의를 통해 우리가 미로를 만들 워크시트 왼쪽 위 3x3의 범위에 조이스틱을 만들었고 숨겼습니다.

 

위의 사진과 같이 셀의 시작이 Cells(4,4)부터입니다. 따라서 항상 특정 행과 열을 선택할 때에는 조이스틱의 크기인 3을 더해주어야 합니다.

 

먼저 미로를 구현할 판을 그려봅시다. 미로의 테두리 색은 빨간색으로 지정하겠습니다.

 

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

Cells()에 행과 열에 3씩 더한 것을 보실 수 있습니다. 또한 Range().Interior.ColorIndex의 값을 변경함으로써 셀의 배경색을 바꿀수 있습니다.

 

먼저 테두리를 포함한 미로의 모든 셀 배경색을 빨간색으로 지정합니다. 그리고나서 테두리를 제외한 미로의 셀 배경색을 지웁니다.

 

이렇게 되면 아래의 그림과 같이 셀이 만들어 집니다.

 

이후에 미로생성을 위해 각 셀에 테두리의 두께를 지정해 줍시다. 테두리의 두께는 Range().Borders.Weight로 지정할 수 있습니다.

 

xlHairline: 가장 가는 실선

xlThin: 가는 실선

xlMedium: 보통굵기의 선

xlThick: 굵은 실선

 

Range(Cells(4,4), Cells(3+map_size+2, 3+map_size+2)).Borders.Weight = xlThcik

위의 코드를 추가하면 아래의 셀에 두꺼운 테두리가 적용됩니다.

 

이젠 본격적으로 Hunt And Kill 알고리즘을 구현할 준비를 마쳤습니다. 다음 강의부터 미로 알고리즘을 구현해 봅시다!


WRITTEN BY
컴공학도

,

각각의 셀이 미로가 맞는지, 아니면 아직 미로가 아닌지 구분하기 위해서 2차원 배열을 사용할 것입니다.

 

우선 이전 강의까지의 코드입니다.

Sub MakeMaze()
	worksheets("Sheet2").Select
	Dim map_size As Integer
    
	map_size = worksheets("Sheet1").Cells(8,2).value
    
	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
End Sub

 

여기에 2차원 배열 변수를 추가해 봅시다.

 

Dim maze() As Boolean

 

위의 코드를 통해 이름은 maze, 타입은 Boolean타입의 동적 배열을 선언해 줍니다.

 

정적 배열이 아닌 동적 배열을 선언하는 이유는 선언 당시에는 맵의 크기를 알 수 없기 때문입니다. 맵의 크기를 입력은 후에 ReDim으로 배열의 크기를 정해줍시다.

 

ReDim maze(1 To map_size+2, 1 To map_size+2)

 

map_size+2 x map_size+2 크기의 maze 배열이 생성되었습니다.(+2는 테두리를 위해서 입니다.)

 

이젠 미로가 아닌 곳은 False로, 미로인 곳은 True로, 그리고 테두리는 True로 배열값을 초기화해 줍시다. 이때 For 반복문을 이용해 줍니다.

 

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

 

이를 통해 배열 생성과 초기화를 모두 마쳤습니다.

 

아래에는 이전 강의와 이번 강의의 내용을 합친 코드입니다.

 

Sub MakeMaze()
	worksheets("Sheet2").Select
	Dim map_size As Integer
	Dim maze() As Boolean '동적배열 선언
    
	map_size = worksheets("Sheet1").Cells(8,2).value
	ReDim maze(1 To map_size+2, 1 To 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
End Sub

WRITTEN BY
컴공학도

,

저희가 만드는 미로는 2개의 워크시트로 구성할 것입니다.

 

첫번째는 게임을 시작하고 플레이어의 점수를 기록하는 시트, 두번째는 미로를 플레이하는 시트입니다.

 

첫번째 시트의 구성은 간단합니다. 

게임시작 버튼, 이름과 크기를 입력하는 셀, 플레이어의 점수를 기록하는 셀로 구성됩니다. 특별한 코드가 없으므로 넘어가겠습니다. 셀의 크기와 버튼의 디자인은 개인의 취향에 맞게 해주시면 됩니다.

 

이젠 본격적으로 두번째 시트를 구성해 봅시다.

 

맨 왼쪽 위의 3x3의 셀은 키보드 이벤트(이하 조이스틱)를 위해 남겨놓고 행의 높이는 1, 열의 너비는 0.1로 설정합니다. 그리고 미로가 아닌 칸은 선택할 수 없도록 모두 숨겨야 합니다.

Sub MakeMaze()
	worksheets("Sheet2").Select
	Dim map_size As Integer
    
	'맵 사이즈 입력받기
	map_size = worksheets("Sheet1").Cells(8,2).value
    
	'셀을 정사각형으로 만들기
	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
End Sub

MakeMaze는 미로를 만드는 프로시저입니다.

 

ColumnWidth 와 RowHeight를 이용해 셀의 크기를 설정해주고, EntireRow.Hidden 과 EntireColumn.Hidden을 이용해 미로가 아닌 칸은 숨겨줍니다.

 

미로가 아닌 셀을 숨길 때,

Rows(map_size+6 & ":" & Rows.Count)로 미로의 아래 행을 모두 선택할 수 있습니다. map_size+6인 이유는

미로크기 + 조이스틱 3칸 + 테두리 2칸 + 1칸 을 해야 미로의 아래행부터 시작할 수 있기 때문입니다.

 

Rows.Count는 해당 시트의 가장 마지막 행을 알 수 있는 변수입니다.

 

이후에 Range를 이용해 미로의 오른쪽 셀들을 전부 선택해 숨겨줍니다.

 

위의 예제와 같이 게임시작 버튼과 매트로를 지정한 뒤 버튼을 눌러 크기가 10인 미로를 생성하게 되면 왼쪽위의 3x3의 조이스틱과 테두리를 포함한 12x12의 미로공간이 만들어지게 됩니다.


WRITTEN BY
컴공학도

,

우리가 만드는 미로에서는 직접 방향키를 이용해 캐릭터를 움직여가며 미로를 풀어나갈 겁니다.

 

그러기 위해서는 각 방향키를 눌렀을 때 이벤트가 발생하도록 만들어야 합니다.

 

키보드 이벤트를 발생시키기 위해서는 Application.OnKey() 함수를 사용해도 되지만 필자가 사용하는 한셀2018버전에서는 Application.OnKey()함수가 작동하지 않습니다.

 

따라서 Worksheet_SelectionChange 프로시저를 사용할 예정입니다. 

 

Worksheet_SelectionChange는 해당 워크시트의 선택된 셀이 바뀔 때마다 실행이 됩니다.

 

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
	With Target.Cells
		MsgBox "행: " & .Row & " 열: "& .Column
	End With
End Sub

셀이 선택될 때마다 SelectionChange 프로시저가 실행되어서 선택된 셀의 행과 열을 MsgBox로 보여주는 예제입니다.

 

이를 이용해 키보드 이벤트를 만들어 보겠습니다.

 

먼저 아래의 논리구조로 선택된 셀이 바뀌었을 때 무슨 방향키를 눌렀는지 알 수 있습니다.

 

1. 기준 셀을 하나 정해둔다.

  1) 위쪽 방향키를 눌러서 선택된 셀은 기준 셀보다 행의 값이 1이 작다.

  2) 아래쪽 방향키를 눌러서 선택된 셀은 기준 셀보다 행의 값이 1이 크다.

  3) 왼쪽 방향키를 눌러서 선택된 셀은 기준 셀보다 행의 값이 1이 작다.

  4) 오른쪽 방향키를 눌러서 선택된 셀은 기준 셀보다 행의 값이 1이 크다.

 

무슨 방향키를 눌렀는지 알 수 있따면 각각의 방향키에 맞는 프로시저를 실행시킬 수 있습니다.

 

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
	Dim row, col As Integer
	row = 2
	col = 2
	With Target.Cells
		If .Row = row-1 Then
			MsgBox "UP"
		ElseIf .Row = row+1 Then
			MsgBox "Down"
		ElseIf .Column = col-1 Then
			MsgBox "Left"
		ElseIf .Column = col+1 Then
			MsgBox "Right"
		End If
		Cells(row, col).Select
	End With
End Sub

기준 셀을 B2로 잡고 상하좌우로 움직인 예제입니다.

 

위의 예제처럼 각각의 방향키를 인식할 수 있습니다.

 

MsgBox를 띄우는 대신 MoveUp프로시저를 만든 다음에 MsgBox "UP" 대신 Call MoveUp 으로 대체한다면 위쪽 방향키가 눌렸을 때 원하는 코드를 실행시키도록 할 수 있습니다.

 

하지만 여기서 만약 마우스로 C10을 선택하여도 Right이라는 MsgBox가 뜨게 되고, D1을 선택하면 Up이라는 MsgBox가 뜨게 됩니다. 이런 예외를 처리하기 위해서 기준 셀과 상하좌우의 셀이 포함된 행렬을 숨겨주시면 됩니다.

 

여기서 행의 높이나 열의 너비를를 0으로 지정해 완전히 숨기게 되면 셀 선택이 불가능하게 됩니다. 따라서 완전히 숨기기보단 행의 높이는 1, 열의 너비는 0.1 정도로 보이지만 않게 설정해주시면 됩니다.

(ps. 위의 코드를 작성한 상태에서는 셀 선택이 되지 않습니다. 15번째 줄의 'Cells(row, col).Select'를 주석처리 해주시면 됩니다.)

 

위의 사진과 같이 깔끔하게 키보드 이벤트를 구현할 수 있습니다.


WRITTEN BY
컴공학도

,