오늘은 내일배움캠프 프로그래밍 기본주차의 개인 과제인 Sparta Dungeon
의 튜터님들의 코드 리뷰가 있었다. 내가 받은 피드백을 갈무리하고, 어떤 점을 보완해하면 좋을지 정리해보기로 했다.
git repository : https://github.com/jyWooooo/SpartaDungeon
내가 받은 피드백을 정리해보면,
/// <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을 생성하는 방법으로 구현해봤다.
기존에는 DrawDungeon()
메서드에서 던전을 선택하고 들어가면, 그 메서드 안에서 전투까지 진행했는데, 이번에 DrawBattleScene()
을 작성하여 전투 로직을 이쪽으로 빼냈다.
나는 코드를 짜다보면 Main함수나 GameManager 부분의 코드만 엄청나게 길어지는데, 앞으로는 기능별로 잘 분리해서 설계적인 코드를 짜보도록 노력해야겠다.
지금이라도 위의 수정사항들을 하나씩 커밋해보고 있다.
그런데 지금 프로젝트에 C#, Visual Studio와 관련된 gitignore를 설정해 뒀는데, .suo .pdb 이런 녀석들이 계속 변경사항에 나온다.
내일 일어나면 바로 뛰어가서 질문해봐야겠다.