오늘은 TextRPG의 마감일이기 때문에 팀원분들과 함께 코드 리뷰를 진행했다. 마지막으로 각자 진행한 코드를 살펴보면서 주석을 첨삭하거나, 에러 수정 및 더 나은 코드 작성 방안을 함께 고민했다.
팀원분께서 GetReward()를 수정해주셨는데, GetReward()의 수정 사항을 함께 얘기해보았는데, 어제 아이템이 이상하게 출력되던 문제를 해결해주셨다.
문제는 dungeonMonster[]
배열을 통해 아이템의 이름을 가져오려 했던 것에서 발생한 것이었다. 해당 배열은 몬스터 클래스를 랜덤하게 생성했기 때문에, 정렬 문제 및 몬스터 종류가 일정하지 않기 때문에 출력값이 이상하게 나오는 것이었다.
public void GetReward()
{
Random rnd = new Random();
int[] itemsCounter = new int[3]; // 낡은 대검, 초보자의 갑옷, 가시 갑옷 총 3개의 아이템만 떨어트린다.
int gold = 0;
foreach (Monster monster in dungeonMonsters)
{
if (rnd.Next(1, 101) <= 8) //8퍼 확률로
{
// 아이템 드랍 이벤트 전송
EventManager.Instance.PostEvent(EventType.Item, Utilities.EventPair(eItemType.eGetFieldItem,monster.Item));
// itemsCounter : 아이템 별 획득한 개수.
// itemsCounter[0] : "낡은 대검"
// itemsCounter[1] : "초보자의 갑옷"
// itemsCounter[2] : "가시 갑옷"
if (monster.Level == 2)
{
itemsCounter[0]++; // 획득한 아이템 리스트에 추가
}
else if (monster.Level == 3)
{
itemsCounter[1]++;
}
else
{
itemsCounter[2]++;
}
}
EventManager.Instance.PostEvent(EventType.Quest, Utilities.EventPair(eQuestType.Monster, monster.Class)); //몬스터 수만큼 처치 이벤트 발생
gold += monster.Gold; //몬스터 골드 총합
}
EventManager.Instance.PostEvent(EventType.Player, Utilities.EventPair(ePlayerType.Gold, gold)); //플레이어 골드 증가 이벤트
Console.WriteLine();
Console.WriteLine("[획득 아이템]");
Utilities.TextColorWithNoNewLine($"{gold}", ConsoleColor.DarkRed); // 플레이어가 얻은 골드 출력
Console.WriteLine($" Gold");
for (int i = 0; i < itemsCounter.Length; i++)
{
if (itemsCounter[i] > 0)
{
// 몬스터가 가지고 있는 아이템 이름 - 개수
Console.WriteLine($"{dungeonMonsters[i].item} - {itemsCounter[i]}");
}
}
}
int[] itemsCounter;
는 아이템들의 개수를 카운트하는 카운터들의 배열이다.
이 배열을 통해 전투 종료 후 몬스터들이 떨어트린 아이템의 개수를 각각 저장하기 위해 만들었다.
내가 원한 것은 itemsCounter가 0보다 클 때, 즉 아이템이 드랍되었을 때 해당 아이템의 이름을 dungeonMonster[]에서 가져오려 했었다.
그러나 itemsCounter는 아이템 종류가 정렬되어 저장되어 있는 반면,
dungeonMonster는 몬스터들이 랜덤한 종류로 랜덤한 수 만큼 생성되어 있었기 때문에 내가 원하던 대로 출력이 되지 않았던 것이다.
고민하던 찰나에 팀원분이 조언해주시길, 아이템 이름을 열거형으로 만들어 보라고 해주셨다. 눈이 번뜩 뜨이는 느낌을 받았다. ㅋㅋ
public enum MonsterItemType
{
monsterItem1 = 0,
monsterItem2,
monsterItem3
}
...
public void GetReward()
{
Random rnd = new Random();
int[] itemsCounter = new int[3]; // 낡은 대검, 초보자의 갑옷, 가시 갑옷 총 3개의 아이템만 떨어트린다.
int gold = 0;
foreach (Monster monster in dungeonMonsters)
{
if (rnd.Next(1, 101) <= 8) //8퍼 확률로
{
// 아이템 드랍 이벤트 전송
EventManager.Instance.PostEvent(EventType.Item, Utilities.EventPair(eItemType.eGetFieldItem,monster.Item));
// itemsCounter : 아이템 별 획득한 개수.
// itemsCounter[0] : "낡은 대검"
// itemsCounter[1] : "초보자의 갑옷"
// itemsCounter[2] : "가시 갑옷"
if (monster.Level == 2)
{
itemsCounter[0]++; // 획득한 아이템 리스트에 추가
}
else if (monster.Level == 3)
{
itemsCounter[1]++;
}
else
{
itemsCounter[2]++;
}
}
EventManager.Instance.PostEvent(EventType.Quest, Utilities.EventPair(eQuestType.Monster, monster.Class)); //몬스터 수만큼 처치 이벤트 발생
gold += monster.Gold; //몬스터 골드 총합
}
EventManager.Instance.PostEvent(EventType.Player, Utilities.EventPair(ePlayerType.Gold, gold)); //플레이어 골드 증가 이벤트
Console.WriteLine();
Console.WriteLine("[획득 아이템]");
Utilities.TextColorWithNoNewLine($"{gold}", ConsoleColor.DarkRed); // 플레이어가 얻은 골드 출력
Console.WriteLine($" Gold");
for (int i = 0; i < itemsCounter.Length; i++)
{
if (itemsCounter[i] > 0)
{
Console.Write($"{GetMonsterItemName(i)} "); // 아이템 이름 가져오기
Utilities.TextColorWithNoNewLine("- ", ConsoleColor.DarkYellow);
Utilities.TextColorWithNoNewLine($"{itemsCounter[i]}", ConsoleColor.DarkRed);
}
}
}
// 아이템 이름 가져오기
string GetMonsterItemName(int i)
{
switch ((MonsterItemType)i)
{
case MonsterItemType.monsterItem1:
return "낡은 대검";
case MonsterItemType.monsterItem2:
return "초보자의 갑옷";
default:
return "가시 갑옷";
}
}
사실 해당 방법이 정답인지는 확실치 않지만, 내가 원하는 결과를 얻을 수 있었다!
MonsterItemType이라는 열거형을 선언해놓고, 이후 itemCounter를 비교하는 for문을 돌 때, 이름을 GetMonsterItemName()이라는 함수에서 switch문을 통해 i 값에 해당하는 아이템의 이름을 return 해주는 것으로 해결할 수 있었다.
몬스터가 스킬을 사용하기 위해 스킬을 호출할 때, MP와 스킬 Cost를 비교하여 MP가 부족할 경우, 스킬을 null을 return 하도록 코드가 작성되어 있었다.
이 때, 몬스터의 공격 타입이 Skill로 지정될 경우, Skill이 null을 참조하기 때문에 에러가 발생했다.
public bool IsUseSkill => myState.Skill != null;
위의 코드를 통해 몬스터의 Skill이 현재 null인지 비교를 하여, null이 아닐 경우 true를, null일 경우 false 값을 저장하도록 했다.
if ((AttackType)monsterAttackType == AttackType.Skill)
{
monster.SetSkill(skillManager.GetMonsterSkill(monster.Class, monster.GetMP));
if (!monster.IsUseSkill)
{
monsterAttackType = AttackType.Attack;
}
}
이 후, 몬스터가 스킬을 사용하려 할 때, if문을 통해 몬스터의 스킬이 null일 경우, 공격 타입을 Attack으로 변경하도록 수정했다.
정말 격정의 일주일이었던 것 같다. 원래 주저리 주저리 적어놓은 수준의 코드에서 갑자기 난이도가 확 뛰었다. 이런 식의 코드를 작성해야 될텐데... 당장 다시 작성하라고 하면 못할 것 같다. 주말에 시간이 된다면 TextRPG 코드를 복기해볼 생각이다. 정말 팀원분들이 고생이 많으셨고, 팀장이긴 한데 팀장 역할을 수행 못한 것 같아 정말 죄송하다... 😭