C#/수업내용

몬스터 잡고 아이템 드랍 저장, 싱글톤 데이터매니저

띵킹진 2022. 6. 20. 14:45

 

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.monsters = new List<Monster>();
            this.LoadDatas();
            this.inven = new Inventory();
        }

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

        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];
            target.dieAction = () => {
                MonsterData data = DataManager.instance.GetMonsterData(target.Id);
                Item item = this.DropItem(data.drop_item0, data.drop_item1, data.drop_item2);
                //Item item = this.DropItem();
                //Console.WriteLine("id : {0}, name : {1}".item.Id, item.Name);

                //이펙트생성
                //Liste에서 제거
                this.monsters.Remove(target);
                Console.WriteLine(this.monsters.Count);

                this.inven.Add(item);

            };
            target.onHit += (sener, args) =>
            {
                Console.WriteLine("{0}%", args.per);
            };
            Console.WriteLine(target);
            target.Hit(5);
            target.Hit(5);
            this.Save();
        }

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

        private void LoadInfos()
        {
            var itemInfosJson = File.ReadAllText("./item_infos.json");
            var itemInfos = JsonConvert.DeserializeObject<ItemInfo[]>(itemInfosJson);
            foreach (var info in itemInfos)
            {
                var item = new Item(info);
                this.inven.Add(item);
            }
        }

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

        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());
            foreach(var id in ids)
            {
                Console.WriteLine("=>{0}", id);
            }
            int randItemIdx = arr[idx];
            Console.WriteLine("randItemIdx, {0}", randItemIdx);
            ItemData data = DataManager.instance.GetItemData(randItemIdx);

            Item item = this.CreateItem(data.id);
            return item;
        }

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

        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("인벤토리 아이템들 저장완료");
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;

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 LoadMonsterDatas()
        {
            Console.WriteLine("LoadData");
            var json = File.ReadAllText("./monster_data.json");
            Console.WriteLine(json);
            //역직렬화 : 문자열 -> 객체
            MonsterData[] arrMonsterDatas = JsonConvert.DeserializeObject<MonsterData[]>(json);
            this.dicMonsters = new Dictionary<int, MonsterData>();

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

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

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

        }

        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 MonsterData GetMonsterData(int id)
        {
            return this.dicMonsters[id];
        }

        public ItemData GetItemData(int id)
        {
            Console.WriteLine(id);
            return this.dicItems[id];
        }
    }
}
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 Action dieAction;
        public EventHandler<HitEventArgs> onHit;
        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;
        private int drop_item0 { get; }
        private int drop_item1 { get; }
        private int drop_item2 { get; }

        public Monster(int id)
        {
            this.Id = id;
            MonsterData data = DataManager.instance.GetMonsterData(this.Id);

            Console.WriteLine("name: {0}", data.name);

            this.maxHp = data.max_hp;
            this.hp = this.maxHp;
            this.drop_item0 = data.drop_item0;
            this.drop_item1 = data.drop_item1;
            this.drop_item2 = data.drop_item2;
            Console.WriteLine("{0},{1},{2}", drop_item0, drop_item1, drop_item2);
            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;

            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 });

            if (this.hp <= 0) this.hp = 0;
            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();
        }
    }
}
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;

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

namespace Study08
{
    public class Item
    {
        public int Id { get; private set; }
        public string Name
        {
            get { ItemData data = DataManager.instance.GetItemData(this.Id);
                return data.name;
            }
        }
        private float damage;
        public Item(int id)
        {
            this.Id = id;
            ItemData data = DataManager.instance.GetItemData(this.Id);
            this.damage = data.damage;
        }

        public Item(ItemInfo info)
        {
            this.Id = info.Id;
            ItemData data = DataManager.instance.GetItemData(this.Id);
            this.damage = data.damage;
        }
    }
}
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;
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Study08
{
    public class ItemInfo
    {
        public int Id
        { 
        get { return this.info.Id; }
        }
        private ItemInfo info; //저장객체

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

    }
}