상세 컨텐츠

본문 제목

Study_018-1 아이템 상점 구현.

C#/수업내용

by McRobbin 2020. 4. 28. 15:49

본문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Study_018
{
    public class App
    {
        public static DateTime GameDateTime = DateTime.Now;
 
        public App()
        {
            //데이터 매니져 초기화 및 함수 불러보기.
            DataManager.Instance.DataLoad();
            EventShopData data = DataManager.Instance.GetDataById<EventShopData>(100);
            EventShopDueData dueData = DataManager.Instance.GetDueDataByShopId(100);
 
 
            //인포 매니져 초기화 및 함수 불러보기.
            InfoManager.Instance.InitInfoManager();
            InfoManager.Instance.PrintDueInfo();
 
 
            //바이어 인포 생성.
            BuyerInfo buyer = new BuyerInfo("남현석");
            buyer.PrintInfo();
 
            List<EventShopDueData> rawDatas = DataManager.Instance.GetAllDataByType<EventShopDueData>();
 
            buyer.LevelUp(60);
            buyer.ChargeCoin(10000000);
            buyer.ChargeDiamonds(10000);
            buyer.BuyPackage(105);
            InfoManager.Instance.GetInfoById<EventShopInfo>(105).PrintProductInfo();
            buyer.PrintBuyList();
            buyer.BuyPackage(103);
            buyer.PrintInfo();
            buyer.PrintBuyList();
            InfoManager.Instance.GetInfoById<EventShopInfo>(103).PrintProductInfo();
 
 
            this.SetDateTime(new DateTime(202063));
 
            buyer.LevelUp(60);
            buyer.BuyPackage(105);
            InfoManager.Instance.GetInfoById<EventShopInfo>(105).PrintProductInfo();
            buyer.PrintInfo();
            buyer.PrintBuyList();
 
            buyer.LevelUp(60);
            buyer.BuyPackage(105);
            InfoManager.Instance.GetInfoById<EventShopInfo>(105).PrintProductInfo();
            buyer.PrintInfo();
            buyer.PrintBuyList();
 
            buyer.BuyPackage(103);
            buyer.PrintInfo();
            buyer.PrintBuyList();
            InfoManager.Instance.GetInfoById<EventShopInfo>(103).PrintProductInfo();
        }
 
 
        public void SetDateTime(DateTime dateTime)
        {
            Console.WriteLine("\n바뀌기 전 날짜 : {0}", GameDateTime);
            //날짜가 바뀌었을 때 limit_type이 1인 모든 info의 count를 0으로 초기화
            if((dateTime - GameDateTime).Days >= 1)
            {
                var dailyProductDatas = DataManager.Instance.GetDataByLimitType(1);
                foreach(var data in dailyProductDatas)
                {
                    InfoManager.Instance.GetInfoById<EventShopInfo>(data.id).ClearBuyCount();
                }
            }
 
            GameDateTime = dateTime;
            Console.WriteLine("바뀐 후 날짜 : {0}\n", GameDateTime);
        }
    }
}
 
 
 

App.cs 코드 입니다.

날짜를 바꿔가며 테스트하기 위해 App에 GameDateTime을 넣었습니다.

유저가 들어왔을 시점의 날짜를 매개변수의 dateTime으로 상정했습니다.

GameDateTime getter에 DateTime.Now를 반환받게 하고 싶었으나 확인이 되지 않아 하지 않았습니다.

day가 하나 늘어났다면 매일의 구매 갯수를 초기화 합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Study_018
{
    public class BuyerInfo
    {
        public string name;
 
        public int coinAmount;
        public int diamondAmount;
        public int level;
        public int mileage;
        public List<int> productList;
 
        public BuyerInfo(string name, int level = 0int coinAmount = 0int diamondAmount = 0int mileage = 0)
        {
            this.name = name;
            this.coinAmount = coinAmount;
            this.diamondAmount = diamondAmount;
            this.level = level;
            this.mileage = mileage;
            this.productList = new List<int>();
        }
 
        public void PrintInfo()
        {
            Console.WriteLine("이름 : {0}, 코인 : {1}, 다이아 : {2}," +
                " 레벨 : {3}, 마일리지 : {4}\n"this.name, this.coinAmount,
                this.diamondAmount, this.level, this.mileage);
        }
 
        public void BuyPackage(int productId)
        {
            
            EventShopData productData = DataManager.Instance.GetDataById<EventShopData>(productId);
            var productInfo = InfoManager.Instance.GetInfoById<EventShopInfo>(productId);
            var dueData = DataManager.Instance.GetDueDataByShopId(productData.id);
 
            //기간 지났을때 검사.
            if(dueData != null && dueData.due_date < App.GameDateTime)
            {
                Console.WriteLine("상품 구매 기간이 지났습니다. 이름 : {0}"productData.name);
                Console.WriteLine("기간 : {0} 까지\n", dueData.due_date);
            }
 
            //레벨 낮을 때 검사.
            else if (this.level < productData.require_level)
            {
                Console.WriteLine("레벨이 낮아 {0}을 구매할 수 없습니다. 요구레벨 : {1} / {2}\n"productData.name, this.level, productData.require_level);
            }
 
            //가능한 갯수 모두 구매했을 때.
            else if(productData.limit_count != 0 && productInfo.buyCount >= productData.limit_count)
            {
                Console.WriteLine("가능한 갯수를 모두 구매했습니다, {0} / {1}\n", productInfo.buyCount, productData.limit_count);
            }
 
            //다이아몬드가 모자랄때.
            else if(productData.price_type == 1 && this.diamondAmount < productData.price_amount)
            {
                Console.WriteLine("다이아몬드가 모자랍니다. {0} / {1}\n", diamondAmount, productData.price_amount);
            }
 
            //코인이 모자랄때.
            else if(productData.price_type == 2 && this.coinAmount < productData.price_amount)
            {
                Console.WriteLine("코인이 모자랍니다. {0} / {1}\n"this.coinAmount, productData.price_amount);
            }
 
            //구매.
            else
            {
                this.mileage += productData.mileage;
 
                if (productData.price_type == 1)
                    this.diamondAmount -= productData.price_amount;
                else
                    this.coinAmount -= productData.price_amount;
 
                InfoManager.Instance.AddBuyCount(productData.id);
 
                productList.Add(productData.id);
                Console.WriteLine("{0} 아이템을 구매했습니다.\n"productData.name);
            }
        }
 
        public void PrintBuyList()
        {
            Console.WriteLine("\n구매한 아이템 리스트=============");
            for(int i = 0; i < productList.Count; i++)
            {
                var productData = DataManager.Instance.GetDataById<EventShopData>(productList[i]);
                var productInfo = InfoManager.Instance.GetInfoById<EventShopInfo>(productList[i]);
 
                Console.WriteLine("id : {0}, 이름 : {1}",
                    productData.id, productData.name);
            }
 
        }
 
        public void LevelUp(int count = 1)
        {
            this.level += count;
            Console.WriteLine("레벨이 올랐습니다. 레벨 : {0}\n"this.level);
        }
 
        public void ChargeDiamonds(int amount)
        {
            this.diamondAmount += amount;
            Console.WriteLine("다이아몬드를 충전했습니다. 현재 갯수 : {0}\n"this.diamondAmount);
        }
 
        public void ChargeCoin(int amount)
        {
            this.coinAmount += amount;
            Console.WriteLine("코인을 충전했습니다. 현재 갯수 : {0}\n"this.coinAmount);
        }
    }
}
 
 
 

BuyerInfo.cs 입니다.

레벨업, 패키지 구매, 코인충전, 다이아몬드 충전 기능이 있습니다.

구매한 물건들을 List<int>로 EventShopData의 id를 가지고 있게 합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
 
namespace Study_018
{
    public class DataManager
    {
        private static Dictionary<int, RawData> DataDict;
 
        private static DataManager dataManager;
        public static DataManager Instance
        {
            get
            {
                if(dataManager == null)
                {
                    dataManager = new DataManager();
                }
 
                return dataManager;
            }
        }
 
        private DataManager() 
        {
            DataDict = new Dictionary<int, RawData>();
        }
 
        public void DataLoad()
        {
            string[] dataPaths =
            {
                @"E:\DataFile\event_shop_data.json",
                @"E:\DataFile\event_shop_due_data.json"
            };
 
            string fileText = File.ReadAllText(dataPaths[0]);
            EventShopData[] shopDatas = JsonConvert.DeserializeObject<EventShopData[]>(fileText);
            Console.WriteLine("\nEventShopData Load========");
            foreach (var data in shopDatas)
            {
                DataDict.Add(data.id, data);
                Console.WriteLine("{0}, {1}, {2}"data.id, data.name, data.price_amount);
            }
 
            fileText = File.ReadAllText(dataPaths[1]);
            EventShopDueData[] dueDatas = JsonConvert.DeserializeObject<EventShopDueData[]>(fileText);
            Console.WriteLine("\nEventShopDueData Load========");
            foreach (var data in dueDatas)
            {
                DataDict.Add(data.id, data);
                Console.WriteLine("{0}, {1}, {2}"data.id, data.event_shop_id, data.due_date);
            }
        }
 
        public T GetDataById<T>(int id) where T : RawData
        {
            RawData data;
            DataDict.TryGetValue(id, out data);
 
            return data as T;
        }
 
        public EventShopDueData GetDueDataByShopId(int shopId)
        {
            var dataList = DataDict.Values.ToList();
            var dueList = dataList.FindAll(x => x.GetType() == typeof(EventShopDueData));
            
            foreach(var due in dueList)
            {
                EventShopDueData dueData = due as EventShopDueData;
                if (dueData.event_shop_id == shopId)
                    return dueData;
            }
 
            return null;
        }
 
        public List<T> GetAllDataByType<T>() where T : RawData
        {
            List<T> rtnList = new List<T>();
            foreach(var rawData in DataDict.Values)
            {
                if(rawData.GetType() == typeof(T))
                {
                    rtnList.Add(rawData as T);
                }
            }
 
            return rtnList;
        }
 
        public List<EventShopData> GetDataByLimitType(int limitType)
        {
            List<EventShopData> rtnList = new List<EventShopData>();
            foreach(var data in DataDict.Values)
            {
                if(data.GetType() == typeof(EventShopData))
                {
                    EventShopData val = data as EventShopData;
                    if (val.limit_type == limitType)
                        rtnList.Add(val);
                }
            }
 
            return rtnList;
        }
    }
}
 
 
 

DataManager.cs 입니다.

저는 EventShopData와 EventShopDueData를 두개로 나누어 엑셀 파일을 구성했습니다.

판매 기간이 없는 상품이 있어 이를 관리하기 위함입니다. 후에 코드에서 판매 기간이 없다면

무기한 판매 상품으로 간주합니다.

 

EventShopData와 EventShopDueData 모두 Data.cs 를 상속받아 한개의 딕셔너리에 모두 넣었습니다.

이 경우 두 데이터에 겹치는 id가 있으면 안됩니다. Object로 받아도 무관합니다.

 

이로인해 데이터 타입을 입력받고 그에 따른 반환값을 주는 제너릭 메서드를 정의했습니다.

 

 

데이터 파일 매핑 클래스는 건너뛰겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Study_018
{
    public class EventShopInfo : RawInfo
    {
        public int buyCount;
 
        public EventShopInfo(int id, int buyCount = 0)
        {
            this.id = id;
            this.buyCount = buyCount;
        }
 
        public void ClearBuyCount()
        {
            this.buyCount = 0;
        }
 
        public void PrintProductInfo()
        {
            var productData = DataManager.Instance.GetDataById<EventShopData>(this.id);
            Console.WriteLine("{0} 구매 가능 갯수 : {1} / {2}"
                DataManager.Instance.GetDataById<EventShopData>(id).name,
                this.buyCount, productData.limit_count);
        }
    }
}
 
 
 

EventShopInfo.cs 코드 입니다.

유저가 어느 상품을 몇개 구매해야 하는지 확인하기 위해 카운트 정보만 가지고 있습니다.

또한 매일 구매 갯수가 초기화 되는 경우를 위해 ClearBuyCount메서드를 정의했습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using System;
using System.Collections.Generic;
 
namespace Study_018
{
    public class InfoManager
    {
        private static InfoManager infoManager;
 
        private static Dictionary<int, RawInfo> InfoDict;
        public static InfoManager Instance
        {
            get
            {
                if (infoManager == null)
                    infoManager = new InfoManager();
 
                return infoManager;
            }
        }
 
        private InfoManager() 
        {
            InfoDict = new Dictionary<int, RawInfo>();
        }
 
 
        public void InitInfoManager()
        {
            var dataDict = DataManager.Instance.GetAllDataByType<EventShopData>();
            Console.WriteLine("\nInfoManager Initialize=======");
            foreach (var data in dataDict)
            {
                Console.WriteLine("{0}", data.id);
            }
        }
 
        public void PrintDueInfo()
        {
            foreach (var val in InfoDict.Values) {
                var shopVal = val as EventShopInfo;
                Console.WriteLine("id : {0}, buy_count : {1}\n", shopVal.id, shopVal.buyCount);
 
            }
        }
 
        public T GetInfoById<T>(int id) where T : RawInfo
        {
            foreach(var info in InfoDict.Values)
            {
                if(info.GetType() == typeof(T))
                {
                    if (info.id == id)
                        return info as T;
                }
            }
 
            return null;
        }
 
        public void AddBuyCount(int id, int count = 1)
        {
            var info = InfoDict[id] as EventShopInfo;
            info.buyCount += count;
        }
    }
}
 
 
 

InfoManager.cs 입니다.

캐릭터의 인포는 관리하지 않아 의미는 없는 수준입니다. ShopInfo를 딕셔너리로 관리합니다.

DataManager와 마찬가지로 제너릭을 사용합니다.

 

RawData.cs, RawInfo.cs 모두 id만 가지고 있습니다. 생략합니다.

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

Unity Study_003 5Run  (0) 2020.05.08
Study_019_2 일일 출석 보상  (0) 2020.04.29
Study_014 - json변환, 파일입출력, Dictionary  (0) 2020.04.22
json파일 예제. With File 3가지 출력.  (0) 2020.04.21
Study_012  (0) 2020.04.20

관련글 더보기