본문 바로가기
스파르타 내배캠

스파르타 내배캠 Unity 3기 15일차

by LemongO 2024. 1. 12.

주말! 주말! 주말! 주말!

 

 

 

요새 날짜 감각이 없다... 지만 금요일은 못 참지 ㅋㅋ

 

 

오늘은 내가 한게 아니라 팀원분께서 작성하신 코드를 너무 유용하게 썻는데,

쓰다보니 줄이고 줄이고 또 줄이고 싶은 부분이 있어 그 부분을 짚어보도록 하자.

 


 

이걸 뭐라 부르는지 모르겠다... 찾아봐도 잘 모르겠다...

리팩토링? 추상화? 용어가 있었던거 같은데...

 

 

주 기능은 기존의 중복코드를 하나의 코드로 만들었고 그것을 정적메서드로 만들어 두셨다는 것이다.

internal class UI
{
    #region UserInput
    /// <summary>
    /// 경고문과 함께 사용자에게 입력을 받는 UI를 표시하고, 사용자가 입력한 값을 반환합니다.
    /// </summary>
    /// <param name="alert">표시할 경고문입니다. 기본값은 빈 문자열입니다.</param>
    /// <param name="positive">경고문의 성격이 긍정적인지 나타냅니다. 기본값은 false입니다.</param>
    /// <returns>사용자로부터 입력받은 문자열을 반환합니다.</returns>
    public static string UserInput(string alert="", bool positive=false, string reqMsg= "다음 행동을 입력하세요.")
    {
        Console.WriteLine("");
        Console.WriteLine(".──────────────────────────────────────────────────────────────────── .");
        Console.WriteLine($"  {reqMsg}");
        Console.WriteLine("");
        Console.WriteLine(""); Console.ForegroundColor = (positive)?ConsoleColor.Green:ConsoleColor.Red;
        Console.WriteLine($"  {alert}"); Console.ResetColor();
        Console.WriteLine("  >>>"); 
        Console.WriteLine("'──────────────────────────────────────────────────────────────────── '");
        Console.SetCursorPosition(6, Console.CursorTop-2);
        return Console.ReadLine();
    }
    #endregion


    public static void ColoredWriteLine(string s, ConsoleColor color)
    {
        Console.ForegroundColor = color;
        Console.WriteLine(s);
        Console.ResetColor();
    }
}

 

콘솔 RPG 에서 그래도 그럴싸한 UI가 필요했고 이를 구현하기 위해

Console.WriteLine과 ConsoleForegroundColor 가 아주 많이 쓰였다.

 

유저의 입력을 받는 곳도 중복되는곳이 매우 많고, 컬러를 입혀야 하는 구간도 아주 많았다.

우리 팀에서 구현 한 것처럼 하나의 클래스에서 모든 씬을 드나드는 경우, 해당 기능을 쓰다보면 수백줄을 넘어 수천줄이 됐을지도 모를것이다.

 

하지만 위 코드처럼 중복 사용되는 코드를 하나로 묶어 유틸리티를 만들어 주셨다는것이고 이를 실제로 사용해 보았다.

 

private bool TryRun(Monster[] monsters)
{
    for (int i = 0; i < 3; i++)
    {
        Console.Write(".");
        Thread.Sleep(500);
    }

    int randRun = new Random().Next(0, 10);
    if (randRun < 6)
    {
        UI.ColoredWriteLine("\n스파르타 교육을 뿌리칠 수 없었습니다... [몬스터의 턴으로 넘어갑니다]", ConsoleColor.DarkRed);
        UI.UserInput(reqMsg: "아무 키나 입력해주세요.");
        MonsterPhase(monsters);
    }
    else
    {
        UI.ColoredWriteLine("\n뒤도 돌아보지 않고 도망쳤습니다. [잠시 후 던전입구에 도착합니다]",ConsoleColor.Green);
        UI.UserInput(reqMsg: "아무 키나 입력해주세요.");
        return true;
    }                
    return false;                            
}

 

전투 장면에서 도망을 치는 부분이다.

도망을 칠 때, 확률적으로 도망에 성공 / 실패를 하는데 각각의 메세지를 출력해야했다.

기존의 방식대로였다면 콘솔에 메세지를 출력하는데만 조건당 10줄 이상이 들었을 것이다.

하지만 단 2줄로 줄일 수 있었다.

 

 

사진처럼 같은 기능이지만 유틸성없이 그냥 코딩을 하면 매우 길어졌을 것이다.

 

 

참고로 주목해야 할 것이 UserInput 메서드이다.

public static string UserInput(string alert="", bool positive=false, string reqMsg= "다음 행동을 입력하세요.")

 

세 가지 매개변수를 받으며(string, bool, string) 각각이 기본값을 가지고있다.

만약 기본값을 가지고있지 않은 일반 매개변수였다면, 함수 호출시 매개변수 없이 사용이 불가능 했을 것이다.

하지만 기본값을 가지고 있기 때문에 그냥 사용해도 된다.

다만 여기서 커스터마이징이 자주 일어날 수 있는 부분이 세번째 매개변수인 string reqMsg 이다.

 

기본값을 가지고있는 매개변수라도 함수 사용시 차례대로 인식이 된다.

다음과 같이 말이다.

UI.UserInput("", false, "아무 키나 입력해주세요.");

 

하지만 세번째 매개변수만 기본값이 아닌 값으로 쓰고 싶다면 다음과 같이 쓸 수 있다.

UI.UserInput(reqMsg: "아무 키나 입력해주세요.");

 

그리고 쓰다보니 UI 부분도 없애버리고 싶어졌다.

그래서 찾아본 결과 using 선언을 해주면 된다고 한다.

using static RtanTextDungeon.UI;

 

우리의 모든 클래스들은 RtanTextDungeon 네임스페이스 안에 있으므로 위와 같이 선언하면 UI 조차 생략할 수 있다.

using static RtanTextDungeon.Define;

internal class Dungeon
{
    private bool TryRun(Monster[] monsters)
    {        
        ColoredWriteLine("\n스파르타 교육을 뿌리칠 수 없었습니다... [몬스터의 턴으로 넘어갑니다]", ConsoleColor.DarkRed);
        UserInput(reqMsg: "아무 키나 입력해주세요.");
              
        return false;                            
    }
}

 

 

다만 무작정 줄이는것은 가독성이 떨어질 우려가 있긴하다. 실제 코드에선 UI조차 줄이진 않았다.