You are on page 1of 1

한셀

[Excel VBA, VBS] 엑셀로 2048 만들기


가속 이웃추가 본문 기타 기능
2020. 2. 4. 18:28

당직 서는 군인들을 위해 작성(사실 조회수를 위함)

군대에서 최신 버전으로 업그레이드된 2018 한셀으로도 구동 가능

한셀2018 에서는 키인식


application.onkey 가 안된다 !

하지만 2048은 다른 게임들처럼 실시간으로 움직여줄 필요 없이


천천히 해도 되기 때문에

화살표 도형에 매크로를 지정해 돌아가는 방식으로 설계함

블로그
카 가속의 블로그

2048.xlsm

(버그 수정했습니다(2))
(2021.02.21 보드판에 1이나 2가 남아있음에도 2, 4와 같은 상위 숫자가 생성되는 문제 해결)

알트+F11로 스크립트 편집기를 연 후에


엑셀 파일 우클릭하고 모듈 삽입 한 후
그 모듈에 코드를 삽입해야 한다.

우선 틀을 만든다

해야할 것은
2048 보드판인
B2 ~ E5 셀을 굵은 외곽 테두리로 지정해주고
가운데 정렬
글씨 크기 20? 정도로 설정해둔다
셀의 색은 설정하지 않아도 알아서 된다.

점수와 하이스코어 셀도 병합 후 가운데 정렬,


테두리와 글씨 크기만 설정한다

가운데에 화살표 도형을 상하좌우 방향으로 만든다

그리고 각각 위 아래 왼쪽 오른쪽 매크로를 지정해둔다

START 버튼은 start 매크로 지정한다.

그리고 1행과 1열의 크기는 좁게 하면 더 이쁘다

1단계 라고 쓰여있는 칸도 병합 후 가운데 정렬 하고


글씨 크기 20 정도로 설정한다

셀의 위치만 바꾸지 않는다면 기본적인 설정은 임의로 변경할 수 있다.

Sub START()
Range("B2:E5").Select
Selection.ClearContents
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
Selection.Interior.Color = RGB(255, 255, 255)
Cells(6, 8) = 0
Cells(2, 6) = "0단계"
Range("A1").Select
Application.OnKey "{UP}", "위"
Application.OnKey "{DOWN}", "아래"
Application.OnKey "{LEFT}", "왼쪽"
Application.OnKey "{RIGHT}", "오른쪽"
End Sub

게임 시작 프로시저

B2:E5셀(보드판) 을 초기화하고 배경색을 흰색으로 한다.


6,8 점수 셀을 초기화 하고
2,6 단계도 초기화

A1셀을 선택해두는 이유는 셀 선택할 때 생기는 테두리가 지저분하기 때문에 구석으로 치웠음

application.onkey "해당키","매크로이름"

하면 해당 키를 눌렀을 때 해당 매크로가 실행된다.


이를 이용해 방향키를 활용한 게임을 만들 수 있지만
군대 한셀2018에서는 이 함수는 빼도 좋다.(어차피 못씀 ㅠㅠ)(라떼는 돌아감)

Sub game_over_condition()
Dim count1, count2
count1 = 0
count2 = 0

For i = 2 To 5 ' 상하좌우 체크


For j = 2 To 5
If Cells(i, j) <> Cells(i - 1, j) Then
If Cells(i, j) <> Cells(i + 1, j) Then
If Cells(i, j) <> Cells(i, j - 1) Then
If Cells(i, j) <> Cells(i, j + 1) Then
count1 = count1 + 1
End If
End If
End If
End If
Next
Next

For i = 2 To 5 ' 모든 칸이 차 있는지 체크


For j = 2 To 5
If Cells(i, j) <> 0 Then
count2 = count2 + 1
End If
Next
Next

If count1 = 16 Then
If count2 = 16 Then
game_over
End If
End If
End Sub

게임 오버 조건 확인 프로시저

반복문을 이용해 모든 셀의 상하좌우를 하나 하나 확인한다.


만약 B2셀과 B3셀이 같다면 합칠 수 있으니까 게임 오버가 안되는 방식
만약 상하좌우와 해당 셀이 다르다면 count1에 1을 더한다. 셀의 수는 16개니까
count1이 16이 되면 게임 오버 조건 달성임

그리고 셀이 비어있다면 0으로 취급된다.


모든 셀이 차 있는지 확인해준다.
이것은 count2로 카운트한다.

count1과 count2가 모두 16이라면 게임오버다

Sub game_over()
Range("B2,C3,D4,E5").Select ' \
With Selection.Borders(xlDiagonalDown)
.LineStyle = xlcontinous
.Weight = xlMedium
.ColorIndex = xlAutomatic
End With

Range("E2,D3,C4,B5").Select ' /
With Selection.Borders(xlDiagonalUp)
.LineStyle = xlcontinous
.Weight = xlMedium
.ColorIndex = xlAutomatic
End With

If Cells(6, 8) > Cells(6, 11) Then


MsgBox "? 당신의 점수가...?", vbQuestion, "띠요옹?"
ActiveWindow.Activate
Cells(5, 11) = Application.InputBox("하이스코어 달성 !", "축하합니다", "이름을 입력해주십시오"
Cells(6, 11) = Cells(6, 8)
Else
MsgBox "GAME OVER", vbOKOnly + vbCritical, "GAME OVER"
ActiveWindow.Activate
End If
Cells(6, 12) = Cells(5, 11)
End Sub

게임 오버 프로시저

게임 오버 했을 경우 보드판에 X자가 그려지게 된다.

B2 C3 D4 E5 에는 왼쪽 위에서 오른쪽 아래로 가는 대각선


B5 C4 D3 E2 에는 왼쪽 아래에서 오른쪽 위로 가는 대각선을 지정한다.

그리고 하이 스코어보다 점수가 높을 경우 inputbox로 이름을 입력한다.

Sub 얇게()
Range("B2:E5").Select
Selection.Font.Bold = False
Range("A1").Select
End Sub

글씨 얇게 하는 프로시저

보드판에 새로운 숫자가 나올 경우에는 알아보기 쉽기 위해


굵은 글씨로 표시된다.
한 턴이 지나면 다시 얇게 만들어야한다

Sub 색깔()
For i = 2 To 5
For j = 2 To 5
Select Case Cells(i, j)
Case 0
Cells(i, j).Interior.Color = RGB(255, 255, 255)
Case 1
Cells(i, j).Interior.Color = RGB(255, 101, 101)
Case 2
Cells(i, j).Interior.Color = RGB(255, 163, 101)
Case 4
Cells(i, j).Interior.Color = RGB(255, 255, 101)
Case 8
Cells(i, j).Interior.Color = RGB(25, 255, 25)
Case 16
Cells(i, j).Interior.Color = RGB(127, 127, 25)
Case 32
Cells(i, j).Interior.Color = RGB(116, 116, 208)
Case 64
Cells(i, j).Interior.Color = RGB(255, 63, 255)
Case 128
Cells(i, j).Interior.Color = RGB(127, 127, 127)
Case 256
Cells(i, j).Interior.Color = RGB(255, 0, 0)
Case 512
Cells(i, j).Interior.Color = RGB(255, 102, 0)
Case 1024
Cells(i, j).Interior.Color = RGB(255, 255, 0)
Case 2048
Cells(i, j).Interior.Color = RGB(23, 181, 94)
Case 4096
Cells(i, j).Interior.Color = RGB(0, 0, 255)
End Select

Next
Next
End Sub

셀 배경색 프로시저

숫자에 따라 셀의 배경색이 변한다.


나름 RGB따서 열심히 지정했다.
부대에서 테스트 결과 1024까지도 나오기 힘들어서
밸런스 조정을 통해 나름 쉽게 만들었다.
그래서 4096을 넘어설 지도 모르는데
넘을 경우 아마 색 지정이 안 될 것이다.
응용해서 아래에 쭉 쭉 추가하면 된다.

Sub 생성()
얇게

Dim rd
Dim mm
Dim isThereOne
Dim isThereTwo
Dim isThereFour

For i = 1 To 1000
rd = WorksheetFunction.RandBetween(0, 15)

If Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 0 Then


Select Case Cells(6, 8)
Case 0 To 300
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 1
Cells(2, 6) = "1단계"
Case 301 To 1000
Cells(2, 6) = "2단계"
mm = WorksheetFunction.RandBetween(1, 10)
If mm <= 6 Then

isThereOne = 0

For k = 2 To 5
For j = 2 To 5
If Cells(k, j) = 1 Then
isThereOne = isThereOne + 1 ' 1의 개수 체크
End If
Next
Next

If isThereOne = 1 Then ' 1이 하나만 존재한다면 짝을 이룰 수 없


Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 1
Else
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 2
End If

ElseIf mm <= 9 Then ' 낮은 확률로 생성 안함


Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 2
End If
Case 1001 To 3001
Cells(2, 6) = "3단계"
mm = WorksheetFunction.RandBetween(1, 10)

isThereTwo = 0

If mm <= 2 Then
For k = 2 To 5
For j = 2 To 5
If Cells(k, j) = 1 Then
isThereOne = isThereOne + 1 ' 1의 개수 체크
ElseIf Cells(k, j) = 2 Then
isThereTwo = isThereTwo + 1 ' 2의 개수 체크
End If
Next
Next

If isThereOne = 1 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 1 ' 1,2 유무에 따라 생성
ElseIf isThereTwo = 1 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 2
Else
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 4
End If

ElseIf mm <= 8 Then


Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 4
ElseIf mm <= 9 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 8
End If

Case 3001 To 10000


Cells(2, 6) = "4단계 !!"
mm = WorksheetFunction.RandBetween(1, 10)
If mm <= 1 Then

isThereOne = 0
isThereTwo = 0

For k = 2 To 5
For j = 2 To 5
If Cells(k, j) = 1 Then ' 1의 개수 체크
isThereOne = isThereOne + 1
ElseIf Cells(k, j) = 2 Then ' 2의 개수 체크
isThereTwo = isThereTwo + 1
End If
Next
Next

If isThereOne = 1 Then '1,


Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 1
ElseIf isThereTwo = 1 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 2
Else
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 4
End If

ElseIf mm <= 8 Then


Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 8
ElseIf mm <= 9 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 16
End If
Case 10001 To 100000
Cells(2, 6) = "5단계 ∞"
mm = WorksheetFunction.RandBetween(1, 10)
If mm <= 1 Then

isThereOne = 0
isThereTwo = 0
isThereFour = 0

For k = 2 To 5
For j = 2 To 5
If Cells(k, j) = 1 Then
isThereOne = isThereOne + 1
ElseIf Cells(k, j) = 2 Then
isThereTwo = isThereTwo + 1
ElseIf Cells(k, j) = 4 Then
isThereFour = isThereFour + 1

End If
Next
Next

If isThereOne = 1 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 1
ElseIf isThereTwo = 1 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 2
ElseIf isThereFour = 1 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 4
End If

ElseIf mm <= 8 Then


Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 16
ElseIf mm <= 9 Then
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2) = 32
End If
End Select
Exit For
End If

Next
Cells(Int(rd / 4) + 2, (rd Mod 4) + 2).Select
Selection.Font.Bold = True '글씨 굵게

game_over_condition

End Sub

숫자 랜덤 생성 프로시저

rd에 0부터 15까지의 랜덤 숫자를 지정한다.


그럼 경우의 수가 총 16개인데
보드판의 칸도 16개다 !

0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
이 순으로 칸이 배정된다.

반복문을 1부터 1000까지 돌리는 이유는


만약 랜덤으로 셀을 찾았는데 그 셀이 이미 차있는 경우
다시 돌려야 하기 때문이다.
어차피 조건에 맞는 셀을 찾으면 마지막에 Exit For 함수로 반복문을 탈출하니 괜찮다.

6,8 셀은 점수 셀이다
Select Case cells(6,8)을 통해 점수를 토대로 몇 단계인지 식별하고
그에 맞는 숫자가 나온다.
이 프로시저를 통해 난이도 조절이 가능하다.

Case 0 to 300 이라는 것은


점수가 0부터 300까지 1단계

301 부터 1000까지 2단계로 치는 것이다.

부대원들이 생각보다 쉽게 한다면 이 부분을 조정하면 된다.

중간에 cells(k,j) = 1 인지 확인하고


1이라면 isThereOne에 1을 더하는 부분이 있다.

2048 게임을 진행하다보면 1을 다 합쳐서 없을 때가 있고


아직 다 못 합쳐서 남아있는 때가 있을 것이다.
1을 다 합쳐서 없다면 더 이상 1은 나오지 않는다.
하지만 만약 1이 하나 남아있는데 나오지 않으면 안되므로
셀의 값을 확인한 후 1을 줄지 안줄지 판단한다.

isThereOne이 1이라면 1을 생성, 아니라면 상위의 숫자인 2를 생성

isThereOne에 1을 계속 더하는 이유는


하위의 숫자는 짝을 맞출 최소인 2개만 유지하기 위해서이다.

그 아래는 그대로 반복한 것이다.

마지막에 font.bold = true 는 글씨를 굵게 하는 것이다.

새로 나온 숫자를 굵게 해 시각 효과를 높였다.

Sub 위()
For a = 1 To 3 '위로 올리기
For i = 1 To 3
For j = 2 To 5
If Cells(5 - i, j) = 0 Then
Cells(5 - i, j) = Cells(6 - i, j)
Cells(6 - i, j).ClearContents
End If
Next
Next
Next

For i = 2 To 4 ' 합치기


For j = 2 To 5
If Cells(i, j) = Cells(i + 1, j) Then
Cells(6, 8) = Cells(6, 8) + Cells(i, j) ' 6,8은 점수 셀
Cells(i, j) = Cells(i, j) * 2
Cells(i + 1, j).ClearContents
End If
Next
Next

For a = 1 To 2 ' 마저 올리기


For i = 1 To 3
For j = 2 To 5
If Cells(5 - i, j) = 0 Then
Cells(5 - i, j) = Cells(6 - i, j)
Cells(6 - i, j).ClearContents
End If
Next
Next
Next
생성
색깔
End Sub

밀기 프로시저

위로 미는 프로시저이다.

a = 1 to 3은
보드판이 4x4 이므로
맨 아래에서 맨 위로 올라갈 경우도 생각해 설정했다.
만약 위가 비어있다면 쭉 쭉 올라갈 것이고
차 있다면 그냥 반복될 뿐 아무 의미 없어진다.

i가1
j가 2 일 때를 가정하면

If Cells(5 - i, j) = 0 Then
Cells(5 - i, j) = Cells(6 - i, j)
Cells(6 - i, j).ClearContents

If Cells(4, 2) = 0 Then
Cells(4, 2) = Cells(5, 2)
Cells(5, 2).ClearContents 이렇게 되는데

위에 셀이 비어있다면 해당 셀의 값을 주고 해당 셀의 값은 없앤다.

i가 2
j가 2 일 때 가정

If Cells(i, j) = Cells(i + 1, j) Then


Cells(6, 8) = Cells(6, 8) + Cells(i, j) ' 6,8은 점수 셀
Cells(i, j) = Cells(i, j) * 2
Cells(i + 1, j).ClearContents
End If

You might also like