ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TECHIT 앱 스쿨 2기: Android 22일차 (23.05.25)
    [THEC!T] 앱 스쿨2기 : Android 2023. 5. 26. 00:37
    728x90

    자료 출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 내용

     

    오늘은 미니프로젝트 틱택톡 게임을 구현해보는 것으로 시작하였습니다.

    강사님께서는 문제를 내주시고 팁을 주셨는데 일단 화면구성부터 먼저 하는 것이 일반적이고, 화면을 구성해놓고 나서 기능을 구현하면서 조금씩 수정해가는 것이 편하다고 말씀해주셨습니다.

    그래서 저도 코드 작성 시 화면을 먼저 구성해 놓고 기능들을 추가 하면서 작성하였습니다.

     

    하기는 제가 작성한 코드입니다.

    import java.lang.NumberFormatException
    import java.util.Scanner
    
    // 플레이어가 입력한 위치에 대한 정보를 저장할 이차원 배열
    val board = Array(3) { Array<String>(3, {" "}) }
    
    // 현재 토큰을 놔야하는 플레이어
    var nowPlayer = Player.PLAYER1
    
    // 플레이어 별 토큰 저장
    enum class Player(val token:String){
        PLAYER1("O"),
        PLAYER2("X")
    }
    
    // 변경한 Exception
    class CustomException : Exception()
    
    fun main(){
        while (true){
            // 게임판수를 출력하는 기능
            printCount()
            // 게임판을 출력하는 기능
            printTiTekToBoard()
            //println("printTiTekToBoard() 작동 : ${count++}")
            // 플레이어가 입력하는 정보를 받는 기능
            var input = playInfo()
            //println("var input = playInfo() 작동 : ${count++}")
            // 플레이어가 입력한 위치에 o,x 를 저장하는 기능
            inputSave(input)
            //println("inputSave(input) 작동 : ${count++}")
            // 플레이어가 우승하였는지 확인하는 기능
            // true : 우승, false : 패배
            //println("winCheck() 작동 : ${count++}")
            if(winCheck(input[0],input[1])){
                break
            }
    
            // 플레이어 변경
            //println("changePlayer() 작동 : ${count++}")
            changePlayer()
    
        }
        printTiTekToBoard()
        println("${nowPlayer.name} 승리!")
    
    }
    var count = 1
    fun printCount(){
        println("${count}번째 턴")
        count++
    }
    
    // 플레이어가 입력하는 정보를 받는 기능
    fun playInfo(): IntArray{
        val scanner = Scanner(System.`in`)
        var row = 5
        var col = 5
        while(true){
            try{
                print("${nowPlayer.name} 입력(줄,칸) : ")
                val input = scanner.next()
                row = input.split(",")[0].toInt()
                col = input.split(",")[1].toInt()
    
                // 허용 범위 내인지 확인
                if(row !in 0 .. 2 || col !in 0 .. 2){
                    throw NumberFormatException()
                }
                // 이미 놓여진 곳에 놓으려는지 확인.
                if(board[row][col] != " "){
                    throw CustomException()
                }
                // 에러가 없다면 while문 종료
                break
            }catch (e : CustomException){
                println("이미 놓여진 곳에는 말을 넣을 수 없습니다")
            }catch (e : NumberFormatException){
                println("줄과 칸의 입력 허용 범위는 0 ~ 2 까지 입니다.")
            }catch (e : Exception){
                println("1,2 혹은 2,0 등 올바른 형식으로 입력해주십시오.")
            }
        }
        return intArrayOf(row, col)
    }
    
    // 플레이어가 입력한 위치에 o,x 를 저장하는 기능
    fun inputSave(info : IntArray){
        val row = info[0]
        val col = info[1]
        board[row][col] = nowPlayer.token
    }
    
    
    val rowArray = intArrayOf(-1,-1,-1,0,0,1,1,1)
    val colArray = intArrayOf(-1,0,1,-1,1,-1,0,1)
    // 해당 플레이어가 턴을 종료하였을 때 우승하였는지 체크하는 기능
    // 기준점은 마지막에 놓은 위치로 한다.
    // 우승이라면 true, 아니라면 false를 반환한다.
    fun winCheck(row:Int,col:Int): Boolean{
        var count : Int
        for(i in 0 .. 7){
            var nextRow = row
            var nextCol = col
            count = 1
            while(true){
                nextRow += rowArray[i]
                nextCol += colArray[i]
    
                if(nextRow < 0 || nextCol < 0 || nextRow >= board.size || nextCol >= board[0].size) break
                if(board[nextRow][nextCol] != nowPlayer.token) break
                if(board[nextRow][nextCol] == nowPlayer.token) count++
                if(count == 3) break
            }
            if(count == 3) return true
        }
        return false
    }
    
    // 현재 플레이어를 바꾸는 기능
    fun changePlayer(){
        if(nowPlayer == Player.PLAYER1){
            nowPlayer = Player.PLAYER2
        } else {
            nowPlayer = Player.PLAYER1
        }
    }
    
    
    // 틱택토 게임 판 출력하는 기능
    
    fun printTiTekToBoard(){
        println("  0 1 2")
        for(i in 0 .. board.size-1){
            print("$i ")
            for(j in 0 .. board.size-1){
                print(board[i][j])
                if(j != board.size-1) print("|")
                else println()
            }
            if(i != 2) println("  -+-+-")
        }
        println()
    
    }

     

    저의 경우 상기와 같이 함수들을 호출하는 식으로 코드를 작성하였었습니다.

    하지만 강사님은 클래스를 생성하여 변수를 통해 함수를 호출하는 방식으로 작성하셨었습니다.

    그리고 생각을 해보니 추후 코드량이 많아 진다면, 함수를 호출하는 식으로 코드를 작성하면 나중에는 해당 함수가 어디에 쓰이는 것인지 명확하게 확인하기 어려울 것 같다는 생각이 들어 앞으로 코드를 작성할 때 왠만하면 클래스를 이용하여 작성하는 버릇을 좀 들여야 겠다라는 생각을 하였으며, 만약 헷갈린다면 기존과 같이 함수로 작성한 다음 클래스로 묶어주는 작업을 하면서 익숙해 져야 겠다는 대비책도 같이 생각하였습니다.

     

    그리고 이후에는 또 다른 문제를 내주셨는데 어제 배운 입출력 스트림 중 이어쓰고 이어읽는 기능을 사용해야 되는 부분이 있었으나, 어제 예습등을 미리 하여서 이어쓰고, 이어서 읽는 부분은 문제 없이 원활하게 작성할 수 있었습니다. 

    그 외의 문제들 중 날짜와 중복데이터 처리가 있었으나 기존에 알고 있는 방법들이 있어 이 또한 큰 문제 없이 원활하게 작성하였습니다.

     

    마무리

    문제를 풀면서 느낀 점은 정말 복습이나 예습을 안했다면 어려울만한 문제를 잘 내주신다라는 생각과 비전공자 혹은 알고리즘 문제등을 별로 안풀어본 사람이라면 어렵게 느낄 수 있을 것 같다는 느낌을 받았습니다. 근데 최소한 제가 속한 조원분들은 속도차이는 조금 있었지만 모두 각자 코드를 완성하셨습니다.  그래서 저는 다른 분들은 코드를 어떻게 작성하셨는지 궁금하여 서로 작성한 코드를 리뷰하는 시간을 가져보자라고 의견을 제시하였는데 조원분들 모두 흔쾌히 수락해주셔서 다행이라고 생각하였습니다. 하지만 각자 작성한 코드를 리뷰하기에는 시간이 얼마 남지 않아 내일 오전에 조원분들과 같이 코드를 리뷰하기로 하였습니다. 사실 강의를 들으면서 조별과제를 할 때를 제외하고 제가 작성한 코드와 강사님이 작성한 코드만 보았었기에 기대가 됩니다

     

    오늘의 마음가짐

    다른사람들의 코드를 많이 읽고 작성하고 수정하는 과정등을 통해 다양한 스타일들을 익혀 코드 스타일 수용력이 높은 개발자가 되자

Designed by Tistory.