오늘의 알고리즘 오류 상황
문제: 정수 num1과 num2가 매개변수로 주어질 때, num1을 num2로 나눈 값에 1,000을 곱한 후 정수 부분을 return 하도록 soltuion 함수를 완성해주세요.
using System;
public class Solution
{
public int solution(int num1, int num2)
{
double a = (double)num1;
double b = (double)num2;
double quotient = a / b;
int answer = (double) quotient * 1000; // 나중에 보니 여기가 문제였음;;
return answer;
}
}
C#은 정수형 변수 끼리 '/' 연산자로 나눗셈을 하면 몫과 나머지로 구분해
정수형 몫만 반환한다.
나도 그걸 알고 있기에 double 자료형을 쓴 건데....
계속 원하는 결과가 나오질 않는다며 콘솔창이 뭐라하고 있었다.
계속 코드를 보면서 뭐가 잘못됐지...? 싶어서 생각해봤더니
아무래도 계산 결과에서 정수부분만 남겨서 반환하려는 게
나의 의도랑 다르게 뭔가 안 맞았던 모양이다.
그래서 어쩌면, double형에서 int형으로 캐스팅하는 과정에서
전체 수식에 괄호를 안 쳐서 그런가...? 싶어서
다음 코드로 수정해 돌려봤다.
{
public int solution(int num1, int num2)
{
double a = (double)num1;
double b = (double)num2;
double quotient = a / b;
double answer = quotient * 1000;
return (int) answer;
}
}
해결 됐다!
오류 발생 이유:
(double) quotient * 1000
1. 다시 보니 이 부분에서 잘못된 자료형으로 형변환을 하고 있었다;;
(int) quotient * 1000
2. int 자료형으로 변환하게 고치면 정상 작동될 줄 알았더니...
코드를 자세히 보니 quotient 값을 int형으로 변환하고,
1000을 곱하는 방식으로 되어있었다...
(int) (quotient * 1000)
결국은 이렇게 수정해야 의도했던 정수 부분만 남길 수 있는 것이다.
ItemManager 나머지 기능 구현하기
확실히 코드를 한번 이해하고 나니
나머지 기능을 구현하는 것은 그렇게 어렵지 않았다.
오늘 구현한 기능은 다음과 같다.
- ShowInventory : 인벤토리 아이템 출력
- ShowShop : 상점 판매 중인 아이템 출력
- BuyItem / SellItem : 아이템 사고 팔기, (팔면 85%만 돌려받음)
- OnEquipItem / OffEquipItem : 장비 탈착 기능
- GetFieldItem / DropItem : 던전 필드에서 아이템 줍기 / 버리기
- OnEvent - GetFieldItem 관련 이벤트 동작 시 처리할 것 추가
그리고 팀원들과 협의해서 변수명이 다른 것들은 통일했다.
(Comment -> Description, Atk -> ATK 등)
코드 전체:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace TextRPG
{
enum ItemType
{
Weapon,
Armor
}
struct ItemData
{
public string[] inventory;
public string[] equippedItem;
public string[] fieldItem;
public string[] saleItem;
}
internal class ItemManager : IListener
{
readonly Item[] items;
readonly Item[] fieldItems;
readonly Item[] shopItems;
List<Item> inventory;
List<Item> shopDisplay;
List<Item> fieldDisplay;
public int GetInventorySize { get { return inventory.Count; } }
public int GetShopDisplaySize { get { return shopDisplay.Count; } }
public int GetFieldDisplaySize { get { return fieldDisplay.Count; } }
public ItemManager()
// ItemManager 생성자 :
{
List<Item>? list = (List<Item>?)Utilities.LoadFile(LoadType.Item);
items = list.ToArray();
ItemData? data = (ItemData?)Utilities.LoadFile(LoadType.ItemData);
inventory = [];
shopDisplay = [];
fieldDisplay = [];
if (data != null)
// 아이템 정보를 data에서 읽어와서 inventory및 기타 배열에 할당하기
{
foreach (string item in data.Value.inventory)
{
Item _item = list.Find(x => x.Name == item);
inventory.Add(_item);
}
foreach (string item in data.Value.equippedItem)
{
Item _item = list.Find(x => x.Name == item);
_item.IsEquipped = true;
}
foreach (string item in data.Value.saleItem)
{
Item _item = list.Find(x => x.Name == item);
shopDisplay.Add(_item);
}
foreach (string item in data.Value.fieldItem)
{
Item _item = list.Find(x => x.Name == item);
fieldDisplay.Add(_item);
}
}
shopItems = list.FindAll(x => x.IsSale == true).ToArray();
fieldItems = list.FindAll(x => x.IsOnField == true).ToArray();
List<Item>? equippedItems = inventory.FindAll(x => x.IsEquipped);
EventManager.Instance.PostEvent(EventType.eUpdateItem, null);
// ItemManager에 Event Listener 등록
EventManager.Instance.AddListener(EventType.eGetFieldItem, this);
EventManager.Instance.AddListener(EventType.eGameEnd, this);
}
public void ShowInventory()
// 인벤토리 보기 관련 메서드
{
Console.WriteLine("[아이템 목록]");
int count = 0;
foreach (Item item in inventory)
// 양식에 맞춰 콘솔에 아이템 정보 출력
// 1. [E] {아이템 이름} | {공격력 or 방어력} {추가 스탯} | {설명} |
{
count++;
if (item.IsEquipped)
Console.Write($"-{count} [E] ");
else
Console.Write($"-{count} [-] ");
Console.WriteLine($"{item.Name} | " +
$"{((item.ATK > 0) ? ("공격력" + $" +{item.ATK}") : "")} " +
$"{((item.DEF > 0) ? ("방어력" + $" +{item.DEF}") : "")} " +
$"{item.Description} | " );
}
}
public void ShowShop()
{
Console.WriteLine("[아이템 목록]");
int count = 0;
foreach (Item item in shopDisplay)
// 양식에 맞춰 콘솔에 아이템 정보 출력
// 1. {아이템 이름} | {공격력 or 방어력} {추가 스탯} | {설명} | {가격} G
{
count++;
Console.Write($"{item.Name} | " +
$"{((item.ATK > 0) ? ("공격력" + $" +{item.ATK}") : "")} " +
$"{((item.DEF > 0) ? ("방어력" + $" +{item.DEF}") : "")} " +
$"{item.Description}");
if (item.IsSale)
Console.WriteLine($"{item.Cost} G");
else
Console.WriteLine("구매 완료");
}
}
public void BuyItem(int itemNum, int myWallet)
{
// 아이템 구매 관련 메서드
Item item = shopDisplay[itemNum - 1];
if (item.Cost > myWallet)
{
Console.WriteLine("소지금이 부족합니다.");
return;
}
else
{
item.IsSale = false;
inventory.Add(item);
Console.WriteLine($"{item.Name}을 구매했습니다.");
// EventManager로 골드 변경 이벤트 전달
EventManager.Instance.PostEvent(EventType.eUpdateGold, -item.Cost);
}
}
public void SellItem(int itemNum, int myWallet)
{
// 아이템 판매 관련 메서드
Item item = inventory[itemNum - 1];
item.IsSale = true;
inventory.Remove(item);
Console.WriteLine($"{item.Name}을 판매했습니다.");
// EventManager로 골드 변경 이벤트 전달
int resultGold = (int) (item.Cost * 0.85);
EventManager.Instance.PostEvent(EventType.eUpdateGold, resultGold);
}
public void OnEquipItem(int itemNum)
{
// 장비 착용 관련 메서드
Item item = inventory[itemNum - 1];
item.IsEquipped = true;
Console.WriteLine($"{item.Name}을 착용했습니다.");
// EventManager로 스탯 변경 이벤트 전달
EventManager.Instance.PostEvent(EventType.eUpdateStat, item);
}
public void OffEquipItem(int itemNum)
{
// 장비 해제 관련 메서드
Item item = inventory[itemNum - 1];
item.IsEquipped = false;
Console.WriteLine($"{item.Name}을 해제했습니다.");
// EventManager로 스탯 변경 이벤트 전달
EventManager.Instance.PostEvent(EventType.eUpdateStat, item);
}
public void GetFieldItem(object? data = null)
{
// 필드에 드랍된 아이템 줍줍
if (data != null)
{
fieldDisplay.Add((Item)data);
foreach (Item item in fieldDisplay)
{
inventory.Add(item);
Console.WriteLine($"{item.Name}을 획득했습니다.");
}
}
else
{
Console.WriteLine($"아무 아이템도 얻지 못했습니다.");
}
}
public void DropItem(int itemNum)
{
// 아이템 버리기(인벤토리에서 삭제)
Item item = inventory[itemNum - 1];
inventory.Remove(item);
Console.WriteLine($"{item.Name}을 버렸습니다.");
if (item.IsEquipped) // 버린 아이템이 장비중인 경우
{
// EventManager로 스탯 변경 이벤트 전달
EventManager.Instance.PostEvent(EventType.eUpdateStat, item);
}
}
public void OnEvent(EventType type, object data)
{
// 게임 이벤트에 따른 인벤토리 기능 구현
switch (type)
{
// case가 eGameEnd인 경우 ItemData를 저장
case EventType.eGameEnd:
ItemData itemData = new ItemData();
itemData.inventory = inventory.Select(x => x.Name).ToArray();
itemData.equippedItem = inventory.FindAll(x => x.IsEquipped).Select(x => x.Name).ToArray();
itemData.fieldItem = fieldDisplay.Select(x => x.Name).ToArray();
itemData.saleItem = shopDisplay.Select(x => x.Name).ToArray();
Utilities.SaveFile(SaveType.ItemData, itemData);
break;
// case가 eGetItem인 경우 필드 아이템 획득
case EventType.eGetFieldItem:
GetFieldItem(data);
break;
}
}
}
class Item
// 아이템 자료 클래스
{
// { get; private set; } : 읽기 전용 프로퍼티, 외부에서 수정 불가
public string Name { get; private set; }
public ItemType Type { get; private set; }
public int ATK { get; private set; }
public int DEF { get; private set; }
public string Description { get; private set; }
public int Cost { get; private set; }
public bool IsEquipped { get; set; } // 장비 착용 여부
public bool IsSale { get; set; } // 상점에서 판매 가능한 지의 여부
public bool IsOnField { get; private set; } // 던전에서 얻을 수 있는 지의 여부
public Item(string name, int type, int atk, int def, string description, int reqGold, bool isSale, bool isOnField)
// Item 클래스 생성자
{
Name = name;
Type = (ItemType)type;
ATK = atk;
DEF = def;
Description = description;
Cost = reqGold;
IsSale = isSale;
IsOnField = isOnField;
}
}
}
느낀 점
오늘 아침 9시부터 알고리즘 문제풀이를 시작하려니
아직은 익숙하지 않아서 머리가 안 돌아가는 느낌도 났는데,
이건 적응의 문제라 꾸준히 하다보면
알고리즘 문제 풀이에도 뇌가 말랑말랑 해질 것 같은 생각이 든다.
그리고 이제 내가 맡은 부분을 구현은 했지만
팀원들이 작업한 코드를 하나로 뭉쳐서 테스트는 안해봤기에,
내일 하나로 뭉쳤을 때 어떤 버그가 생길지도 모른다.
하지만, 충분히 팀원과의 협업으로 극복 가능하다고 확신한다.
240111-15:55
+ShowInventory 기능 구현,
+ShowShop 기능 구현,
+BuyItem 기능 구현
240111-16:04
+SellItem 메서드 구현
+OnEquipItem 기능 구현
+OffEquipItem 기능 구현
+DropItem 기능 구현
240111-16:27
+ GetFieldItem 기능 구현
+ eGetFieldItem 이벤트 발생 시 관련 기능 추가
'TIL(Today I Learned)' 카테고리의 다른 글
텍스트 RPG 게임 : 상점, 인벤토리에 기능 추가 - TIL#16 (0) | 2024.01.15 |
---|---|
텍스트 RPG 게임 : 기능 구현과 디버깅 - TIL#15 (0) | 2024.01.12 |
텍스트 RPG 게임 : EventManager 이해하기 등 - TIL#13 (0) | 2024.01.10 |
중간 점검 : EventManager는 어떻게 동작하는가 (0) | 2024.01.10 |
텍스트 RPG 게임, 팀원과 협업하기 - TIL#12 (0) | 2024.01.09 |