카테고리 없음

2024-04-24 [Kotlin 간단한 RPG Game 만들기]

Glen_check 2024. 4. 25. 00:05

[스파르타코딩클럽 Kotlin 문법 종합반] 강의 2주차 과제로 사실 강의를 들은 걸로만 해당 과제를 풀기에는 꽤나 어려움이 컸다.

해당 과제가 기본기를 다지고 금주 과제 [간단한 계산기 만들기] 를 할 때 큰 도움이 될 것으로 보여 꽤 여러 번 반복 학습하였다.

 

Level 1 문제 설명

사용자에게 메뉴를 입력 받아 각 메뉴에 해당하는 기능을 실행시켜주세요.

프로그램을 실행하면 화면에 메뉴를 입력해주세요 라는 문구와 함께 선택할 수 있는 메뉴가 출력됩니다.

 

  • 게임 시작하기 메뉴
    • 게임이 시작되었습니다라는 문구가 화면에 출력됩니다.
  • 게임 끝내기 메뉴
    • 게임이 종료되었습니다라는 문구가 화면에 출력됩니다.

 

Level 1 문제 풀이

프로그램이 시작되면 메뉴를 입력하라는 문구와 함께 유저가 선택할 수 있는 옵션 Game Start / End The Game 두 가지를 보여주고,

둘 중 뭘 선택하는지에 따라 게임이 시작되었습니다 / 게임이 종료되었습니다 문구를 화면에 출력하면 됩니다.

 

* when 문을 사용하여 유저가 어떤 옵션을 선택하는지에 따라 어떤 문구를 출력할지 결정하는 것이 이번 단계에 포인트인데요,

작성한 코드는 아래와 같습니다.

package org.example

fun main() {
    println("메뉴를 입력해주세요.")
    println("1.Game Start / 2.End The Game")

    val selectedMenu = readLine()!!.toInt()

    when(selectedMenu) {
        1 -> println("게임이 시작되었습니다.")
        2 -> println("게임이 종료되었습니다.")
    }
}

 

코드를 간단히 리뷰하자면

selectedMenu를 변수로 저장하여 readline()을 활용 사용자에게 번호를 입력받고, 번호에 따라 알맞은 문구를 출력하도록 작성해보았습니다.

 

여기서 readline()을 짚고 넘어가자면

readline()의 경우 기본적으로 String Type으로 반환하도록 설정되어 있어, .toInt를 붙여 Int Type으로 반환될 수 있도록 설정하였으며,

readline() 뒤 바로 붙는 '!!' 의 경우 단언 연산자로 변수가 null이 아님을 확신할 수 있을 경우 사용할 수 있습니다.

 

when 문에서 selectedMenu를 확인하고,

만약 유저가 1을 입력했다면 게임이 시작되었습니다 문구를 출력, 2를 입력했다면 게임이 종료되었습니다 문구가 출력되는 것을 확인할 수 있었습니다.

 

 

Level 2 문제 설명

캐릭터 추가, 캐릭터 목록 출력 메뉴를 추가해주세요.

  • 캐릭터 추가 메뉴
    • 캐릭터는 이름과 직업을 가집니다.
    • 사용자로부터 추가할 캐릭터의 이름과 직업을 입력 받습니다.
    • 입력받은 캐릭터를 저장합니다.
  • 캐릭터 목록 출력 메뉴
    • 프로그램을 실행한 이후로 추가한 캐릭터 목록을 출력합니다.

 

Level 2 문제 풀이

캐릭터를 추가할 수 있는 옵션을 추가 해야하며

캐릭터 하나를 추가한 후 유저는 '다시 한번 캐릭터를 추가할지' / '캐릭터 추가를 그만할지' 두가지 옵션을 갖습니다.

캐릭터를 다시 추가할 경우 위의 패턴이 다시 반복되며, 캐릭터 추가를 멈출 경우 캐릭터 목록을 출력하여 유저에게 보여주면 됩니다.

 

강의에서 제시해주는 힌트로

캐릭터의 이름, 직업에 대한 정보를 함께 담으려면 Map 형태로 저장해야 하며

지금까지 추가한 여러개의 캐릭터를 가지고 있으려면 List 형태로 저장할 수 있어야합니다.

 

문제를 풀다 캐릭터 추가 결정에 따라 반복문을 돌리는 방식이 헷갈려 지속적으로 오류가 발생했고,

해설을 보고 이해한 내용을 자세히 풀어 보았습니다.. 너무 어렵습니다.. 흙흙

 

fun main() {
    println("메뉴를 입력해주세요.")
    println("1.Game Start / 2.Create New Character / 3.End The Game")

    val selectedMenu = readLine()!!.toInt()

    when(selectedMenu) {
        1 -> startGame()
        2 -> createCharacter()
        3 -> endGame()
    }
}

fun startGame() {
    println("게임이 시작되었습니다")
}

fun createCharacter() {
    val characterList: MutableList<Map<String, String>> = mutableListOf()

    var isNeedMoreCharacter = "Y"

    while (isNeedMoreCharacter == "Y") {
        println("추가할 캐릭터의 이름을 입력해주세요.")
        val name = readLine() ?: ""

        println("추가할 캐릭터의 직업을 입력해주세요.")
        val job = readLine() ?: ""

        val character = mapOf("name" to name, "job" to job)

        characterList.add(character)

        println("사용자를 더 추가하시겠습니까? (Y: 추가, N: 그만두기)")
        isNeedMoreCharacter = readLine() ?: "N"
    }

    characterList.forEach {
        println(it)
    }
}

fun endGame() {
    println("게임이 종료되었습니다")
}

 

1. Creat New Character 선택 옵션을 2번에 추가해 주었고 when문에서 문구를 출력하도록 설정하는 것이 아닌,

각 함수로 만들어 선택 옵션마다 원하는 함수가 실행될 수 있도록 설정하였는데요.

 

함수로 설정한 것은 코드 작성의 확장성이나 추후 유지 보수에 용이성 때문인데,

예시로 추후 startGame() 내 추가 로직이 필요할 경우 추가 구성하기 편하고, 코드를 이해하는데 또한 용이합니다.

 

2. creatCharacter() 함수 관련 순차적으로 자세히 풀어보자면

fun createCharacter() {
		println("추가할 캐릭터의 이름을 입력해주세요.")
        val name = readLine()

        println("추가할 캐릭터의 직업을 입력해주세요.")
        val job = readLine()
        
        val character = mapOf("name" to name, "job" to job)
}

추가할 캐릭터의 이름을 입력하라는 문구를 출력, name 이라는 변수에 사용자에게 입력받은 값을 저장하고

추가할 캐릭터의 직업을 입력하라는 문구를 출력, job 이라는 변수에 사용자에게 입력받은 값을 저장합니다.

 

그리고 map 자료 구조를 만들어 입력받은 이름과 직업 정보를 character 변수에 저장할 수 있도록 만들어 줍니다.

 

fun createCharacter() {

		val characterList: MutableList<Map<String, String>> = mutableListOf()

		println("추가할 캐릭터의 이름을 입력해주세요.")
        val name = readLine() ?: ""

        println("추가할 캐릭터의 직업을 입력해주세요.")
        val job = readLine() ?: ""
        
        val character = mapOf("name" to name, "job" to job)
        
        characterList.add(character)
}

character를 추가할 list를 만들어줘야 하는데,

character list의 경우 지속적으로 추가되니 그냥 list가 아닌, mutablelist로 작성해줍니다.

list는 타입을 별도로 지정해줘야 하는데, list에서는 동일한 타입 하나만 넣을 수 있고,

변수에 타입을 지정해 줄건데, 변수는 MutableList 타입이어야 하고

안에는 map이 들어가야 하고, map도 어떤 타입인지 함께 작성해주어야 합니다.

키와 값 모두 String이니 String으로 저장해야 합니다.

 

해당 문법이 다소 어려워 지속적으로 적어보면서 연습을 해야겠네요 ..

 

characterList 안 character를 지속적으로 추가해 줄 코드를 characterList.add(character)로 추가해주고,

사용자에게 입력받는 값이 null일 경우를 대비하여 elvis 연산자를 사용 변수가 null일 경우 대신 사용할 값을 지정합니다.

?: 뒤에는 null이 발생할 경우 어떤 값으로 반환할지 기재해주면 되는데 empty String으로 반환해줄거기 때문에 다음과 같이 코드를 작성해줍니다.

 

fun createCharacter() {
    val characterList: MutableList<Map<String, String>> = mutableListOf()

    var isNeedMoreCharacter = "Y"

    while (isNeedMoreCharacter == "Y") {
        println("추가할 캐릭터의 이름을 입력해주세요.")
        val name = readLine() ?: ""

        println("추가할 캐릭터의 직업을 입력해주세요.")
        val job = readLine() ?: ""

        val character = mapOf("name" to name, "job" to job)

        characterList.add(character)

        println("사용자를 더 추가하시겠습니까? (Y: 추가, N: 그만두기)")
        isNeedMoreCharacter = readLine() ?: "N"
    }

    characterList.forEach {
        println(it)
    }
}

isNeedMoreCharacter는 변할 수 있는 변수로 저장, boolean으로 반환하는 변수는 is~로 변수명을 짓는 경우가 많아 다음과 같이 변수명을 결정하였습니다.

 

캐릭터를 지속적으로 추가할 경우 여러번 계속해서 해당과정을 반복해야 하니 while 문을 사용하였으며,

"N" 일 경우 반복하는 것을 깨고 캐릭터 리스트를 출력 후 끝이 납니다.

 

 

 

* Level3은 글이 다소 길어져, 이어서 작성하여 밑에 링크를 첨부하겠습니다.

자세히 복습하고 싶어 다소 글이 길어지는 부분이 있으나 글을 써보면서 확실히 이해가 되고 다시 한번 복기해볼 수 있어 참 좋은 것 같습니다 ..