내일배움캠프 Unity 12일차 TIL - 개인과제 코드 피드백

Wooooo·2023년 11월 14일
0

내일배움캠프Unity

목록 보기
14/94

오늘의 키워드

오늘은 내일배움캠프 프로그래밍 기본주차의 개인 과제인 Sparta Dungeon의 튜터님들의 코드 리뷰가 있었다. 내가 받은 피드백을 갈무리하고, 어떤 점을 보완해하면 좋을지 정리해보기로 했다.

git repository : https://github.com/jyWooooo/SpartaDungeon


피드백

내가 받은 피드백을 정리해보면,

  • 구현과 코드 가독성에서는 좋은 평가를 받았으나, 예외처리가 부족함.
  • 중복된 코드를 줄이기 위해 리팩토링을 해보면 좋은 경험이 될 것.
  • git 사용에 신경을 쓸 것.
    • 커밋 메시지 구체적으로 쓸 것.
    • 기능별로 분리하여 조금씩 커밋하는 습관 가질 것.
    • README.md 작성해서 프로그램의 개요와 구조 설명해보기.

프로젝트 수정사항

  • 사용자 입력 부분
    • 사용자가 유효하지 않은 입력을 하면 예외처리
      • 현 상황에서도 에러가 발생하지는 않으나, 알림 메시지가 따로 존재하지 않음.
        따라서 사용자에게 유효하지 않은 입력을 유도하는 알림 메시지를 추가할 것.
  • 파일 입출력 부분
    • 불러오기 예외처리
      • 세이브 파일이 없는 경우
      • 세이브 파일이 깨진 경우
        • 파일은 있으나, 내용이 비어있는 경우
        • JSON에 잘못된 값이 들어있는 경우
        • JSON으로 변환할 수 없는 경우
    • AES 복호화 예외처리
      • 복호화된 파일이 수정돼 정상적으로 복호화 할 수 없는 경우
  • 리팩토링
    • 씬 드로우 부분
      • Dungeon씬과 Battle씬 분리
    • 사용자 입력 부분
      • 씬마다 비슷한 로직으로 사용 중이므로, 메서드로 묶어서 재사용성 높이기
      • 예외처리를 메서드 안에서 처리할 수 있게 정리

사용자 입력 부분 수정

        /// <summary>
        /// 매개변수로 지정한 범위 내의 사용자 입력을 받습니다. 범위 외의 입력은 예외처리됩니다.
        /// </summary>
        /// <param name="binaryBoolArray"> 비트 연산을 수행하여 범위 내의 입력인지 판단합니다.
        /// <br> 가장 오른쪽부터 0번 키, 가장 왼쪽이 9번 키입니다.</br>
        /// </param>
        static int InputKey(int binaryBoolArray = 0b0000000001)
        {
            do
            {
                int? res;
                var key = Console.ReadKey(true).Key;
                if (ConsoleKey.D0 <= key && key <= ConsoleKey.D9)
                    res = key - ConsoleKey.D0;
                else if (ConsoleKey.NumPad0 <= key && key <= ConsoleKey.NumPad9)
                    res = key - ConsoleKey.NumPad0;
                else res = null;

                if (res.HasValue)
                {
                    int checker = 1 << res.Value;
                    if ((checker & binaryBoolArray) != 0)
                        return res.Value;
                }
                int cursorLeft = Console.CursorLeft;
                int cursorTop = Console.CursorTop;
                InputExceptionMessage(cursorLeft, cursorTop, "유효하지 않은 입력입니다.");
            } while (true);
        }

        static void InputExceptionMessage(int cursorLeft, int cursorTop, string message, int clearLineCount = 1)
        {

            Console.WriteLine(message);
            Console.ReadKey(true);
            Console.SetCursorPosition(cursorLeft, cursorTop);
            for (int i = 0; i < clearLineCount; i++)
                Console.WriteLine("                         ");
            Console.SetCursorPosition(cursorLeft, cursorTop);
        }

InputKey()가 호출되면 유효한 입력이 들어올 때까지 무한 루프를 돌게 했다.
while문 안에서 입력된 키가 숫자인지, 숫자라면 매개변수로 지정한 키와 and 연산하여 숫자 중에서도 선택지가 있는 숫자인지 판단하여 return하도록 했다.

만약 유효하지 않은 입력이 들어오면, 현재의 Console의 커서위치를 받아와서 그 위치에 안내 메시지를 출력해주는 InputExceptionMessage()도 작성했다.


파일 입출력 부분

try catch 문을 처음 써봤다 (...)
그래서 그런지 많이 조악하다. 부끄럽다.
여태까진 if문으로만 예외처리를 해왔는데, 앞으로는 많이 써봐야겠다.

        public static Character LoadPlayerData()
        {
            Character res = null;
            try
            {
                //var josnStr = File.ReadAllText(@"PlayerData.json");
                var josnStr = AESManager.Decrypt(File.ReadAllText(@"PlayerData.json"));
                var jobject = JsonConvert.DeserializeObject<JObject>(josnStr);
                res = new Character((string)jobject["Name"], (string)jobject["Job"], (int)jobject["Level"], (int)jobject["Atk"],
                                              (int)jobject["Def"], (int)jobject["HP"], (int)jobject["Gold"], (int)jobject["Exp"]);
                foreach (var e in jobject["Inventory"])
                {
                    if (Shop.instance.ContainsKey((int)e))
                    {
                        Item n = Shop.instance[(int)e].DeepCopy();
                        res.inventory.InsertItem(n);
                        if (jobject["equipArmor"].HasValues)
                            if ((int)jobject["equipWeapon"] == (int)e)
                                res.equipWeapon = n as Weapon;
                        if (jobject["equipArmor"].HasValues)
                            if ((int)jobject["equipArmor"] == (int)e)
                                res.equipArmor = n as Armor;
                    }
                }
            }
            catch (FileNotFoundException ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey(true);
            }
            catch (NullReferenceException ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey(true);
            }
            catch (JsonReaderException ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey(true);
            }
            catch (FormatException ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey(true);
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey(true);
            }
            if (res == null)
                res = MakeBasicCharacterFile();
            return res;
        }

catch를 주렁주렁 달고 있는데, 이게 맞는지 모르겠다.
각 예외마다 어떻게 처리를 해야할지도 모르겠어서, 에러메시지만 띄워놓고 마지막에 res가 null이라면 기본 file을 생성하는 방법으로 구현해봤다.


리팩토링 - DungeonScene과 BattleScene 분리

기존에는 DrawDungeon() 메서드에서 던전을 선택하고 들어가면, 그 메서드 안에서 전투까지 진행했는데, 이번에 DrawBattleScene()을 작성하여 전투 로직을 이쪽으로 빼냈다.

나는 코드를 짜다보면 Main함수나 GameManager 부분의 코드만 엄청나게 길어지는데, 앞으로는 기능별로 잘 분리해서 설계적인 코드를 짜보도록 노력해야겠다.


Git 많이 써보기

지금이라도 위의 수정사항들을 하나씩 커밋해보고 있다.
그런데 지금 프로젝트에 C#, Visual Studio와 관련된 gitignore를 설정해 뒀는데, .suo .pdb 이런 녀석들이 계속 변경사항에 나온다.
내일 일어나면 바로 뛰어가서 질문해봐야겠다.

profile
game developer

0개의 댓글