본문 바로가기
내일배움캠프 Unity/본 캠프

[내일배움캠프][TIL] 15일차, 팀 과제 완성 (2025-10-20)

by 승연 2025. 10. 20.

목표

팀 과제 마무리하기

 

학습 내용

서로가 작성한 모든 기능을 연결하고, 제대로 출력되는지 확인하는 마지막 작업만이 남았다.

의도와 다르게 작동하거나, 버그가 발생하는 부분은 전부 수정하고 나니 시간이 금방 지나간 것 같다.

내가 담당했던 파트는 아이템, 인벤토리, 상점 클래스였고, 여기에 추가적으로 데이터 JSON 작업을 했다.

더보기

인벤토리

using System;
using System.Collections.Generic;
using System.Linq;

namespace Text_RPG_11
{
    public class Inventory
    {
        private GameManager gameManager;
        public List<Items> Items { get; private set; }

        public Inventory(GameManager manager)
        {
            gameManager = manager;
            Items = new List<Items>();
        }

        #region 아이템 추가
        public void AddItem(Items item)
        {
            if(item == null) //입력한 값이 null 이라면 return
            {
                return;
            }

            if(item is Potion newPotion) //입력한 값이 포션인지 체크
            {
                Potion existing = null; //기존 포션을 넣을 변수. 기본값은 null

                foreach (var i in Items) //Items 리스트 순회, i는 리스트의 각 항목
                {
                    if(i is Potion p && p.ItemId == newPotion.ItemId) //i가 포션일경우 p에 저장, p의 id와 입력한 값의 id가 같다면
                    {
                        existing = p; //existing에 p를 저장
                        break; //찾았으니 순회 중단
                    }
                }

                if(existing != null) //existing 이 null 이 아니라면
                {
                    existing.PotionCount += newPotion.PotionCount; //기존 포션 개수에 새 포션의 수량을 더한다.
                    return; //합쳤으니 메소드 종료
                }
                else
                {
                    newPotion.IsPurchased = true; //existing이 null이라면 새 포션을 구매 상태로 변경
                }
            }

            item.IsPurchased = true;
            Items.Add(item); //포션이 아니라면 리스트에 새 아이템 추가
        }
        #endregion

        #region 아이템 제거
        public bool RemoveItem(Items item, int quantity = 1) //포션의 경우 개수가 여러개기에, 매개변수로 개수 = 1 선언
        {
            if(item == null) //아이템이 null 이라면 false 반환해서 메서드 종료
            {
                return false;
            }

            if(item is Potion p) //아이템이 포션이라면 p로 저장
            {
                if (p.PotionCount > quantity) //포션의 카운트가 1개 이상이라면
                {
                    p.PotionCount -= quantity; //포션 카운트 - quantity(1개)
                    return true; //true 반환해서 메서드 종료
                }
                else
                {
                    return Items.Remove(p); //포션의 개수가 0개라면 리스트에서 포션을 지우고 메서드 종료
                }
            }

            return Items.Remove(item); //리스트에서 해당 아이템 제거
        }
        #endregion

        #region 타입 별 필터링
        public List<Weapon> GetWeapons() //무기 타입만 반환하는 메서드
        {
            List<Weapon> weapons = new List<Weapon>(); //반환할 무기를 저장할 리스트 생성

            foreach (var item in Items) //인벤토리 내 모든 아이템 순회
            {
                if (item is Weapon weapon) //아이템이 Weapon 타입이라면 weapon으로 캐스팅
                {
                    weapons.Add(weapon); //해당 아이템 weapon리스트에 추가
                }
            }

            return weapons; //리스트 반환
        }

        public List<Armor> GetArmors()
        {
            List<Armor> armors = new List<Armor>();

            foreach (var item in Items)
            {
                if( item is Armor armor)
                {
                    armors.Add(armor);
                }
            }

            return armors;
        }

        public List<Potion> GetPotions()
        {
            List<Potion> potions = new List<Potion>();

            foreach (var item in Items)
            {
                if(item is Potion potion)
                {
                    potions.Add(potion);
                }
            }

            return potions;
        }
        #endregion

        #region 아이템 정렬
        public void SortItems()
        {
            Items = Items.OrderBy(i => i.ItemType()) //아이템 타입 기준으로 정렬
                .ThenBy(i => i.Name) //같은 타입 내에선 이름순으로 정렬
                .ToList(); //정렬 한 걸 리스트로 다시 저장
        }
        #endregion
    }
}

 

더보기

상점

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Text_RPG_11
{
    public class Shop
    {
        private GameManager gameManager;
        private List<Items> shopInventory;

        public Shop(GameManager manager)
        {
            gameManager = manager;
            LoadShopInventory();
        }

        #region 상점 아이템 로드
        private void LoadShopInventory()
        {
            shopInventory = ItemDatabase.GetShopItems();
        }
        #endregion

        #region 다른 곳에서 상점 아이템 목록 부르기(UI에서 호출)
        public List<Items> GetShopInventory()
        {
            return shopInventory;
        }
        #endregion

        #region 아이템 구매
        public bool BuyItem(Items shopItem)
        {
            if (shopItem == null) //shopItem 값이 null 이라면 false 리턴(되돌아감)
            {
                return false;
            }

            if (shopItem.Price > gameManager.Player.Gold) //shopItem의 가격이 플레이어가 보유중인 골드보다 크다면 false 리턴(되돌아감)
            {
                Console.WriteLine("보유중인 골드가 부족합니다.");
                return false;
            }

            if(shopItem is Potion potion) //shopItem이 포션이라면,
            {
                gameManager.inventory.AddItem(potion); //인벤토리에 해당 아이템 추가
                gameManager.Player.Gold -= potion.Price; //플레이어 골드에서 아이템 가격만큼 빼기
                potion.IsPurchased = true; //아이템 구매 상태로 변경
                Console.WriteLine($"{shopItem.Name}을 구매했습니다.");
                return true; //true 값을 리턴해서 해당 메소드 종료

            }

            if (shopItem.IsPurchased) //아이템이 이미 구매한 상태라면, false 리턴(되돌아감)
            {
                Console.WriteLine("이미 구매한 아이템입니다.");
                return false;
            }

            Items purchasedItem = ItemDatabase.GetItemById(shopItem.ItemId); //상점에 있는 아이템은 원본 데이터임, 데이터 변경을 방지하기 위해 인벤토리에 넣을 새로운 아이템 객체(클론)를 Id로 불러옴

            if (purchasedItem == null)
            {
                Console.WriteLine("아이템을 찾을 수 없습니다.");
                return false;
            }

            gameManager.inventory.AddItem(purchasedItem); //인벤토리에 아이템(클론) 추가
            gameManager.Player.Gold -= shopItem.Price; //플레이어 골드에서 아이템 가격만큼 빼기
            shopItem.IsPurchased = true; //아이템 구매 상태로 변경

            Console.WriteLine($"{shopItem.Name}을 구매했습니다.");
            return true; //true값 리턴해서 메소드 종료
        }
        #endregion

        #region 아이템 판매
        public bool SellItem(Items playerItem)
        {
            if (playerItem == null) //playerItem 이 null이라면
            {
                return false; //false 반환하여 메서드 종료
            }

            if (playerItem.IsEquipped) //playerItem이 착용중이라면
            {
                Console.WriteLine("장착 중인 아이템은 판매할 수 없습니다.");
                return false; //false 반환하여 메서드 종료
            }

            gameManager.inventory.RemoveItem(playerItem); //인벤토리에서 playerItem 제거
            gameManager.Player.Gold += playerItem.Price; //플레이어 골드에 playerItem 가격만큼 추가해서 넣어줌

            foreach (var shopItem in shopInventory) //shopInventory 리스트를 순회하면서 shopItem이란 지역 변수를 찾는다
            {
                if (shopItem.ItemId == playerItem.ItemId) //shopItem의 Id와 playerItem의 Id가 같다면
                {
                    shopItem.IsPurchased = false; //shopItem의 구매 여부를 false로 설정(다시 구매 가능하게)
                    break; //반복문 종료
                }
            }

            Console.WriteLine($"{playerItem.Name}을 판매했습니다.");
            return true;
        }
        #endregion
    }
}

기본적인 기능인 인벤토리에 아이템 추가/제거, 상점에서 아이템 구매/판매 기능이며 다른 클래스에서 해당 메소드 호출 시 예외 처리를 돌리고 알맞는 값으로 작동되게끔 꼼꼼하게 만드는 걸 목표로 작성했다.

 

회고

기존에 구상했던 합성 기능은 결국 시간 내로 완성하기엔 볼륨이 너무 커져버렸고, 다른 파트에서 작업하는데 민폐가 될 것 같아 기본 기능들만 넣어서 마무리. 작업했던 걸 전부 뒤엎고 다시 만드느라 결국 주말엔 밤을 새서 작업했다....

여러모로 더 잘할 수 있었는데 그러지 못해서 아쉬움이 남는다.