* amount 숫자 증가 X - 수업 이후 해결


실행 결과

1. App.cs

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

namespace Study08
{
    public class App
    {
        // 생성자
        public App()
        {
            Game game = new Game();
            game.Start();
        }
    }
}

2. Game.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;

namespace Study08
{
    public class Game
    {
        // 필드
        public List<Monster> monsters;
        private Inventory inven;

        // 생성자
        public Game()
        {
            this.inven = new Inventory();
            this.monsters = new List<Monster>();
            this.LoadDatas();
            if (!this.IsNewbie())
            {
                this.LoadInfos();
            }
        }

        public void Start()
        {
            Console.WriteLine("Start");
            this.CreateMonster(100);
            this.CreateMonster(101);
            this.CreateMonster(102);

            foreach (var monster in this.monsters)
            {
                //MonsterData data = DataManager.instance.GetMonsterData(monster.Id);
                //Console.WriteLine(data.name);
                Console.WriteLine("{0}, {1}", monster.Id, monster.Name);
            }

            Monster target = this.monsters[0];
            // Action 대리자
            target.dieAction = () =>
            {
                this.monsters.Remove(target);   // List에서 제거
                Console.WriteLine(this.monsters.Count);     // 2
                MonsterData data = DataManager.instance.GetMonsterData(target.Id);
                Item item = this.DropItem(data.drop_item0, data.drop_item1, data.drop_item2);
                this.inven.Add(item);
                Console.WriteLine("아이템 수: {0}", this.inven.Count);

                this.Save();
            };

            target.onHit += (sender, args) =>
            {
                Console.WriteLine("{0}%", args.per); // 남은 체력 %
            };

            Console.WriteLine(target);
            target.Hit(14);
            target.Hit(16);
        }

        public Item DropItem(params int[] arr)
        {
            IEnumerable<int> ids = arr.Where(x => x != 0);
            Random rand = new Random();
            var idx = rand.Next(0, ids.Count());    // 0, 1
            foreach (var id in arr)
            {
                Console.WriteLine("=>{0}", id);
            }
            int randItemIdx = arr[idx];
            Console.WriteLine(randItemIdx);
            ItemData data = DataManager.instance.GetItemData(randItemIdx);

            return this.CreateItem(data.id);
        }

        private Item CreateItem(int id)
        {
            ItemInfo info = new ItemInfo(id);
            return new Item(info);
        }

        private void LoadInfos()
        {
            var itemInfosJson = File.ReadAllText("./item_infos.json");
            // 역직렬화
            var itemInfos = JsonConvert.DeserializeObject<ItemInfo[]>(itemInfosJson);
            Console.WriteLine(itemInfos);

            foreach (var info in itemInfos)
            {
                var item = new Item(info);
                this.inven.Add(item);
            }
            Console.WriteLine("인벤토리 아이템 갯수 : {0}", this.inven.Count);
        }

        private bool IsNewbie()
        {
            var exists = File.Exists("./item_infos.json");
            if (exists)
                Console.WriteLine("기존 유저");
            else
                Console.WriteLine("신규 유저");
            return !exists;
        }

        private void LoadDatas()
        {
            DataManager.instance.LoadMonsterDatas();
            DataManager.instance.LoadItemDatas();
        }

        private void CreateMonster(int id)
        {
            Monster mon = new Monster(id);
            this.monsters.Add(mon);
        }

        public void Save()
        {
            // 직렬화: 객체 -> 문자열
            // List<Item> -> [{"id": 100 }]
            var json = JsonConvert.SerializeObject(this.inven.GetItems());
            Console.WriteLine( json);

            // 파일로 저장
            File.WriteAllText("./item_infos.json", json);
            Console.WriteLine("인벤토리 아이템들 저장 완료");
        }
    }
}

// 저장할 때는 시점이 저장됨

3. DataManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using System.Linq;

namespace Study08
{
    // 싱글톤 클래스
    // sealed: 봉인 키워드 -> 상속 불가
    public sealed class DataManager
    {
        // static: 정적 키워드, 프로그램 시작해서 끝날 때까지 값 유지 -> 형식으로 접근해야 함
        // readonly: 읽기 전용 필드 생성 
        public static readonly DataManager instance = new DataManager();
        private Dictionary<int, MonsterData> dicMonsters;
        private Dictionary<int, ItemData> dicItems;

        // private 생성자
        private DataManager()
        {

        }

        // 인스턴스 메서드
        public void LoadItemDatas()
        {
            string json = File.ReadAllText("./item_data.json");
            // 역직렬화
            var arr = JsonConvert.DeserializeObject<ItemData[]>(json);
            this.dicItems = arr.ToDictionary(x => x.id);
            Console.WriteLine("item_data가 로드되었습니다. {0}", this.dicItems.Count);  
        }


        public void LoadMonsterDatas()
        {
            Console.WriteLine("LoadData");
            string json = File.ReadAllText("./monster_data.json");
            Console.WriteLine(json);

            // 역직렬화 : 문자열 -> 객체
            // 몬스터 데이터 배열을 반환
            MonsterData[] arrMonsterDatas = JsonConvert.DeserializeObject<MonsterData[]>(json);

            // Linq 사용
            // 내부 람다의 의미는 배열에 담긴 객체의 속성 중 key를 어떤 것으로 할 것인가?
            this.dicMonsters = arrMonsterDatas.ToDictionary(x => x.id);

            // Linq 사용 X
            ////this.dicMonsters = new Dictionary<int, MonsterData>();

            //// 배열에 담긴 MonsterData 객체 사전에 옮긴다
            //foreach (MonsterData data in arrMonsterDatas)
            //{
            //    this.dicMonsters.Add(data.id, data);
            //}

            // 확인
            foreach (KeyValuePair<int, MonsterData> pair in this.dicMonsters)
            {
                // id, monsterdata 인스턴스 출력됨
                Console.WriteLine("key: {0}, value: {1}", pair.Key, pair.Value);
            }
        }

        public MonsterData GetMonsterData(int id)
        {
            return this.dicMonsters[id];
        }

        public ItemData GetItemData(int id)
        {
            return this.dicItems[id];
        }
    }
}

4. MonsterData.cs

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

namespace Study08
{
    public class MonsterData
    {
        public int id;
        public string name;
        public float max_hp;
        public int drop_item0;  // item_data 테이블의 id
        public int drop_item1;
        public int drop_item2;
    }
}

5. Monster.cs

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

namespace Study08
{
    public class Monster
    {
        public class HitEventArgs : EventArgs
        {
            public float per;
        }

        public int Id
        {
            get;
            private set;
        }
        public string Name
        {
            get
            {
                MonsterData data = DataManager.instance.GetMonsterData(this.Id);
                return data.name;
            }
        }

        private float hp;       // 현재 체력
        private float maxHp;    // 최대 체력
        public Action dieAction;
        public EventHandler<HitEventArgs> onHit;


        // 생성자
        public Monster(int id)
        {
            this.Id = id;
            MonsterData data = DataManager.instance.GetMonsterData(this.Id);
            this.maxHp = data.max_hp;
            this.hp = this.maxHp;
            Console.WriteLine("몬스터 (id: {0})가 생성되었습니다.", this.Id);
            Console.WriteLine("체력 {0}/{1}", this.hp, this.maxHp);
        }

        public bool IsDie()
        {
            return this.hp <= 0;
        }

        public void Hit(int damage)
        {
            if (this.IsDie()) return;

            this.hp -= damage;
            if (this.hp <= 0)
                this.hp = 0;

            var args = new HitEventArgs();
            args.per = this.hp / this.maxHp * 100.0f;
            this.onHit(this, args);
            //this.onHit(this, new HitEventArgs() { per = this.hp / this.maxHp });
            Console.WriteLine("{0}이(가) {1} 피해를 입었습니다. (체력 {2}/{3})", this.Name, damage, this.hp, this.maxHp);

            if(this.hp <= 0)
            {
                this.Die();
            }
        }

        private void Die()
        {
            Console.WriteLine("id: {0}, name: {1}이(가) 죽었습니다.", this.Id, this.Name);
            this.DieAction();
        }

        public void DieAction()
        {
            this.dieAction();
        }
    }
}

6. ItemData.cs

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

namespace Study08
{
    public class ItemData
    {
        public int id;
        public string name;
        public float damage;
    }
}

7. Item.cs

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

namespace Study08
{
    public class Item
    {
        private ItemInfo info;  // 저장 객체

        public int Id
        {
            get
            {
                return this.info.id;
            }
        }

        public int Amount
        {
            get
            {
                return this.info.amount;
            }
            set
            {
                this.info.amount = value;
            }
        }

        // 생성자
        public Item(ItemInfo info)
        {
            this.info = info;
            this.info.amount = Amount;
        }
    }
}

8. ItemInfo.cs

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

namespace Study08
{
    public class ItemInfo
    {
        // 저장 객체를 public으로 정의
        public int id;
        public int amount;

        // 생성자
        public ItemInfo(int id, int amount = 1)
        {
            this.id = id;
            this.amount = amount;
        }
    }
}

9. Inventory.cs 

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

namespace Study08
{
    public class Inventory
    {
        private List<Item> items;
        public int Count
        {
            get
            {
                return this.items.Count;
            }
        }
        // 생성자
        public Inventory()
        {
            this.items = new List<Item>();
        }

        public void Add(Item item)
        {
            // 아래와 같은 기능
            //Item sameItem = null;
            //for (int i = 0; i < this.items.Count; i++)
            //{
            //    if (this.items[i].Id == item.Id)
            //    {
            //        sameItem = this.items[i];
            //        break;
            //    }
            //}

            var sameItem = this.items.Find(x => x.Id == item.Id);

            if (sameItem != null)
            {
                sameItem.Amount++;
            }
            else {
                this.items.Add(item);
            }
            
        }

        public void Remove(Item item)
        {
            this.items.Remove(item);
        }

        public List<Item> GetItems()
        {
            return this.items;
        }
    }
}

'C# > 수업 내용' 카테고리의 다른 글

[C#] 알고리즘 문제  (0) 2022.07.06
Json 연습 2 - 캐릭터, 경험치 데이터  (1) 2022.06.21
대리자 연습  (0) 2022.06.16
2차원 배열 맵타일  (0) 2022.06.15
2048 왼쪽 이동  (0) 2022.06.15

+ Recent posts