Shader "HJK/NewSurfaceShader"    // 쉐이더 이름
{
    // Properties: SubShader의 변수로 사용(_Color, _MainTex ...), 인터페이스 제작, 인스펙터에 노출됨
    Properties
    {
        //_Color ("Color", Color) = (1,1,1,1)
        //_MainTex ("Albedo (RGB)", 2D) = "white" {}

        // 광택, 재질(거침&매끈)
        //_Glossiness ("Smoothness", Range(0,1)) = 0.5
        //_Metallic ("Metallic", Range(0,1)) = 0.0
    
        _TestColor("TestColor", Color) = (1,1,1,1)
        _R ("Red", Range(0,1)) = 1
        _G ("Green", Range(0,1)) = 1
        _B ("Blue", Range(0,1)) = 1
        _BrightDarkness ("Bright & Darkness", Range(-1, 1)) = 0

        //// float
        //_Darkness ("Darkness", Range(0, 1)) = 0.5   // Range 함수: 슬라이더 바 생성
        //_Attenuation("Attenuation", Float) =  1.2   // float : 숫자 하나

        //// float4
        //_MyColor ("MyColor", Color) = (1,1,1,1)     
        //_Vector ("Vector", Vector) = (1,100,0.5,0)  

        //// Sampler: 대부분 텍스쳐
        //_MyTexture ("MyTexture", 2D) = "white"{}   // 이름{옵션}
    }

    // 실제 색상을 결정해줄 코드 작성
    SubShader   
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM   
        // 1. 설정
        #pragma surface surf Standard fullforwardshadows noambient
        #pragma target 3.0

        //sampler2D _MainTex;

        // 2. 구조체: 유니티 엔진으로부터 받아와야 할 데이터(알아서 넣어줌)
        // 공란이면 안 됨
        struct Input
        {
            // : 시멘틱(CG가 UNITY 코드 알아들을 수 있게 해줌)
            float4 color : COLOR;
            //float2 uv_MainTex;
        };

        // * 변수 영역
        //half _Glossiness;
        //half _Metallic;
        fixed4 _Color;
        float4 _TestColor;
        float _R;
        float _G;
        float _B;
        float _BrightDarkness;
        //float4 test;

        // 3. 최종 픽셀 컬러 지정
        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            //float4 test = float4(1,0,0,1);  // 속성 rgba 집어넣어 색 표현 가능
            
            //float r = 1;
            //float2 gg= float2(0.5, 0);
            //float3 bbb = float3(1,0,1);
            //o.Albedo = float3(bbb.r, gg.r,r.r);
            //o.Albedo = _TestColor;
            o.Albedo = _TestColor + _BrightDarkness;
            
            //// Albedo comes from a texture tinted by color
            //fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            //o.Albedo = c.rgb;
            //// Metallic and smoothness come from slider variables
            //o.Metallic = _Metallic;
            //o.Smoothness = _Glossiness;
            //o.Alpha = c.a;

            // 색 표현
            // Albedo: 빛 영향 O
            // Emission: 빛 영향 X
            //o.Albedo = float3(1, 0, 0);
            //o.Emission = float3(0.5,0.5,0.5) * float3(0.5,0.5,0.5);
            
        }
        ENDCG
    }

    FallBack "Diffuse"  // Diffuse: 유니티 내장 기본 셰이더
}

 

기본 셰이더 코드: _MainTex만 가지고 있다

Shader "Custom/tex"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

 

 

실행 결과

GameDirector2.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameDirector2 : MonoBehaviour
{
    public GameObject shuriken;
    [SerializeField]
    private GameObject ground;
    [SerializeField]
    private GameObject dt;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        float len = this.ground.transform.position.y - this.shuriken.transform.position.y;
        Text textDt = this.dt.GetComponent<Text>();
        textDt.text = string.Format("{0}m", len.ToString("F2"));
        if (len < 0)
        {
            textDt.text = "성공";
        }
    }
}

ShuridenController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShurikenController : MonoBehaviour
{
    [SerializeField]
    private float speed;
    [SerializeField]
    private float rotSpeed = 0;
    [SerializeField]
    private Vector2 startPos;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 마우스가 클릭한 곳의 좌표를 얻어옴
            this.startPos = Input.mousePosition;
            this.speed = 0.1f;
            this.rotSpeed = 15;
        }
        else if (Input.GetMouseButtonUp(0))
        {
            Vector2 endPos = Input.mousePosition;
            var length = endPos.y - this.startPos.y;

            // 감속
            this.speed = length / 500f;
        }

        this.transform.Rotate(0, 0, this.rotSpeed);
        this.transform.position += new Vector3(0, this.speed, 0);
        this.rotSpeed *= 0.96f;

    }
}

shuriken Component
GameDirector Component

App.cs

exam.zip
0.06MB

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

namespace exam
{
    public class App
    {
        // 생성자
        public App()
        {
            //this.Solution1();
            //this.Solution2();
            //this.Solution3();
            //this.Solution4();
            //this.Solution5();
            //this.Solution6();
            //this.Solution7();
            //this.Solution8();
            //this.Solution9();
        }

        public void Solution1()
        {
            int[] arr = new int[] { 20, 10, 35, 30, 7 };
            int min = arr[0];
            int max = arr[0];


            for (int i = 0; i < arr.Length; i++)
            {
                if (arr[i] > max)
                    max = arr[i];

                if (arr[i] < min)
                    min = arr[i];
            }

            Console.WriteLine("{0}, {1}", max, min);
            Console.WriteLine();
        }

        public void Solution2()
        {
            int h = 23;
            int m = 40;

            m -= 45;
            if (m < 0)
            {
                m += 60;
                h -= 1;
                if (h == 0) h = 24;
            }

            Console.WriteLine("{0}시 {1}분", h, m);
            Console.WriteLine();
        }

        public void Solution3()
        {
            Queue<int> queue = new Queue<int>();
            for (int i = 1; i <= 8; i++)
            {
                queue.Enqueue(i);
            }

            while(queue.Count > 1)
            {
                queue.Dequeue();
                int peek = queue.Peek();
                queue.Enqueue(peek);
                queue.Dequeue();
            }

            Console.WriteLine(queue.Peek());
            Console.WriteLine();
        }

        public void Solution4()
        {
            string s1 = "So when I die(the (first) I will see in (heaven) is a score list)";
            string s2 = "A rope may form )( a trail in a maze";
            string s3 = "Help( I(m being held prisoner) in a fortune cookie factory)";

            Stack<string> stack = new Stack<string>();
        }

        public void Solution5()
        {
            Console.Write("입력: ");
            int num = Convert.ToInt32(Console.ReadLine());
            if (num > 10)
            {
                Console.WriteLine("다시 입력하세요.");
            }
            else
            {
                Console.Write("출력: {0}", this.Factorial(num));
                Console.WriteLine();
            }

        }

        public void Solution6()
        {
            var graph = new Graph<int>();
            var one = graph.AddVertex(1);
            var two = graph.AddVertex(2);
            var three = graph.AddVertex(3);
            var four = graph.AddVertex(4);
            var five = graph.AddVertex(5);

            graph.AddEdge(one, two);
            graph.AddEdge(one, four);
            graph.AddEdge(two, three);
            graph.AddEdge(two, four);
            graph.AddEdge(four, five);

            graph.BFS();
            //graph.DebugPrintGraph();
        }

        public void Solution7()
        {
            var bt = new BinaryTree<string>("A");

            bt.Root.left = new BinaryTreeNode<string>("B");
            bt.Root.left.left = new BinaryTreeNode<string>("D");
            bt.Root.right = new BinaryTreeNode<string>("C");
            bt.Root.right.left = new BinaryTreeNode<string>("E");
            bt.Root.right.right = new BinaryTreeNode<string>("F");
            bt.Root.right.right.right = new BinaryTreeNode<string>("G");

            Console.Write("전위 순회한 결과: ");
            bt.PreorderTraversal();
            Console.WriteLine();
            Console.Write("중위 순회한 결과: ");
            bt.InorderTraversal();
            Console.WriteLine();
            Console.Write("후위 순회한 결과: ");
            bt.PostorderTraversal();
            Console.WriteLine();
        }

        public void Solution8()
        {
            string p = "I am happy today";
            string[] words = p.Split(' ');
            foreach(var word in words)
            {
                char[] reverse = word.ToCharArray();
                Array.Reverse(reverse);
                Console.Write(reverse);
                Console.Write(" ");
            }
            Console.WriteLine();
        }

        public void Solution9()
        {
            string p = "It over 2000 years old";
            string str = p.Replace(" ", String.Empty);
            char[] result = str.ToCharArray();
            int count = 0;
            foreach(var c in result)
            {
                count++;
            }
            Console.WriteLine(count);
        }

        private int Factorial(int n)
        {
            if (n == 0 || n == 1) return 1;
            return n * Factorial(n - 1);
        }
    }
}

BinaryTree.cs

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

namespace exam
{
    public class BinaryTree<T>
    {
        public BinaryTreeNode<T> Root { get; private set; }

        public BinaryTree(T data)
        {
            this.Root = new BinaryTreeNode<T>(data);
        }

        public void PreorderTraversal()
        {
            this.PreorderTraversal(this.Root);
        }

        private void PreorderTraversal(BinaryTreeNode<T> node)
        {
            if (node == null) return;
            Console.Write(node.data);
            this.PreorderTraversal(node.left);
            this.PreorderTraversal(node.right);
        }

        public void InorderTraversal()
        {
            this.InorderTraversal(this.Root);
        }

        private void InorderTraversal(BinaryTreeNode<T> node)
        {
            if (node == null) return;
            this.InorderTraversal(node.left);
            Console.Write(node.data);
            this.InorderTraversal(node.right);
        }

        public void PostorderTraversal()
        {
            this.PostorderTraversal(this.Root);
        }

        private void PostorderTraversal(BinaryTreeNode<T> node)
        {
            if (node == null) return;
            this.PostorderTraversal(node.left);
            this.PostorderTraversal(node.right);
            Console.Write(node.data);
        }

        public void PreorderIterative()
        {
            if (this.Root == null) return;
            var stack = new Stack<BinaryTreeNode<T>>();

            // 루트를 스택에 저장
            stack.Push(this.Root);

            while (stack.Count > 0)
            {
                // 스택에 저장된 노드 가져오기
                var node = stack.Pop();

                // 방문
                Console.WriteLine("{0} ", node.data);

                // 오른쪽 노드를 스택에 저장
                if (node.right != null)
                {
                    stack.Push(node.right);
                }
                if (node.left != null)
                {
                    stack.Push(node.left);
                }
            }
        }

        public void InorderIterative()
        {
            var stack = new Stack<BinaryTreeNode<T>>();
            var node = this.Root;

            // 왼쪽 노드를 스택에 저장
            while (node != null)
            {
                stack.Push(node);
                node = node.left;
            }

            while (stack.Count > 0)
            {
                // 스택에 저장된 노드 가져오기
                node = stack.Pop();
                // 방문
                Console.WriteLine("{0} ", node.data);

                // 오른쪽 노드 존재 -> 루프 돌아서 오른쪽 노드의 왼쪽 노드도 저장
                if (node.right != null)
                {
                    node = node.right;
                    while (node != null)
                    {
                        stack.Push(node);
                        node = node.left;
                    }
                }
            }
        }

        public void PostorderIterative()
        {
            var stack = new Stack<BinaryTreeNode<T>>();
            var node = this.Root;

            while (node != null)
            {
                if (node.right != null)
                {
                    stack.Push(node.right);
                }
                stack.Push(node);
                node = node.left;
            }

            while (stack.Count > 0)
            {
                node = stack.Pop();
                if (node.right != null && stack.Count > 0 && node.right == stack.Peek())
                {
                    var right = stack.Pop();
                    stack.Push(node);
                    node = right;

                    while (node != null)
                    {
                        if (node.right != null)
                        {
                            stack.Push(node.right);
                        }
                        stack.Push(node);
                        node = node.left;
                    }
                }
                else
                {
                    Console.WriteLine("{0} ", node.data);
                }
            }
        }
    }
}

BinaryTreeNode.cs

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

namespace exam
{
    public class BinaryTreeNode<T>
    {
        public T data;
        public BinaryTreeNode<T> left;
        public BinaryTreeNode<T> right;

        public BinaryTreeNode(T data)
        {
            this.data = data;
        }
    }
}

Graph.cs

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

namespace exam
{
    public class Graph<T>
    {
        private List<Node<T>> nodes;
        private bool directedGraph;     // 방향 그래프 판단 변수

        public Graph(bool directedGraph = false)
        {
            this.nodes = new List<Node<T>>();
            this.directedGraph = directedGraph;
        }

        public Node<T> AddVertex(T data)
        {
            return this.AddVertex(new Node<T>(data));
        }

        public Node<T> AddVertex(Node<T> node)
        {
            this.nodes.Add(node);
            return node;
        }

        public void AddEdge(Node<T> from, Node<T> to, int weight = 1)
        {
            from.Neighbors.Add(to);
            from.Weights.Add(weight);
            if (!directedGraph)
            {
                to.Neighbors.Add(from);
                to.Weights.Add(weight);
            }
        }

        public void DebugPrintGraph()
        {
            foreach (var vertex in nodes)
            {
                int cnt = vertex.Neighbors.Count;
                for (int i = 0; i < cnt; i++)
                {
                    Console.WriteLine("{0}----({1})----{2}",
                        vertex.Data,
                        vertex.Weights[i],
                        vertex.Neighbors[i].Data);
                }
            }
        }

        // 깊이 우선 방식
        public void DFS()
        {
            // 방문 여부를 표시하는 방문테이블
            var visited = new HashSet<Node<T>>();

            // Disconnected Graph를 위해
            // 방문하지 않은 노드들 모두 체크
            foreach (var node in nodes)
            {
                if (!visited.Contains(node))
                {
                    this.DFSRecursive(node, visited);
                    Console.WriteLine();
                }
            }
        }

        private void DFSRecursive(Node<T> node, HashSet<Node<T>> visited)
        {
            // 노드 방문
            Console.Write("{0}", node.Data);
            visited.Add(node);

            // 인접 노드가 있을 때
            foreach (var adjNode in node.Neighbors)
            {
                // 이미 방문하지 않은 인접 노드에 대해서만
                if (!visited.Contains(adjNode))
                {
                    // 재귀 호출
                    DFSRecursive(adjNode, visited);
                }
            }
        }

        public void DFSIterative()
        {
            // 방문 테이블 생성
            var visited = new HashSet<Node<T>>();

            foreach (var node in nodes)
            {
                if (!visited.Contains(node))
                {
                    DFSUsingStack(node, visited);
                }
            }
        }

        private void DFSUsingStack(Node<T> node, HashSet<Node<T>> visited)
        {
            var stack = new Stack<Node<T>>();
            stack.Push(node);

            while (stack.Count > 0)
            {
                var vertex = stack.Pop();
                if (!visited.Contains(vertex))
                {
                    Console.WriteLine("{0}", vertex.Data);
                    visited.Add(vertex);
                }
                foreach (var adjNode in vertex.Neighbors)
                {
                    if (!visited.Contains(adjNode))
                    {
                        stack.Push(adjNode);
                    }
                }
            }
        }

        public void BFS()
        {
            var visited = new HashSet<Node<T>>();

            // 방문하지 않은 노드 체크
            foreach (var node in nodes)
            {
                if (!visited.Contains(node))
                {
                    BFS(node, visited);
                }
            }
        }

        private void BFS(Node<T> node, HashSet<Node<T>> visited)
        {
            var q = new Queue<Node<T>>();
            int count = 0;
            q.Enqueue(node);

            while (q.Count > 0)
            {
                var vertex = q.Dequeue();

                // 노드 방문
                if (!visited.Contains(vertex))
                {
                    //Console.Write("{0}", vertex.Data);
                    count++;
                    visited.Add(vertex);
                }

                foreach (var adjNode in vertex.Neighbors)
                {
                    // 이미 방문하지 않은 인접 노드에 대해
                    if (!visited.Contains(adjNode))
                    {
                        q.Enqueue(adjNode);
                    }
                }
            }

            Console.WriteLine(count);
        }
    }
}

Node.cs

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

namespace exam
{
    public class Node<T>
    {
        public T Data { get; set; }
        public List<Node<T>> Neighbors { get; set; }
        public List<int> Weights { get; set; }

        public Node()
        {
            this.Neighbors = new List<Node<T>>();
            this.Weights = new List<int>();
        }

        public Node(T data) : this()
        {
            this.Data = data;
        }
    }
}

 

1. App.cs

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

namespace Study09
{
    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 Study09
{
    public class Game
    {
        private Character character;

        // 생성자
        public Game()
        {
            this.LoadDatas();
        }

        public void Start()
        {
            if (this.IsNewbie())
            {
                Console.WriteLine("<메이플 스토리>");
                Console.WriteLine("신규 유저입니다.");
                Console.Write("캐릭터 이름을 정하세요: ");
                string inputName = Console.ReadLine();
                Console.Write("직업을 선택하세요(0. 전사, 1. 마법사, 2. 도적): ");
                int job = Convert.ToInt32(Console.ReadLine());

                CharacterData data = DataManager.instance.GetLoadCharacterData(job);
                this.character = new Character(inputName, data);
            }
            else
            {
                Console.WriteLine("기존 유저입니다.");
                CharacterInfo info = this.LoadCharacterInfo();
                this.character = new Character(info);
                this.character.ShowStatus();
                this.character.Hit(2);
                this.character.ShowStatus();
                this.character.GetExp(100);
                this.character.ShowStatus();
            }

            // 이벤트 구독
            this.character.onUpdateStatus += (sender, args) =>
            {
                CharacterInfo info = args.Info;
                this.Save(info);
            };

            if (this.IsNewbie())
            {
                this.character.Hit(3);
                this.character.GetExp(10);
            }
        }

        // 데이터 정보를 저장할 json 파일 생성
        // 역직렬화: 객체 -> 문자열
        private CharacterInfo LoadCharacterInfo()
        {
            string json = File.ReadAllText("./character_info.json");
            return JsonConvert.DeserializeObject<CharacterInfo>(json);
        }

        private bool IsNewbie()
        {
            var exists = File.Exists("./character_info.json");
            return !exists;
        }

        private void LoadDatas()
        {
            DataManager.instance.LoadCharacterDatas();
            DataManager.instance.LoadExpDatas();
        }

        private void Save(CharacterInfo info)
        {
            Console.WriteLine("Save Game");
            // 저장될 때 현재 변화한 데이터가 담긴 info를 저장
            //Console.WriteLine(info);
            // 직렬화 사용 ( .json 파일에 담겨야하기 때문에)
            string json = JsonConvert.SerializeObject(info);
            File.WriteAllText("./character_info.json", json);
            Console.WriteLine("Save Complete");
        }
    }
}

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 Study09
{
    // 싱글톤 클래스: 생성자를 private로 사용
    // sealed: 다른 클래스에서 상속받지 못하게 함
    // DataManager 클래스: 데이터시트를 딕셔너리로 관리
    public sealed class DataManager
    {
        // readonly 키워드 사용하여 읽기 전용으로 필드 생성
        public static readonly DataManager instance = new DataManager();

        // 데이터를 읽어올 딕셔너리 생성
        private Dictionary<int, CharacterData> dicCharacters;
        private Dictionary<int, ExpData> dicExp;

        //생성자
        private DataManager()
        {

        }

        public void LoadCharacterDatas()
        {
            string json = File.ReadAllText("./character_data.json");
            var arr = JsonConvert.DeserializeObject<CharacterData[]>(json);
            // 배열 요소를 사전에 넣기
            this.dicCharacters = arr.ToDictionary(x => x.id);
            
        }

        public void LoadExpDatas()
        {
            string json = File.ReadAllText("./exp_data.json");
            var arr = JsonConvert.DeserializeObject<ExpData[]>(json);
            // 배열 요소를 사전에 넣기
            this.dicExp = arr.ToDictionary(x => x.id);
        }

        public CharacterData GetLoadCharacterData(int job)
        {
            CharacterData data = this.dicCharacters.Values.Where(x => x.job == job).First();
            return data;
        }

        public ExpData GetRequireExpData(int level)
        {
            ExpData data = this.dicExp.Values.Where(x => x.level == level).First();
            return data;
        }
    }
}

4. CharacterData.cs

*  데이터시트를 기반하여 제작, 변수 정의 후 수정X

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

namespace Study09
{
    // 바인딩 클래스
    public class CharacterData
    {
        public int id;
        public int job;
        public float max_hp;
        public float damage;
    }
}

5. CharacterInfo.cs

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

namespace Study09
{
    public class CharacterInfo
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public int Level { get; set; }
        public float Hp { get; set; }
        public float MaxHp { get; set; }
        public float Damage { get; set; }
        public int CurrExp { get; set; }

        // 생성자
        public CharacterInfo()
        {

        }

        // 생성자
        public CharacterInfo(string name, int id, int level, float hp, float maxHp, float damage, int currExp)
        {
            Name = name;
            Id = id;
            Level = level;
            Hp = hp;
            MaxHp = maxHp;
            Damage = damage;
            CurrExp = currExp;
        }
    }
}

6. Character.cs

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

namespace Study09
{
    public class Character
    {
        public class GetExpEventArgs : EventArgs
        {
            public float per;
        }

        // 캐릭터 정보를 업데이트하는 이벤트 작성
        public class UpdateStatusEventArgs: EventArgs
        {
            public CharacterInfo Info { get; set; }
        }

        public event EventHandler<UpdateStatusEventArgs> onUpdateStatus;
        public event EventHandler<GetExpEventArgs> onGetExp;

        public enum eJob
        {
            Warrior,
            Wizard,
            Assassin
        }

        private eJob job;
        private int reqExp;

        private CharacterInfo info;

        public Character(CharacterInfo info)
        {
            this.info = info;
            // 저장된 레벨, 경험치 가져옴
            ExpData expData = DataManager.instance.GetRequireExpData(this.info.Level);
            this.reqExp = expData.require_exp;
        }

        // 생성자
        // 신규 유저
        public Character(string name, CharacterData data)
        {
            this.info = new CharacterInfo();
            this.info.Id = data.id;
            this.info.Name = name;
            this.job = (eJob)data.job;
            this.info.Level = 1;
            this.info.MaxHp = data.max_hp;
            this.info.Hp = this.info.MaxHp;
            this.info.Damage = data.damage;
            this.info.CurrExp = 0;
            ExpData expData = DataManager.instance.GetRequireExpData(this.info.Level);
            this.reqExp = expData.require_exp;
        }

        public void Hit(int damage)
        {
            this.info.Hp -= damage;
            

            this.UpdateStatus();

            if (this.info.Hp <= 0)
                this.info.Hp = 0;

            if (this.info.Hp <= 0)
            {
                this.ShowDie();
                this.info.Hp = this.info.MaxHp;
                this.info.CurrExp -= this.reqExp / 10;
            }
        }

        public void UpdateStatus()
        {
            if (this.onUpdateStatus != null)
            {
                this.onUpdateStatus(this, new UpdateStatusEventArgs() { Info = this.info});
            }
        }

        public void ShowDie()
        {
            Console.WriteLine("***************************");
            Console.WriteLine("죽었습니다.");
            Console.WriteLine("마을에서 다시 태어났습니다.");
            Console.WriteLine("경험치를 -{0} 잃었습니다.", this.reqExp / 10);
            Console.WriteLine("***************************");
        }

        public void GetExp(int exp)
        {
            this.info.CurrExp += exp;
            if (this.info.CurrExp >= 100)
            {
                this.ShowLevelUp();
                this.LevelUp();
                //this.LevelUp();
            }
                

            this.UpdateStatus();
        }

        public void LevelUp()
        {
            this.info.Level++;
            this.info.Damage++;
            this.info.MaxHp = this.info.MaxHp + 10;
            this.info.Hp = this.info.MaxHp;
            int restExp = this.info.CurrExp - this.reqExp;
            this.info.CurrExp = restExp;
            ExpData expData = DataManager.instance.GetRequireExpData(this.info.Level);
            this.reqExp = expData.require_exp;
            this.UpdateStatus();
        }

        public void ShowLevelUp()
        {
            Console.WriteLine("***************************");
            Console.WriteLine("LEVEL UP !");
            Console.WriteLine("레벨: {0} -> {1}", this.info.Level, this.info.Level + 1);
            Console.WriteLine("체력: {0} -> {1}", this.info.MaxHp, this.info.MaxHp + 10);
            Console.WriteLine("공격력: {0} -> {1}", this.info.Damage, this.info.Damage + 1);
            Console.WriteLine("***************************");
        }

        public string GetStringJob()
        {
            switch (this.job)
            {
                case eJob.Warrior: return "전사";
                case eJob.Wizard: return "마법사";
                case eJob.Assassin: return "도적";
                default: return "";
            }
        }

        public void ShowStatus()
        {
            Console.WriteLine("--------------------");
            Console.WriteLine("이름: {0}", this.info.Name);
            Console.WriteLine("직업: {0}", this.GetStringJob());
            Console.WriteLine("체력: {0} / {1}", this.info.Hp, this.info.MaxHp);
            Console.WriteLine("공격력: {0}", this.info.Damage);
            Console.WriteLine("레벨: {0}", this.info.Level);
            Console.WriteLine("경험치: {0} / {1} ({2}%)", this.info.CurrExp, this.reqExp, (float)this.info.CurrExp / this.reqExp * 100f);
            Console.WriteLine("--------------------");
        }
    }
}

7. ExpData.cs

*  데이터시트를 기반하여 제작, 변수 정의 후 수정X

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

namespace Study09
{
    // 바인딩 클래스
    public class ExpData
    {
        public int id;
        public int level;
        public int require_exp;   // 레벨업 후 필요한 경험치
    }
}

8. ExpInfo.cs

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

namespace Study09
{
    public class ExpInfo
    {
        public int level;
        public float reqExp;

        // 생성자
        public ExpInfo(int level, float reqExp)
        {
            this.level = level;
            this.reqExp = reqExp;
        }
    }
}

9. Exp.cs

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

namespace Study09
{
    public class Exp
    {
        private int id;
        private int level;
        private float requireExp;

        private ExpInfo info;

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

 

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

[Unity2D] Swipe 이용하여 표창 날리기  (0) 2022.07.07
[C#] 알고리즘 문제  (0) 2022.07.06
Json 연습 - 같은 아이템의 개수(amount) 증가  (0) 2022.06.20
대리자 연습  (0) 2022.06.16
2차원 배열 맵타일  (0) 2022.06.15

 

* 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

* 문제점: Key값이 "info"로 들어감

1. WeaponInfo.cs

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

namespace LoadDataExample
{
    // 저장될(변화하는) 데이터 저장
    public class WeaponInfo
    {
        public int id;  // 아이디
        public int enforce; // 강화 수치

        // 생성자
        public WeaponInfo(int id, int enforce = 0)
        {
            this.id = id;
            this.enforce = enforce;
        }
    }
}

2. Item.cs

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

namespace LoadDataExample
{
    public class Item
    {
        public WeaponInfo Info
        {
            get;
            private set;
        }

        // 생성자
        public Item(WeaponInfo info)
        {
            this.Info = info;
        }
    }
}

3. Inventory.cs

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

namespace LoadDataExample
{
    public class Inventory
    {
        Random rand = new Random();
        public List<Item> ItemList { get; set; }

        // 생성자
        public Inventory()
        {
            this.ItemList = new List<Item>();
        }
        public void CreateItem(int id)
        {
            WeaponInfo info = new WeaponInfo(id);
            Item item = new Item(info);
            this.ItemList.Add(item);
        }

        public void AddItem()
        {
            int id = this.rand.Next(100, 104);
            WeaponInfo info = new WeaponInfo(id);
            Item item = new Item(info);
            this.ItemList.Add(item);
        }
    }
}

4. App.cs

using System;
using System.IO;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;

namespace LoadDataExample
{
    public class App
    {
        //생성자 
        public App()
        {
            Inventory inventory = new Inventory();

            bool exists = File.Exists("./weapon_info.json");
            if (exists)
            {
                Console.WriteLine("기존유저");
                //  메모장에 있는 걸 읽어옴
                string weaponInfoJson = File.ReadAllText("./weapon_info.json");
                //Console.WriteLine(weaponInfoJson);

                //역직렬화 : 문자열 -> 오브젝트
                inventory.ItemList = JsonConvert.DeserializeObject<List<Item>>(weaponInfoJson);

                // 아이템 추가
                inventory.AddItem();

                // 직렬화: 오브젝트 -> 문자열
                string serializedJson = JsonConvert.SerializeObject(inventory.ItemList);

                //string serializedJson = JsonConvert.SerializeObject(item.Info);
                Console.WriteLine(serializedJson);
                //저장 
                File.WriteAllText("./weapon_info.json", serializedJson);

            }
            else
            {
                Console.WriteLine("신규유저");
                //초기 아이템 지급 
                inventory.CreateItem(100);

                //직렬화 : 오브젝트 -> 문자열 
                string serializedJson = JsonConvert.SerializeObject(inventory.ItemList);
                Console.WriteLine(serializedJson);
                //저장 
                File.WriteAllText("./weapon_info.json", serializedJson);
            }
        }
    }
}

 

'C# > 수업 과제' 카테고리의 다른 글

for문 연습 문제  (0) 2022.06.10
디아블로 아이템 출력하기  (0) 2022.06.09

1. App.cs

Hero hero2 = new Hero(3, 3);
            hero2.Move((x, y) =>
            {
                Console.WriteLine("({0}, {1})로 이동 완료", x, y);
            });

            Hero hero3 = new Hero(2);
            Monster mon = new Monster("용", 10);
            hero3.SetTarget(mon);
            hero3.Attack((target) =>
            {
                target.hitAction = (id) =>
                {
                    Console.WriteLine("{0}이 피해를 받았습니다.", id);
                };

                target.Hit(2);
            });

2. Hero.cs

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

namespace Study06
{
    public class Hero
    {
        public Action attackCompleteAction;
        
        private int damage;

        private int x;
        private int y;
        private Monster target;

        // 생성자
        public Hero(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public Hero(int damage)
        {
            this.damage = damage;
        }

        public void Move(Action<int, int> callback)
        {
            callback(this.x, this.y);
        }

        public void Attack(Action<Monster> callback)
        {
            this.target.hp -= this.damage;
            callback(this.target);
        }

        public void SetTarget(Monster target)
        {
            this.target = target;
        }
    }
}

3. Monster.cs

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

namespace Study06
{
    public class Monster
    {
        public Action<string> hitAction;
        public Action<string> dieAction;

        private string id;
        public int hp;
        private int maxHp;

        // 생성자
        public Monster(string id, int maxHp)
        {
            this.id = id;
            this.maxHp = maxHp;
            this.hp = this.maxHp;
        }


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

        public void Hit(int damage)
        {
            this.hp -= damage;
            this.hitAction(this.id);
        }
    }
}

실행 결과

 

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

Json 연습 2 - 캐릭터, 경험치 데이터  (1) 2022.06.21
Json 연습 - 같은 아이템의 개수(amount) 증가  (0) 2022.06.20
2차원 배열 맵타일  (0) 2022.06.15
2048 왼쪽 이동  (0) 2022.06.15
인벤토리 예제  (0) 2022.06.14

1. App.cs

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

namespace Study05
{
    public class App
    {
        int[,] map;

        // 생성자
        public App()
        {
            this.CreateMap();
            Hero hero = new Hero(map);

            hero.MoveDown();
            this.DrawMap();
        }

        public void CreateMap()
        { 
            this.map = new int[,]
            {
                {0, 0, 0, 0},
                {0, 0, 0, 0},
                {-1, -1, 0, 0},
                {0, 0, 0, -1}
            };
        }


        public void DrawMap()
        {
            for (int i = 0; i < this.map.GetLength(0); i++)
            {
                for (int j = 0; j < this.map.GetLength(1); j++)
                {
                    Console.Write("{0} ", this.map[i, j]);
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }
    }
}

2. hero.cs

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

namespace Study05
{
    public class Hero
    {
        // id, 공격력
        public int heroId = 10;
        public int damage = 10;
        private int row = 0;
        private int col = 0;
        private int[,] map;

        // 생성자
        public Hero(int[,] map)
        {
            this.map = map;
            this.map[0, 0] = this.heroId;
        }

        public void Location(int row, int col)
        {
            this.row = row;
            this.col = col;
        }

        public void MoveRight()
        {
            int prevCol = this.col;
            int nextCol;

            if (prevCol >= 3)
            {
                Console.WriteLine("이동할 수 없습니다.");
            }
            else
            {
                prevCol = this.col;
                nextCol = this.col + 1;

                this.map[this.row, prevCol] = 0;
                this.map[this.row, nextCol] = this.heroId;

                this.col = nextCol;
            }
            
        }

        public void MoveLeft()
        {
            int prevCol = this.col;
            int nextCol;

            if (prevCol <= 0)
            {
                Console.WriteLine("이동할 수 없습니다.");
            }
            else
            {
                prevCol = this.col;
                nextCol = this.col - 1;

                this.map[this.row, prevCol] = 0;
                this.map[this.row, nextCol] = this.heroId;

                this.col = nextCol;
            }
        }

        public void MoveDown()
        {
            int prevRow = this.row;
            int nextRow;

            if (prevRow >= 3)
            {
                Console.WriteLine("이동할 수 없습니다.");
            }
            else
            {
                prevRow = this.row;
                nextRow = this.row + 1;

                this.map[prevRow, this.col] = 0;
                this.map[nextRow, this.col] = this.heroId;

                this.row = nextRow;
            }
        }

        public void MoveUp()
        {
            int prevRow = this.row;
            int nextRow;

            if (prevRow <= 0)
            {
                Console.WriteLine("이동할 수 없습니다.");
            }
            else
            {
                prevRow = this.row;
                nextRow = this.row - 1;

                this.map[prevRow, this.col] = 0;
                this.map[nextRow, this.col] = this.heroId;

                this.row = nextRow;
            }
        }

        // 실행 X
        public void Colide()
        {
            int row = this.row;
            int col = this.col;
            for (int i = 0; i < this.map.GetLength(0); i++)
            {
                for (int j = 0; j < this.map.GetLength(1); j++)
                {
                    if (this.map[i, j] == -1)
                    {
                        this.map[this.row, this.col] = this.heroId;
                        Console.WriteLine("이동할 수 없습니다.");
                    }
                }
            }
        }
    }
}

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

Json 연습 - 같은 아이템의 개수(amount) 증가  (0) 2022.06.20
대리자 연습  (0) 2022.06.16
2048 왼쪽 이동  (0) 2022.06.15
인벤토리 예제  (0) 2022.06.14
22.06.14 - property, get-set메서드, interface  (0) 2022.06.14

+ Recent posts