본문 바로가기
TechNical/WMI

[HTA] 뱀 게임

by 강멍멍이 2020. 2. 23.
반응형

이건 좀 간단한 뱀 게임이다.

조작방법은 숫자키거나 AWSD 키다.

빨간색을 사과라고 생각하고 먹으면 꼬리가 길어진다.

알다시피 벽에 머리 박으면 끝나는 거다.

뱀 방향 전환 할 때 각각 꺽어지는 부분 알고리즘에 시간 좀 들어 갔다.

몸땡이를 어레이에 담고 다니면서 방향을 기록해 두는 방식으로 극뽁

그거 외에는 딱히 어려운 부분은 없었다.

시간이 지나면서 아주조금씩 빨라지긴 하는데.. 몸땡이가 길어 지면 느려도 어렵더라...

사실 VBScript 문법을 잘 몰라서 그런는데... 배열을 복사 할 때 오류가 나는데 왜 나는지 모르겠다.

 

[Snake.hta]

<html>
    <meta charset="euc-kr">
    <head>
        <title>Snake</title>
        <HTA:APPLICATION 
         ID="강멍멍이"
         APPLICATIONNAME="Snake"
         SCROLL="no"
         SINGLEINSTANCE="yes"
         WINDOWSTATE="normal"
        />
        
        <style>
            BODY {
                font-size:9pt;
                font-family:돋움체;
            }
            
            TABLE, TR, TD {
                font-size:1pt;
                text-indent:-10000px;
                border:1px solid black;
                border-collapse:collapse;
            }            
            
            .hide {
                opacity : 0;
                transition: opacity 1s linear;
                -webkit-transition: opacity 1s linear;
            }
        </style>
     
        <script language="VBScript">
            Dim interval, levelCnt, levelCntMax , intervalMinus, viewLevel
            
            Dim intRow, intCol
            Dim rowBound, colBound
            Dim aniXDir, aniYDir
            
            Dim snakeArr()
            Dim snakeArrBackup()
            Dim turnDir
            Dim rollPoint
            
            Dim endGameYn
            Dim scoreCnt
            
            Dim timerID
            Dim animateTimerID
            
            Dim colorArr
            Dim snakeColor
            
            Sub Window_OnLoad
                window.resizeTo 300, 350
                window.moveTo 1200, 350
                
                colorArr = Array("e2edff", "teal", "aqua", "salmon", "darkkhaki", "darkred", "plum", "lime", "black", "gray")

                rowBound = CInt(labRow.innerHTML)
                colBound = CInt(labCol.innerHTML)
                
                For nRow = 1 To rowBound
                    Set tblRow = mainTbl.insertRow()

                    For nCell = 1 To colBound
                        Set tblCell = tblRow.insertCell()
                        tblCell.style.width = 10
                        tblCell.style.height = 10
                        tblCell.style.backgroundcolor = "#ffffff"
                        tblCell.innerHtml= "0"
                    Next
                Next
                
                aniXDir = 0
                aniYDir = 0
                animateTimerID = window.setTimeOut("animate", 500)
                                
            End Sub
            
            Sub startGame
                document.body.focus()   '시작버튼에 있는 포커스 제거
                window.clearTimeOut(animateTimerID)
                                
                levelCntMax = 100
                intervalMinus = 10
                                
                interval = 300
                levelCnt = 1
                viewLevel = 1
                scoreCnt = 0
                endGameYn = "N"
                snakeColor = 111115
                
                intRow = CInt(rowBound / 2) - 2
                intCol = CInt(colBound / 2)
                
                labLevelCnt.innerHTML = viewLevel                

                For nRow = 0 To rowBound - 1
                    For nCell = 0 To colBound - 1
                        mainTbl.Rows(nRow).Cells(nCell).innerHtml = 0
                        mainTbl.Rows(nRow).Cells(nCell).style.backgroundcolor = "white"
                    Next
                Next                
                                
                ReDim snakeArr(5,4)

                For nRow = 0 To UBound(snakeArr)
                    snakeColor = snakeColor + 1
                    snakeArr(nRow, 0) = intRow + nRow
                    snakeArr(nRow, 1) = intCol
                    snakeArr(nRow, 2) = 1       '방향
                    snakeArr(nRow, 3) = 0       '이동대상여부
                    snakeArr(nRow, 4) = CStr(snakeColor)       '블럭 색상
                Next
                
                snakeArr(0,3) = 1   '이동대상여부                                
                                                                                               
                '뱀 몸땡이 기본
                For i = 0 To UBound(snakeArr)
                    mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).innerHtml = 1
                    mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).style.backgroundcolor = Cstr(snakeArr(i, 4))
                    'mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).style.backgroundcolor = Cstr(snakeColor)
                Next
                
                Call makeApple
                Call makeApple
                Call makeApple
                                
                snakeArr(0, 2) = 1  '최초 위로 이동

                timerID = window.setTimeOut("moveSnake", interval)
                
            End Sub

            Sub moveSnake
                Call chkEnd(snakeArr(0,2))
                
                If endGameYn = "Y" Then
                    Exit Sub
                End If
            
                levelCnt = levelCnt + 1
                
                If levelCnt > levelCntMax Then
                    interval = interval - intervalMinus
                    levelCnt = 1
                    
                    viewLevel = viewLevel + 1
                    labLevelCnt.innerHTML = viewLevel
                End If
                
                posChg = "N"
                eatAppleYn = "N"
                snakeDir = snakeArr(0, 2)
                
                For i = 0 To UBound(snakeArr)
                    '현재 위치는 지운다.
                    mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).innerHtml = 0
                    mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).style.backgroundcolor = "white"
                    
                    '사과를 먹었으면 현재 꼬리를 추가될 꼬리의 포지션으로 한다.
                    If eatAppleYn = "Y" And i = UBound(snakeArr) Then
                        paramRow = snakeArr(i, 0) 
                        paramCol = snakeArr(i, 1) 
                        paramDir = snakeArr(i, 2)
                    End If                    
                    
                    snakeDir = snakeArr(i, 2)

                    If snakeDir = 1 Then        '상
                        snakeArr(i, 0) = snakeArr(i, 0) - 1
                        snakeArr(i, 1) = snakeArr(i, 1)
                    ElseIf snakeDir = 2 Then    '하
                        snakeArr(i, 0) = snakeArr(i, 0) + 1
                        snakeArr(i, 1) = snakeArr(i, 1)
                    ElseIf snakeDir = 3 Then    '좌
                        snakeArr(i, 0) = snakeArr(i, 0)
                        snakeArr(i, 1) = snakeArr(i, 1) - 1
                    ElseIf snakeDir = 4 Then    '우
                        snakeArr(i, 0) = snakeArr(i, 0)
                        snakeArr(i, 1) = snakeArr(i, 1) + 1
                    End If
                                        
                    '사과를 먹으면 꼬리를 1칸 늘여야 한다.
                    If mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).innerHtml = 2 Then
                        eatAppleYn = "Y"
                    End If                    
                    
                    '이동 할 위치를 찍는다.
                    mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).innerHtml = 1
                    mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).style.backgroundcolor = Cstr(snakeArr(i, 4))
                    'mainTbl.Rows(snakeArr(i, 0)).Cells(snakeArr(i, 1)).style.backgroundcolor = Cstr(snakeColor)
                    
                Next
                
                '역순으로 이전 블럭의 이동 방향을 가져 온다.
                For i = UBound(snakeArr) To 1 Step - 1
                    snakeArr(i, 2) = snakeArr(i - 1, 2) '이전 블럭의 이동 방향을 받아서 다음에 움직일때 적용 한다.
                Next
                
                '사과를 먹었으면 꼬리를 추가한다.
                If eatAppleYn = "Y" Then
                    Call eatApple(paramRow, paramCol, paramDir)
                End If
                
                window.clearTimeOut(animateTimerID)
                timerID = window.setTimeOut("moveSnake", interval)
                    
            End Sub
            
            Sub makeApple
                '사과 위치
                makeDone = "N"
                Do While makeDone = "N"
                    Randomize                
                    rndRow = Int(rowBound * Rnd)
                    rndCol = Int(colBound * Rnd)  
                    
                    '뱀은 피해서 만든다.
                    If mainTbl.Rows(rndRow).Cells(rndCol).innerHtml = 0 Then
                        mainTbl.Rows(rndRow).Cells(rndCol).innerHtml = 2
                        mainTbl.Rows(rndRow).Cells(rndCol).style.backgroundcolor = "red"
                        makeDone = "Y"
                    End If
                Loop                
            End Sub
            
            Sub eatApple(paramRow, paramCol, paramDir)
                '원본 어레이 백업
                ReDim snakeArrBackup(UBound(snakeArr), 4)
                
                '어레이 복사 중에 오류가 나는데 왜 나는지 모르겠다.
                On Error Resume Next    
                For nRow = 0 To UBound(snakeArr)
                    For nCol = 0 To 4
                        'If Err.Number <> 0 Then
                        '    msgBox nRow & " " & nCol
                        'End If
                        snakeArrBackup(nRow, nCol) = snakeArr(nRow, nCol)
                    Next                    
                Next
                                
                '뱀 재생성
                ReDim snakeArr(UBound(snakeArr) + 1, 4)
                For nRow = 0 To UBound(snakeArrBackup)
                    For nCol = 0 To 4
                        snakeArr(nRow, nCol) = snakeArrBackup(nRow, nCol)
                    Next
                Next
                
                'msgbox snakeArr(snakeSize - 1, 0) & " " & snakeArr(snakeSize - 1, 1)
                
                '꼬리 추가
                snakeColor = snakeColor + 1
                snakeArr(UBound(snakeArr), 0) = paramRow
                snakeArr(UBound(snakeArr), 1) = paramCol
                snakeArr(UBound(snakeArr), 2) = paramDir
                snakeArr(UBound(snakeArr), 3) = 0
                snakeArr(UBound(snakeArr), 4) = snakeColor
                
                scoreCnt = scoreCnt + 1
                labScore.innerHTML = scoreCnt
                
                Call makeApple
                
            End Sub
            
            Sub chkEnd(moveDir)
                If moveDir = 1 Then        '상
                    chkRowPos = snakeArr(i, 0) - 1
                    chkColPos = snakeArr(i, 1)
                ElseIf moveDir = 2 Then    '하
                    chkRowPos = snakeArr(i, 0) + 1
                    chkColPos = snakeArr(i, 1)
                ElseIf moveDir = 3 Then    '좌
                    chkRowPos = snakeArr(i, 0)
                    chkColPos = snakeArr(i, 1) - 1
                ElseIf moveDir = 4 Then    '우
                    chkRowPos = snakeArr(i, 0)
                    chkColPos = snakeArr(i, 1) + 1
                End If
                
                If chkRowPos < 0 Or chkRowPos >= rowBound Or chkColPos < 0 Or chkColPos >= colBound Then
                    endGameYn = "Y"
                    MsgBox "G a m e   O v e r ! !"
                    animateTimerID = window.setTimeOut("animate", 500)
                    Exit Sub
                End If
                
                '바운더리가 넘어 가기때문에 따로 끝내야 한다
                '돌다가 자기 몸땡이에 부딪히면 끝이다.
                If mainTbl.Rows(chkRowPos).Cells(chkColPos).innerHtml = 1 Then
                    endGameYn = "Y"
                    MsgBox "G a m e   O v e r ! !"
                    animateTimerID = window.setTimeOut("animate", 500)
                    Exit Sub
                End If
            End Sub

            Sub moveUp
                '반대반향으로는 선회 못 한다.
                If snakeArr(0,2) = 2 Then
                    Exit Sub
                End If
                
                Call chkEnd(1)
                snakeArr(0,2) = 1   '방향
                snakeArr(0,3) = 1   '이동대상여부
            End Sub
                            
            Sub moveDown
                '반대반향으로는 선회 못 한다.
                If snakeArr(0,2) = 1 Then
                    Exit Sub
                End If
                            
                Call chkEnd(2)
                snakeArr(0,2) = 2   '방향
                snakeArr(0,3) = 1   '이동대상여부           
            End Sub
            
            Sub moveLeft     
                '반대반향으로는 선회 못 한다.
                If snakeArr(0,2) = 4 Then
                    Exit Sub
                End If
                            
                Call chkEnd(3)           
                snakeArr(0,2) = 3   '방향
                snakeArr(0,3) = 1   '이동대상여부
            End Sub            

            Sub moveRight
                '반대반향으로는 선회 못 한다.
                If snakeArr(0,2) = 3 Then
                    Exit Sub
                End If
                            
                Call chkEnd(4)
                snakeArr(0,2) = 4   '방향
                snakeArr(0,3) = 1   '이동대상여부
            End Sub            
            
            Sub chekKeyPress
                
                'msgbox window.event.Keycode    '키 값을 알고 싶다면?
                
                If endGame <> "Y" Then
                    IF (window.event.Keycode = 119 Or window.event.Keycode = 56) THEN    'w키, 상
                        Call moveUp
                    END IF
    
                    IF (window.event.Keycode = 115 Or window.event.Keycode = 53) THEN    's키, 하
                        Call moveDown
                    END IF
                                    
                    IF (window.event.Keycode = 97 Or window.event.Keycode = 52) THEN    ' a키, 좌
                        Call moveLeft
                    END IF
    
                    IF (window.event.Keycode = 100 Or window.event.Keycode = 54) THEN    'd키, 우
                        Call moveRight
                    END IF

                    'IF (window.event.Keycode = 32) THEN    '스페이스키, 파이어!
                    '    Call fireBlock
                    'END IF

                    IF (window.event.Keycode = 27) THEN    'ESC 중지/시작
                        MsgBox "일시중지!!"
                    END IF
                End If
            End Sub
            
            Sub animate
                Randomize                
                aniDir = Int(2 * Rnd)
                
                If aniDir = 0 Then
                    If aniXDir = 0 Then
                        intRow = intRow + 1
                    Else
                        intRow = intRow - 1
                    End If                
            
                    If intRow = colBound -1 Then
                        aniXDir = 1
                    End If
    
                    If intRow = 0 Then
                        aniXDir = 0
                    End If
                End If

                Randomize                
                aniDir = Int(2 * Rnd)

                If aniDir = 0 Then
                    If aniYDir = 0 Then
                        intCol = intCol + 1
                    Else
                        intCol = intCol - 1
                    End If
                
                    If intCol = rowBound - 1 Then
                        aniYDir = 1
                    End If
    
                    If intCol = 0 Then
                        aniYDir = 0
                    End If
                End If
                
                On Error Resume Next
                Randomize                
                aniColor = Int(10 * Rnd)
                mainTbl.Rows(intRow).Cells(intCol).style.backgroundcolor = colorArr(aniColor)
                window.clearTimeOut(animateTimerID)
                animateTimerID = window.setTimeOut("animate", 100)
            End Sub
                        
        </script>
    </head>        
    
    <body onKeyPress="chekKeyPress">
        <button onClick="startGame" style="width:35px;height:20px">Start</button>
        [Row:<label id="labRow">15</label>
        Col:<label id="labCol">15</label>]
        lv:<label id="labLevelCnt">1</label>
        Sc:<label id="labScore">0</label>
        <br>
        <div style="float:left;width:100%;height:95%;margin:3px;">
            <table id="mainTbl" style="width:100%;height:100%"></table>
        </div>
    </body>
</html>
반응형

댓글