대리자 콜백 부분이랑 / 이펙트가 에니메이션이 아니고 파티클 시스템이라 시간 많이 잡아 먹음 ㅜㅜ

시간 관계상 누르면 도끼 생성해서 던지는것으로 대체 

> 예제

using UnityEngine;
using UnityEngine.SceneManagement;

public class ExampleCode : MonoBehaviour
{
    void Start()
    {
    	  DonDestroyOnLoad();
        // Start는 최초 씬에서만 호출된다.
    }

    void OnEnable()
    {
    	  // 씬 매니저의 sceneLoaded에 체인을 건다.
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    // 체인을 걸어서 이 함수는 매 씬마다 호출된다.
    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        Debug.Log("OnSceneLoaded: " + scene.name);
        Debug.Log(mode);
    }

    void OnDisable()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }
}

 

> 로비 씬에서 인게임 씬에 데이터 넘겨주기

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

public class Lobby : MonoBehaviour
{
    public Button btn1;
    public Button btn2;
    public int id;


    // Start is called before the first frame update
    void Start()
    {
        this.btn1.onClick.AddListener(() =>
        {
            log("1");
            SceneManager.sceneLoaded += SceneLoad; // 씬 로드 될 때 실행
            SceneManager.LoadScene("Ingame");
        });

        this.btn2.onClick.AddListener(() =>
        {
            log("2");
            SceneManager.sceneLoaded += SceneLoad;
            SceneManager.LoadScene("Ingame");
        });
    }

    private void SceneLoad(Scene scene, LoadSceneMode mode)
    {

        log("[Lobby] 델리게이트");
        this.id = 100;
        GameObject inGameGo = GameObject.Find("Ingame");
        var ingame = inGameGo.GetComponent<Ingame>();
        ingame.Init(this.id);
    }

    // Update is called once per frame
    void Update()
    {
    }

    public static void log(object data) { Debug.Log(data); }
}

'c# 강의 > 유니티' 카테고리의 다른 글

▶ 유니티/싱글톤 - DataManager  (0) 2020.05.12
▶ 마우스 이벤트  (0) 2020.05.11
20200511 - 현재까지 패키지 구성  (0) 2020.05.11
20200511 - Scene  (0) 2020.05.11
20200511 - FindWithTag (자주 쓰이는 예제 필요)  (0) 2020.05.11

> 정리

> 클래스
- : MonoBehaviour 삭제

> 생성자 
- private DataManager()  디셔너리 초기화

> 멤버
- private static DataManager instance;
- priavte Dictionary<int, data타입> dic타입datas;

> 인스턴스 메소드
- public static DataManager GetInstance(){
    if(DataManager.instance == null) DataManager.instance = new DataManager();
    return DataManager.instance;
}

> JSON Data 파일 직렬화
- LoadDatas();
- Resources.Load("Data/chacacter_data") <-- Object 타입 리턴
- Json파일은 TextAsset타입으로 받을수 있다.
- TextAsset textAsset = Resources.Load("Data/character_data") as TextAsset;
- string json = textAsset.text;
- data.cs 만들어논 타입[]로 직렬화 
- 디셔너리 =  타입[].ToDictionary( x => x.id);

> data 값 리턴해주는 메소드들 작성

 

> code 참고

더보기
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Newtonsoft.Json;

public class DataManager
{
    private static DataManager instance;
    private Dictionary<int, CharacterData> dicCharacterDatas;


    private DataManager()
    {
        this.dicCharacterDatas = new Dictionary<int, CharacterData>();
    }

    public DataManager GetInstance()
    {
        if (DataManager.instance == null)
        {
            DataManager.instance = new DataManager();
        }
        return DataManager.instance;
    }

    public void LoadData()
    {
        TextAsset textAsset = Resources.Load("data/character_data") as TextAsset;
        string json = textAsset.text;
        Debug.Log(json);

        CharacterData[] arrCharacterData = JsonConvert.DeserializeObject<CharacterData[]>(json);

        this.dicCharacterDatas = arrCharacterData.ToDictionary(x => x.id);

    }

    public CharacterData GetCharacterDataById(int id)
    {
        return this.dicCharacterDatas[id];
    }


}

'c# 강의 > 유니티' 카테고리의 다른 글

20200512 - 델리게이트 / 대리자  (0) 2020.05.12
▶ 마우스 이벤트  (0) 2020.05.11
20200511 - 현재까지 패키지 구성  (0) 2020.05.11
20200511 - Scene  (0) 2020.05.11
20200511 - FindWithTag (자주 쓰이는 예제 필요)  (0) 2020.05.11
public class ExampleClass : MonoBehaviour {
    void Update() { 
        //  0, 1, 2에 따라 마우스 [왼쪽버튼], [오른쪽버튼], [휠버튼]

        if (Input.GetMouseButton (0))
            Debug.Log("마우스 버튼을 누르는 동안");
        
        if (Input.GetMouseButtonDown (1))
            Debug.Log("마우스 버튼을 누른 순간");
        
        if (Input.GetMousebuttonUp (2))
            Debug.Log("마우스 버튼을 눌렀다 때는 순간.");
     // Input.mousePositio  마우스 클릭한 좌표값 얻을수 있음
    }
}
Assets
ㄴ ArtResources
ㄴ Resources
    ㄴ Data
    ㄴ Prefabs
ㄴ Scenes
ㄴ Scripts
    ㄴ Data
ㄴ Textures

 

'c# 강의 > 유니티' 카테고리의 다른 글

▶ 유니티/싱글톤 - DataManager  (0) 2020.05.12
▶ 마우스 이벤트  (0) 2020.05.11
20200511 - Scene  (0) 2020.05.11
20200511 - FindWithTag (자주 쓰이는 예제 필요)  (0) 2020.05.11
20200508 - 프리팹  (0) 2020.05.08

 

> 정리


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using Newtonsoft.Json;

public class App : MonoBehaviour
{
    float timer;
    int logoWaitingTime;
    int titleWaitingTime;

    private void Awake()
    {
          UnityEngine.Object.DontDestroyOnLoad(this);
    }

    void Start()
    {
        this.timer = 0.0f; // 타이머
        this.logoWaitingTime = 1; // 로고 시간
        this.titleWaitingTime = 1; // 타이틀 시간
    }

    // Update is called once per frame
    void Update()
    {
        this.timer += Time.deltaTime;

        if (this.timer > logoWaitingTime){
            SceneManager.LoadScene("Logo");
        }

        if (this.timer > titleWaitingTime){
            SceneManager.LoadScene("Title");
            this.timer = 0.0f;
        }
    }
}

 

 

> 씬 적용 순서

 

 

 


강의중 기록

 

 

 

App - 로고 - 타이틀 - 로딩화면 - 로비 - 인게임

App: 진입씬

여러가지 씬들은 전환될수 있다

 

  • 씬 (로고, 타이틀)
  • 팝업: 닫기 버튼이 무조건 있음
  • 페이지: 뒤로가기가 무조건 있음

// 팝업과 페이지는 씬으로 보지 않음


 

 

 

 

 

 

 


 

 

 

 

 

 

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

public class App : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // logo 씬으로 전환
        SceneManager.LoadScene("logo");
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void log(object data)
    {
        Debug.Log(data);
    }
}

 

> app -> logo -> title 

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

public class App : MonoBehaviour
{
    // Start is called before the first frame update

    private void Awake()
    {
        UnityEngine.Object.DontDestroyOnLoad(this);
    }

    void Start()
    {
        // logo 씬으로 전환
        SceneManager.LoadScene("logo");
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void log(object data)
    {
        Debug.Log(data);
    }
}

 

 

 

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

public class Title : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            this.log("down click");

            SceneManager.LoadScene("Lobby");
        }

        if (Input.GetMouseButtonUp(0))
        {
            this.log("up click");
            SceneManager.LoadScene("Lobby");

        }
    }

    void log(object data)
    {
        Debug.Log(data);
    }
}

 

 

    private void Awake()
    {
       var mainCamGo = GameObject.FindWithTag("Player");

        Debug.Log(mainCamGo.name);
    }

'c# 강의 > 유니티' 카테고리의 다른 글

20200511 - 현재까지 패키지 구성  (0) 2020.05.11
20200511 - Scene  (0) 2020.05.11
20200508 - 프리팹  (0) 2020.05.08
20200507 - 캐릭터 생성 및 무기 장착  (0) 2020.05.08
20200508 - 벡터1  (0) 2020.05.08

> GameObject 가 파일화 된 것

 

 

 

클론 프리팹 연결 해제

 

폴더 이름 대소문자 까지 같아야함 위치는 상관없음

 

Prefabs 폴더 생성

 

 


> 리소스 불러오기

public GameObject heroPrefab;

void Start(){
this.heroPrefab =  Resources.Load("Prefabs/ch_01_01") as GameObject;
        Debug.Log(this.heroPrefab);
        
        }

 

 

 


 

 

1. prefab을 로드 한다(Hero, ch_01_01 )

-> Resources.Load(경로) 확장자 제외 Assets/Resources 까지 상위 폴더 경로 필요

    Resources.Load(경로) as GameObject;

-> Resources.Load<GameObject>(path) 가능하다.

 

2. Hero 프리팹을 Instantiate 한다 -> Hero 프리팹의 Clone게임오브젝트 생성됨.

 

3. Hero컴포넌트를 부착

  ->  this.heroPrefab.AddComponent<Hero>();

 

4. Model(ch_01_01) 프리팹을 Instantiate 한다

-> ch_01_01 프리팹의 Clone 게임오브젝트 생성됨

 

5. ch_01_01게임 오브젝트(Clone)의 부모로 Hero 게임 오브젝트 (Clone) 를 설정

 this.transform.SetParent(paransfrom);

this.transform.SetParent(paransfrom, false);

 

'c# 강의 > 유니티' 카테고리의 다른 글

20200511 - Scene  (0) 2020.05.11
20200511 - FindWithTag (자주 쓰이는 예제 필요)  (0) 2020.05.11
20200507 - 캐릭터 생성 및 무기 장착  (0) 2020.05.08
20200508 - 벡터1  (0) 2020.05.08
20200508 - 복습  (0) 2020.05.08

 

 

 

 


 

> Code

더보기

> App.cs

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


public class App : MonoBehaviour
{
    public Button btn;
    public GameObject heroPrefab;
    public GameObject weaponPrefab;

    private void Start()
    {
        this.btn.onClick.AddListener(() => {
            var heroModelGo = this.CreateModel();
            var weaponGo = this.CreateWeapon();
            var dummyRHand = heroModelGo.GetComponent<HeroModel>().dummyRHand;
            weaponGo.transform.SetParent(dummyRHand, false);
        });
    }

    private GameObject CreateModel()
    {
        return Instantiate(this.heroPrefab);
    }
    private GameObject CreateWeapon()
    {
        return Instantiate(this.weaponPrefab);
    }

}

 

>HeroModel.cs 

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

public class HeroModel : MonoBehaviour
{

    public Transform dummyRHand;

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

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

'c# 강의 > 유니티' 카테고리의 다른 글

20200511 - FindWithTag (자주 쓰이는 예제 필요)  (0) 2020.05.11
20200508 - 프리팹  (0) 2020.05.08
20200508 - 벡터1  (0) 2020.05.08
20200508 - 복습  (0) 2020.05.08
20200507 - 오브젝트 생성 및 부모설정(Instantiate)  (0) 2020.05.08
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class App : MonoBehaviour
{

    public GameObject hero;
    public GameObject monster;

    void Start()
    {
        float distance = Vector3.Distance(this.hero.transform.position, this.monster.transform.position);

        Vector3 c = this.hero.transform.position - this.monster.transform.position;
        // 방향은 모른다.
        Debug.Log(c.magnitude);

        // 정규화 시켜서 길이를 1로 만든다. 그럼 방향을 알수 있다.
        Debug.Log(c.normalized);
        
    }
}

ctor3 distance 는 벡터의 길이
길이가 1인 벡터를 만든다. 단위 벡터 
비교하기 쉽게하기 위해

'c# 강의 > 유니티' 카테고리의 다른 글

20200508 - 프리팹  (0) 2020.05.08
20200507 - 캐릭터 생성 및 무기 장착  (0) 2020.05.08
20200508 - 복습  (0) 2020.05.08
20200507 - 오브젝트 생성 및 부모설정(Instantiate)  (0) 2020.05.08
20200507 - 애니메이션2  (0) 2020.05.08

> gameObject의 App 컴포넌트가 비활성화시 Awake 함수 호출됨

그러나 gameObject 가 비활성화시 Awake 함수 호출안됨

App 컴포넌트가 활성화 되면 Start함수는 한번만 호출됨

App 컴포넌트가 활성화 되면 update 매프레임마다 호출되지만 비활성화시 update함수 호출 안됨

App 컴포넌트에 ㅂ줕어 있는 gameObject가 비활성화시 update함수 호출 안됨

플레이를 멈췄을 경우 Ppp컴포넌트의 OnDestory 함수 호출됨

 

 

 

 

 


 

> 오브젝트,스크립트 설정

 

 


> App.cs

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class App : MonoBehaviour
{
    public Hero hero;
    public GameObject[] arrHeroModels;
    public string modelName;

    // Start is called before the first frame update
    void Start()
    {
      //  this.modelName = "";
        Debug.Log(this.modelName.ToString());

        this.hero.Init(this.CreateModel(this.modelName));
    }

    private GameObject CreateModel(string modelName)
    {
        GameObject foundModel = null;
        foreach (GameObject model in this.arrHeroModels)
        {
            if (model.name == modelName)
            {
                foundModel = model;
                break;
            }
        }
        Debug.LogFormat("model: {0}", foundModel);

        //게임오브젝트를 생성함 
        var newModel = UnityEngine.Object.Instantiate(foundModel);
        return newModel;
    }
}

 

> Hero.cs

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    public GameObject hero;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    public void Init(GameObject newModel)
    {
        //newModel.transform.SetParent(this.transform);
        newModel.transform.SetParent(this.transform, false);
        Debug.Log("zzzz"); 
    }
    
}

'c# 강의 > 유니티' 카테고리의 다른 글

20200508 - 벡터1  (0) 2020.05.08
20200508 - 복습  (0) 2020.05.08
20200507 - 애니메이션2  (0) 2020.05.08
20200507 - 애니메이션  (0) 2020.05.07
20200507 - 유니티(MonoBehaviour), 라이프사이클  (0) 2020.05.07

 

> 타격 프레임 code

더보기
public GameObject model;
public Button btn;
public int attackFrame;

private Animation anim;
private AnimationState state;

public int attackFrame;
private float totalFrames;
private float attackTime;
private float elapsedTimeAttack;  //타격 시간 
private float elapsedTimeAttackComplete;  //공격 애니메이션 종료 시간 
private bool isAttackAnimationPlaying;  //공격애니메이션 실행중인지 
private bool isAttack;  //공격을 했는지 

void Start()
{
    this.anim = this.model.GetComponent<Animation>();
    this.state = this.anim["attack_sword_01"];
    this.totalFrames = state.length * state.clip.frameRate;
    // fps의 뜻 (60fps, 30fps, 29.97fps, 24fps) 
    // 영상에서 매 초당 보여지는 이미지 장면의 수, 즉 프레임이 재생되는 속도

    // 22 : 8 = 0.733 : x 
    // 8 * 0.733 / 22 = x 
    this.attackTime =
        this.attackFrame * state.length / this.totalFrames;

}

void Update()
{
    //공격 애니메이션 실행 중이라면 
    if (this.isAttackAnimationPlaying)
    {
        //경과시간 누적 
        this.elapsedTimeAttack += Time.deltaTime;
        if (this.elapsedTimeAttack >= this.attackTime)
        {
            if (!this.isAttack)
            {
                //공격을 했는지 
                Debug.Log("타격!");
                this.isAttack = true;
            }
        }

        this.elapsedTimeAttackComplete += Time.deltaTime;

        if (this.elapsedTimeAttackComplete >= this.state.length)
        {
            //공격 애니메이션 종료 
            this.elapsedTimeAttack = 0;
            this.elapsedTimeAttackComplete = 0;
            this.isAttack = false;
            this.isAttackAnimationPlaying = false;
            this.anim.Play("idle@loop");
            Debug.Log("공격 애니메이션 종료");
        }
    }
}

 

> 이동

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
 
public class App : MonoBehaviour
{
    public Animation anim;
    public Button btnMoveForward;
    public Button btnMoveBack;
    public Button btnMoveLeft;
    public Button btnMoveRight;
    public Button btnStop;
    public float speed;
 
    private bool isMove;
    private Vector3 dir;
 
 
    void Start()
    {
        this.btnMoveForward.onClick.AddListener(() => {
            this.Move(Vector3.forward);
        });
 
        this.btnMoveBack.onClick.AddListener(() => {
            this.Move(Vector3.back);
        });
 
        this.btnMoveRight.onClick.AddListener(() => {
            this.Move(Vector3.right);
        });
 
        this.btnMoveLeft.onClick.AddListener(() => {
            this.Move(Vector3.left);
        });
 
 
        this.btnStop.onClick.AddListener(() => {
            Debug.Log("Stop");
            this.Stop();
        });
    }
 
    private void Move(Vector3 dir) {
        this.dir = dir;
        this.anim.Play("run@loop");
        this.isMove = true;
    }
 
    private void Stop() {
        this.isMove = false;
        this.anim.Play("idle@loop");
    }
 
    private void Update()
    {
        if (this.isMove) {
            this.anim.gameObject.transform.Translate(this.dir * this.speed * Time.deltaTime);
        }
    }
}

* 방향, 속도, 시간

 

> 오브젝트와의 거리 계산

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
 
public class App : MonoBehaviour
{
    public GameObject model;
    public GameObject target;
    public Button btnMove;
 
    private bool isMove;
    private Animation anim;
 
    void Start()
    {
        this.anim = this.model.GetComponent<Animation>();
 
        this.btnMove.onClick.AddListener(() => {
            this.Move();
        });
    }
 
    private void Move() {
        this.isMove = true;
        this.anim.Play("run@loop");
    }
 
    private void Stop() {
        this.isMove = false;
        this.anim.Play("idle@loop");
    }
 
    private void Update()
    {
        if (this.isMove) {
            //float
            var distance = Vector3.Distance(model.transform.position,
                target.transform.position);
 
            //move
            var speed = 1.2f;
            var dir = Vector3.forward;
            this.model.transform.Translate(speed * dir * Time.deltaTime);
 
            Debug.Log(distance);
 
            if (distance <= 0.03f)
            {
                this.model.transform.position = this.target.transform.position;
                this.Stop();
            }
        }
 
    }
}

 

> 히트&다이(프레임계산 적용)

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
 
public class App : MonoBehaviour
{
    public GameObject model;
    public GameObject target;
    public Button btnMove;
    public float attackDely;
 
    private bool isMove;
    private bool isAttack;
    private Animation heroAnim;
    private Animation monsterAnim;
    private float elapsedTime;
    private int attackFrame;
    private float totalFrames;
    private float attackTime;
    private int attackCount;    //공격 몇번 했는지 카운트 
    private bool isImpact;   //타격 했나?
    private AnimationState attackAnimState;
    private bool isMonsterHit;
    private float monsterHitElapsedTime;
    private float monsterAttackDamageAnimLength;
    private float attackDelayElapsedTime;
    private bool isContinousAttack;
    private bool isMonsterDie;
    private float monsterDieElapsedTime;
    private float monsterDieAnimationLength;
 
 
    void Start()
    {
        //init
        this.attackFrame = 8;
        this.heroAnim = this.model.GetComponent<Animation>();
        this.monsterAnim = this.target.GetComponent<Animation>();
        this.monsterAttackDamageAnimLength = this.monsterAnim["Anim_Damage"].length;
        this.monsterDieAnimationLength = this.monsterAnim["Anim_Death"].length;
 
        this.attackAnimState = this.heroAnim["attack_sword_01"];
        this.totalFrames = this.attackAnimState.length * this.attackAnimState.clip.frameRate;
        //22 : 8 = 0.733 : x 
        // x = 8 * 0.733 / 22
        this.attackTime = this.attackFrame * this.attackAnimState.length / this.totalFrames;
 
        this.btnMove.onClick.AddListener(() => {
            this.Move();
        });
    }
 
    private void Move() {
        this.isMove = true;
        this.heroAnim.Play("run@loop");
    }
 
    private void Stop() {
        this.isMove = false;
        this.Idle();
    }
 
    private void Idle() {
        this.heroAnim.Play("idle@loop");
    }
 
    private void Attack() {
        this.isAttack = true;
        this.heroAnim.Play("attack_sword_01");
    }
 
    private void MonsterHit() {
        this.isMonsterHit = true;
        this.monsterAnim.Play("Anim_Damage");
    }
 
    private void MonsterIdle() {
        this.isMonsterHit = false;
        this.monsterAnim.Play("Anim_Idle");
    }
 
    private void Update()
    {
        if (this.isMove) {
            //float
            var distance = Vector3.Distance(model.transform.position,
                target.transform.position);
 
            //move
            var speed = 1.2f;
            var dir = Vector3.forward;
            this.model.transform.Translate(speed * dir * Time.deltaTime);
 
            if (distance <= 0.5f)
            {
                this.Stop();
                this.Attack();
            }
        }
 
        if (this.isAttack) {
 
            this.elapsedTime += Time.deltaTime;
            if (this.elapsedTime >= attackTime)
            {
                if (this.isImpact == false) {
                    isImpact = true;
                    this.MonsterHit();
                }
            }
 
            if (this.elapsedTime >= this.attackAnimState.length) {
                //공격 완료 
                this.isAttack = false;
                this.isImpact = false;
                this.elapsedTime = 0;
                this.attackCount++;
 
                Debug.Log(this.attackCount);
                
                this.Idle();
 
                if (this.attackCount >= 3) {
                    this.isContinousAttack = false;
                    this.MonsterDie();
                }
 
                
            }
        }
 
 
        if (this.isMonsterHit) {
            this.monsterHitElapsedTime += Time.deltaTime;
            if (this.monsterHitElapsedTime >= monsterAttackDamageAnimLength)
            {
                this.monsterHitElapsedTime = 0;
                this.MonsterIdle();
                this.isContinousAttack = true;
            }
        }
 
        if (this.isContinousAttack) {
            this.attackDelayElapsedTime += Time.deltaTime;
            if (this.attackDelayElapsedTime >= this.attackDely) {
                this.attackDelayElapsedTime = 0;
                this.isContinousAttack = false;
                this.Attack();
            }
        }
 
        if (this.isMonsterDie) {
            this.monsterDieElapsedTime += Time.deltaTime;
            if (this.monsterDieElapsedTime >= this.monsterDieAnimationLength) {
                UnityEngine.Object.Destroy(this.target.gameObject);
            }
        }
 
    }
 
    private void MonsterDie()
    {
        this.monsterAnim.Play("Anim_Death");
        this.isMonsterDie = true;
    }
}
 

 

using UnityEngine.UI; // 버튼 사용하려면  2019.3.7

public class App : MonoBehaviour
{
    public GameObject model; //구멍을 뚫어
    public Button btn; // 버튼 인스턴스

 

> 버튼 클릭시 리스너

 this.btn.onClick.AddListener(메소드());
        this.btn.onClick.AddListener(() =>
        {
            Debug.Log("test1");
        });

> 프레임 시간

timer += Time.deltaTime;

 

> 애니메이션 컴포넌트 먼저가져와야함(model은 GameObaect)

  var anim = this.model.GetComponent<Animation>(); // 애니 컴포넌트 가져와

 

> 애니메이션

var state = anim["attack_sword_01"]; // 애니메이션 컴포넌트 활용

 anim.Play("attack_sword_01"); //애니메이션 실행

 


 

MonoBehaviour

Awake - Start - Update

 

> Awake

- 인스턴스가 메모리에 오라가고,  로딩 될 때, 호출

- 마치 생성자와 같다.
- 미리 정의되어 있다. 

- 종료 될 때까지 한 번만 실행된다. 

 

 

> start (스크립트가 실행 될 때 한번)

Start는 Update메소드가 처음 호출되기 바로 전에 호출됩니다.

 

 

> Update

- Update는 MonoBehaviour가 활성화 되어 있는 경우에, 매 프레임마다 호출됩니다.

- Update는 게임 동작을 수행하기위해 가장 흔하게 사용되는 기능입니다.

지난 Update호출로부터의 경과시간을 받아오고 싶은 경우에, Time.deltaTime을 사용합니다. Behaviour가 활성화 되어있는 경우에만 호출됩니다. 사용자 컴포넌트의 기능을 제공하기 위해 함수를 오버라이드(override)해서 사용할 수 있습니다.

 

 


> 라이프사이클

 

 

> 정리 코드 - 참고

더보기
public class App : MonoBehaviour
{
    //인스턴스가 로딩될때 한번만 호출됨 
    //게임오브젝트가 비활성화 일경우 호출 안됨 
    //게임오브젝트가 활성화 이고 컴포넌트가 비활성화 일경우 호출됨 
    private void Awake()
    {
        Debug.Log("App::Awake");
    }
 
    //게임오브젝트가 활성화 되었을경우 호출됨 
    //게임오브젝트가 비활성화 일경우 호출 안됨 
    //게임오브젝트가 활성화 이고 컴포넌트가 비활성화 일경우도 호출 안됨 
    private void OnEnable()
    {
        Debug.Log("App::OnEnable");
    }
 
    //오브젝트가 활성화 상태일경우 업데이트 함수 호출전에 한번만 호출됨 
    void Start()
    {
        Debug.Log("App::Start");
    }
 
    //오브젝트가 활성화 상태일경우 매프레임마다 호출됨 
    void Update()
    {
        Debug.Log("App::Update");
    }
 
    //오브젝트가 비활성화 일경우 호출됨 
    //인스턴스화 될때 게임오브젝트가 비활성화, 컴포넌트가 비활성일경우 호출안됨 
    //인스턴스화 되고 오브젝트또는 컴포넌트가 활성화에서 비활성화 되었을경우 호출됨 
    private void OnDisable()
    {
        Debug.Log("App::OnDisable");
    }
 
    //Object.Destroy 
    //씬 종료
    //오브젝트 존재의 마지막 프레임에 대해 모든 프레임 업데이트를 마친 후 이 함수가 호출됩니다. 
 
    //오브젝트 활성화, 컴포넌트 활성화 : 
    //Awake - OnEnable - Staret - Update - OnDisable - OnDestory 
 
    //오브젝트 활성화, 컴포넌트 비활성화 : 
    //Awake - OnDestory 
 
    //오브젝트 비활성화, 컴포넌트 활성화 : X 
 
 
    private void OnDestroy()
    {
        Debug.Log("App::OnDestroy");
    }
}

'c# 강의 > 유니티' 카테고리의 다른 글

20200507 - 오브젝트 생성 및 부모설정(Instantiate)  (0) 2020.05.08
20200507 - 애니메이션2  (0) 2020.05.08
20200507 - 애니메이션  (0) 2020.05.07
20200506 - 설정2  (0) 2020.05.06
20200506 - 설정1  (0) 2020.05.06

> 구조

- 좌표를 가지는 구조체 백터

- 게임 오브젝트가 구조체 멤버로 가짐

- 캐릭터와 타일은 게임오브젝트를 상속받고 캐릭터는 좌표값을 받아 위치 값을 설정 할 수 있다.

 


내용 추가

 


> 맵 좌표

 

 

> 튜플 (인덱스 <=> 포지션)

 

> 매개변수 한정자

더보기

 

해설 코드

int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod);     // value is now 44

void OutArgExample(out int number)
{
    number = 44;
}

※ out 키워드를 사용하면 참조를 통해 인수를 전달할 수 있습니다.

 

 

 

 

 

 

 

 

 

그리드  - 1유닛 작은 상작

 

 

 

 

더보기

 

 

 

 

 

 

> 후기

- winfrom 을 스터디 하고 싶었던 차에 2048을 winfrom으로 만들어보기로 했다.

- 역시 마쏘는 어마어마한 형들이다.  사용하기 쉽게? 만든느낌을 받으며 적용시킬수 있었다.

- 아카데미시절 눈물나게했던,  JAVA Swing.. 요놈으로 게임만들어본 경험이 큰도움이 됬다.

- 아무래도 수학적인 머리가 부족해서, 2차원배열 정렬하는데, 애좀 먹었다. ㄷㄷ 

- 특히 좌우 정렬 공간지각능력 부족인가 ㅜㅜ

- 자바스크립트의 forEach 관련 메소드들이 있엇다면 좀더 쉽게 했을텐데, 머리가 나쁘면 몸이 고생하는것 을 다시 느꼈다.

- 스코어 누적은 잘되는지, 2048만들어서 클리어 해봐야하는데 검증 할 기력이 없다. ㄷㄷ

- 개똥같읕 코드로 반복문과 분기문이 아주 지저분한데, 가볍게 잘돌아가는것 같아 신기했다. 

 

> 실행파일

lioncho_2048.exe
0.15MB

 

> 게임 이미지

더보기
시작 화면

 

스코어 및 연산

 

칸 다차면 종료

 

 

> code

더보기
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace _20200502
{
    public partial class form : Form
    {
        Random random;

        int[,] array;
        bool start = true;
        int totalScore;

        int x;
        int y;
        int randomNum1;
        int randomNum2;

        Control newNumTemp;


        public form()
        {
            InitializeComponent();

            this.Init();
            this.StartGame();

            this.TableInit();

            this.IsNumberBackgroundColor();

        }

        public void Init()
        {
            this.random = new Random();
            this.newNumTemp = new Control();
        }

        // up 버튼 입력시 해당 방향으로 재정렬
        public void UpDataSort()
        {
            int[,] newArr = new int[4, 4];

            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (this.array[i, j] > 0)
                    {
                        for (int k = 0; k < newArr.GetLength(1); k++)
                        {
                            if (newArr[k, j] == 0)
                            {
                                if (k != 0)
                                {
                                    if (newArr[k - 1, j] == this.array[i, j])
                                    {
                                        newArr[k - 1, j] = this.array[i, j] * 2;
                                        this.totalScore += newArr[k - 1, j];
                                        break;
                                    }
                                }
                                newArr[k, j] = this.array[i, j];
                                break;
                            }
                        }
                    }
                }
            }
            this.array = newArr;
        }

        //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

        // down 버튼 입력시 해당 방향으로 재정렬
        public void DownDataSort()
        {
            int[,] newArr = new int[4, 4];


            for (int i = 3; i >= 0; i--)
            {
                for (int j = 3; j >= 0; j--)
                {
                    if (this.array[i, j] > 0)
                    {
                        for (int k = 3; k >= 0; k--)
                        {
                            if (newArr[k, j] == 0)
                            {
                                if (k != 3)
                                {
                                    if (newArr[k + 1, j] == this.array[i, j])
                                    {
                                        newArr[k + 1, j] = this.array[i, j] * 2;
                                        this.totalScore += newArr[k + 1, j];
                                        break;
                                    }
                                }
                                newArr[k, j] = this.array[i, j];
                                break;
                            }
                        }
                    }
                }
            }
            this.array = newArr;
        }

        //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

        // left 버튼 입력시 해당 방향으로 재정렬
        public void LeftDataSort()
        {
            int[,] newArr = new int[4, 4];

            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    // 값있을 경우
                    if (this.array[j, i] > 0)
                    {

                        // 행 
                        for (int k = 0; k < newArr.GetLength(1); k++)
                        {

                            if (newArr[j, k] == 0)
                            {
                                if (k != 0)
                                {
                                    if (newArr[j, k - 1] == this.array[j, i])
                                    {
                                        newArr[j, k - 1] = this.array[j, i] * 2;
                                        this.totalScore += newArr[j, k - 1];
                                        break;
                                    }
                                }
                                newArr[j, k] = this.array[j, i];
                                break;
                            }
                        }
                    }
                }
            }
            this.array = newArr;
        }

        //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

        // right 버튼 입력시 해당 방향으로 재정렬
        public void RightDataSort()
        {
            int[,] newArr = new int[4, 4];

            for (int i = 3; i >= 0; i--)
            {
                for (int j = 0; j < 4; j++)
                {
                    // 값있을 경우
                    if (this.array[j, i] > 0)
                    {
                        // 행 
                        for (int k = 3; k >= 0; k--)
                        {

                            if (newArr[j, k] == 0)
                            {
                                if (k != 3)
                                {
                                    if (newArr[j, k + 1] == this.array[j, i])
                                    {
                                        newArr[j, k + 1] = this.array[j, i] * 2;
                                        this.totalScore += newArr[j, k + 1];
                                        break;
                                    }
                                }
                                newArr[j, k] = this.array[j, i];
                                break;
                            }
                        }
                    }
                }
            }
            this.array = newArr;
        }

        //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

        // 뷰테이블에 있는 데이터, 로직 배열과 동기화
        public void TableInit()
        {
            this.array = new int[4, 4];

            foreach (Control ctrl in tableLayoutPanel1.Controls)
            {
                if (ctrl is Label)
                {
                    var row = tableLayoutPanel1.GetRow(ctrl);
                    var col = tableLayoutPanel1.GetColumn(ctrl);

                    this.array[row, col] = 0;

                    // 값 있는 경우
                    if (ctrl.Text.Length > 0)
                    {
                        int myNum = int.Parse(ctrl.Text);
                        this.array[row, col] = myNum;
                    }
                }
            }
            this.IsNumberBackgroundColor();
        }


        // 뷰 라벨 테이블 비우고 데이터 배열 초기화
        public void NewTable()
        {
            foreach (Control ctrl in tableLayoutPanel1.Controls)
            {
                if (ctrl is Label)
                {
                    ctrl.Text = "";
                }
            }
            this.array = new int[4, 4];
        }

        // 게임 스타트시 초기값 발생
        public void StartGame()
        {
            this.RandomXY();
            this.RandomNum();
            tableLayoutPanel1.GetControlFromPosition(y, x).Text = randomNum2.ToString();

            this.RandomXY();
            this.RandomNum();
            tableLayoutPanel1.GetControlFromPosition(y, x).Text = randomNum1.ToString();
        }

        // 처음에 주어지는 숫자 위치 정하기
        public void RandomXY()
        {
            // 낮은 확률로 처음 주어지는 숫자 위치 중첩 방지
            while (true)
            {
                int tempX = random.Next(0, 4);
                int tempY = random.Next(0, 4);

                if (this.x != tempX && this.y != tempY)
                {
                    this.x = tempX;
                    this.y = tempY;
                    break;
                }
            }
        }


        // 처음에 주어지는 숫자 2,4 난수 발생 로직
        public void RandomNum()
        {
            while (true)
            {
                int tempNum1 = random.Next(2, 5);
                int tempNum2 = random.Next(2, 5);

                bool cheeck1 = false;
                bool cheeck2 = false;

                // 처음만 두개의 숫자 발생
                if (this.start)
                {
                    if (tempNum2 == 2 || tempNum2 == 4)
                    {
                        this.randomNum1 = tempNum2;
                        cheeck1 = true;
                    }
                }

                if (tempNum1 == 2 || tempNum1 == 4)
                {
                    this.randomNum2 = tempNum1;
                    cheeck2 = true;
                }

                if (cheeck1 && cheeck2)
                {
                    break;
                }
            }

        }

        // 턴 이후 지급되는 랜덤 숫자 생성
        public void CreateNewNum()
        {
            while (true)
            {
                this.RandomXY();
                if (this.array[this.x, this.y] == 0)
                {
                    break;
                }
            }
            this.newNumTemp.ForeColor = Color.Black;
            this.RandomNum();
            this.array[this.x, this.y] = this.randomNum2;
            tableLayoutPanel1.GetControlFromPosition(y, x).Text = this.randomNum2.ToString();

            tableLayoutPanel1.GetControlFromPosition(y, x).ForeColor = Color.IndianRed;

            this.newNumTemp = tableLayoutPanel1.GetControlFromPosition(y, x);

            logBox.Items.Add($"신규랜덤난수:[{x},{y}]:{this.randomNum2}");
        }



        // new버튼 이벤트 발생시 초기화
        public void GameReset()
        {
            this.array = new int[4, 4];
            this.start = true;
            this.totalScore = 0;


            this.ViewReset();
            this.StartGame();
            this.TableInit();
            this.SetScoreView();
        }

        // 전체 테이블 라벨 지우고, log창 지우기
        public void ViewReset()
        {
            foreach (Control ctrl in tableLayoutPanel1.Controls)
            {
                if (ctrl is Label)
                {
                    ctrl.Text = "";
                }
            }
            logBox.Items.Clear();
        }

        // sort된 배열, 뷰 테이블라벨에 재적용
        public void UpdateView()
        {
            foreach (Control ctrl in tableLayoutPanel1.Controls)
            {
                if (ctrl is Label)
                {
                    var row = tableLayoutPanel1.GetRow(ctrl);
                    var col = tableLayoutPanel1.GetColumn(ctrl);
                    ctrl.Text = "";

                    // 값 있는 경우
                    if (this.array[row, col] > 0)
                    {
                        ctrl.Text = this.array[row, col].ToString();
                    }
                }
            }
        }

        // 빈배열 있는지 체크
        public bool EndGameCheck()
        {
            foreach (var item in this.array)
            {
                if (item == 0)
                {
                    return true;
                }
            }
            return false;
        }

        // 게임 클리어 체크
        public bool ClearGameCheck()
        {
            foreach (var item in this.array)
            {
                if (item.Equals(2048))
                {
                    return true;
                }
            }
            return false;
        }

        // 연산값에 대한 뷰 컬러처리
        public void IsNumberBackgroundColor()
        {
            int checkNum = 0;
            foreach (Control ctrl in tableLayoutPanel1.Controls)
            {
                if (ctrl is Label)
                {
                    ctrl.BackColor = Color.Gainsboro;

                    if (ctrl.Text != "")
                    {
                        checkNum = int.Parse(ctrl.Text);

                        if (checkNum == 8)
                        {
                            ctrl.ForeColor = Color.WhiteSmoke;
                            ctrl.BackColor = Color.LightSalmon;
                        }
                        else if (checkNum == 16)
                        {
                            ctrl.ForeColor = Color.WhiteSmoke;
                            ctrl.BackColor = Color.LightCoral;
                        }
                        else if (checkNum == 32)
                        {
                            ctrl.ForeColor = Color.WhiteSmoke;
                            ctrl.BackColor = Color.Coral;
                        }
                        else if (checkNum >= 64)
                        {
                            ctrl.ForeColor = Color.WhiteSmoke;
                            ctrl.BackColor = Color.Tomato;
                        }
                        else
                        {
                            ctrl.BackColor = Color.Silver;
                            ctrl.ForeColor = Color.Black;
                        }
                    }

                    if (ctrl.Text == "")
                    {
                        ctrl.BackColor = Color.Silver;
                        ctrl.ForeColor = Color.Black;
                    }
                }
            }
        }

        // 스코어 뷰에 누계 적용
        public void SetScoreView()
        {
            scoreLabel.Text = this.totalScore.ToString();
        }

        // 개발시 배열 확인용 매소드
        public void ArrayPrint()
        {
            for (int i = 0; i < this.array.GetLength(0); i++)
            {
                for (int j = 0; j < this.array.GetLength(1); j++)
                {
                    Console.Write("[{0}, {1}]:{2} ㅣ", i, j, this.array[i, j]);
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }

        //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ 방향킼 버튼 이벤트 리스너 ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
        private void UpBtn_Click(object sender, EventArgs e)
        {
            if (ClearGameCheck()) { MessageBox.Show("게임 클리어!!"); }
            if (EndGameCheck())
            {
                this.UpDataSort();
                this.UpdateView();
                this.CreateNewNum();
                this.IsNumberBackgroundColor();
                this.SetScoreView();
            }
            else
            {
                MessageBox.Show("게임 종료");
            }
        }

        private void DownBtn_Click(object sender, EventArgs e)
        {
            if (ClearGameCheck()) { MessageBox.Show("게임 클리어!!"); }
            if (EndGameCheck())
            {
                this.DownDataSort();
                this.UpdateView();
                this.CreateNewNum();
                this.IsNumberBackgroundColor();
                this.SetScoreView();
            }
            else
            {
                MessageBox.Show("게임 종료");
            }
        }

        private void LeftBtn_Click(object sender, EventArgs e)
        {
            if (ClearGameCheck()) { MessageBox.Show("게임 클리어!!"); }
            if (EndGameCheck())
            {
                this.LeftDataSort();
                this.UpdateView();
                this.CreateNewNum();
                this.IsNumberBackgroundColor();
                this.SetScoreView();
            }
            else
            {
                MessageBox.Show("게임 종료");
            }
        }

        private void RightBtn_Click(object sender, EventArgs e)
        {
            if (ClearGameCheck()) { MessageBox.Show("게임 클리어!!"); }
            if (EndGameCheck())
            {
                this.RightDataSort();
                this.UpdateView();
                this.CreateNewNum();
                this.IsNumberBackgroundColor();
                this.SetScoreView();
            }
            else
            {
                MessageBox.Show("게임 종료");
            }
        }

        // ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ new 버튼  ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

        // newGame 버튼 클릭시 비우고 난수 발생하기
        private void button1_Click(object sender, EventArgs e)
        {
            this.GameReset();
        }

        //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ ?? ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
        private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {

        }

    }
}

연속 출석 했을때 받는 보상을, 누적하면 추가로 주는 보너스 보상으로 생각했었다.

가장 최근에 했던 검은사막m 했던 기억이 나를 지배했다. ㄷㄷ 좀더 귀를 열고 강사님 말씀에 집중해야 할 듯

최근에 과제를 하면서, 확실이 게임 개발은 각 기능의 알고리즘을 이해하는것이 특히나 중요한 것 같다.  

 

 

> 결과

더보기
실행시킨 일자부터 28후 이벤트 종료 / 출석 / 누적 카운트 / 출석or다음날접속 시 today +1

 

2번 다음날 접속시, 하루 소요
같은 아이템 보상시 수량만 추가

 

누적 연속 출석시 추가 보상 

 

하루 소요시, 연속보상 누적 카운트는 초기화

 

만약 5일차 연속보상 수령했는데, 초기화 후 다시 누적해도 해당 연속 보상은 받을수 없다.

 

 

 

> 코드

1. Data.cs

더보기
    class EverydayData
    {
        public int id;
        public int everyday_date;
        public int everyday_item;
        public int everyday_item_amount;
    }
    class ItemData
    {
        public int id;
        public string item_name;
        public string icon_item_image;
        public int amount;
    }

 

 

2. DataManager.cs

더보기
    class DataManager
    {
        private static DataManager singleTone;

        private Dictionary<int, ItemData> dicItemData;
        private Dictionary<int, EverydayData> dicEverydataData;

        private DataManager()
        {
            this.dicEverydataData = new Dictionary<int, EverydayData>();
            this.dicItemData = new Dictionary<int, ItemData>();
        }

        public bool LoadDatas()
        {
            bool reuslt = false;
            string path = "";
            string json = "";

            try
            {
                path = "./data/everyday_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    //   Console.WriteLine(json);
                    this.dicEverydataData = JsonConvert
                        .DeserializeObject<EverydayData[]>(json)
                        .ToDictionary(v => v.id, v => v);
                }

                path = "./data/item_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicItemData = JsonConvert
                           .DeserializeObject<ItemData[]>(json)
                           .ToDictionary(v => v.id, v => v);
                }
                reuslt = true;
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
                throw;
            }
            return reuslt;
        }

        public static DataManager GetInstance()
        {
            if (DataManager.singleTone == null)
            {
                DataManager.singleTone = new DataManager();
                return DataManager.singleTone;
            }
            else
            {
                return DataManager.singleTone;
            }
        }

        public Dictionary<int, EverydayData> GetEverydataDatas()
        {
            return this.dicEverydataData;
        }

        public EverydayData GetEverydayData(int id)
        {
            return this.dicEverydataData[id];
        }

        public Dictionary<int, ItemData> GetItemDatas()
        {
            return this.dicItemData;
        }

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

 

 

3. App.cs

더보기
    class App
    {
        DataManager dm;
        UserInfo info;

        public static DateTime TODAY;
        DateTime endDay;


        public App()
        {
            this.Init();
            this.endDay = TODAY.AddDays(28);

            while (true)
            {
                this.Login();
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine();
                Console.Write("* test 입력 (1번 출석 / 2번 다음날 접속): ");
                string input = Console.ReadLine();
                Console.WriteLine();
                if (TODAY > this.endDay)
                {
                    Console.WriteLine("!!!!! 출석 이벤트 종료 !!!!!");
                    return;
                }
                this.View(input);
                Console.WriteLine();
                TODAY = TODAY.AddDays(1);
                this.info.SaveUserInfoData();

            }
        }

        public void Init()
        {
            dm = DataManager.GetInstance();
            dm.LoadDatas();
            TODAY = DateTime.Now;
            this.info = new UserInfo();
        }

        public void GetItemPrint(ItemData item)
        {
            Console.WriteLine("ㅡㅡㅡㅡ 일간 출석 보상 ㅡㅡㅡㅡ");
            Console.WriteLine("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
            Console.WriteLine($"- {this.info.dayCount}일자 아이템 입니다. 아이템 우편으로 획득");
            Console.WriteLine($"{item.item_name}({item.amount})");
            Console.WriteLine("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
        }

        public void ChainDayPrint(int eventDay, ItemData chainItem, int amount)
        {
            Console.WriteLine("ㅡㅡㅡㅡ 연속 보상 ㅡㅡㅡㅡ");
            Console.WriteLine("□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□");
            Console.WriteLine($"- 누적{this.info.rewardedCount}일 입니다. 아이템 추가증정");
            Console.WriteLine($"{chainItem.item_name}({amount})");
            Console.WriteLine("□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□");
            this.info.RewardedItem(this.info.userId, chainItem);
        }


        public void View(string check)
        {
            var data = dm.GetEverydataDatas();
            List<int> list = new List<int>(data.Keys);

            if (check != "1")
            {
                Console.WriteLine("ㅡㅡㅡ 하루소요 ㅡㅡㅡ");
                Console.WriteLine($"오늘날짜:[{TODAY.Month}월{TODAY.Day}일] / 이벤트 남은일자:[{(this.endDay - TODAY).Days}일]");
                return;
            }


            foreach (var key in list)
            {
                var item = dm.GetItemData(data[key].everyday_item);
                Console.Write($"[{data[key].everyday_date}일]{item.item_name}");
                Console.Write($"({data[key].everyday_item_amount})");
                Console.Write("   ");
                // 줄바꿈
                if (data[key].everyday_date % 7 == 0) { Console.WriteLine(); }
            }
            Console.WriteLine();

            Console.WriteLine($"[출석:{this.info.dayCount}]/[누적:{this.info.rewardedCount}일] / 오늘날짜:[{TODAY.Month}월{TODAY.Day}일] / 이벤트 남은일자:[{(this.endDay - TODAY).Days}일]");

            Console.WriteLine();

            //일일 보상 ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

            // 전체 일정에서 금일 보상에 따른 아이템 찾기
            var todayRewardItemData = data.FirstOrDefault(v => v.Value.everyday_date == this.info.dayCount).Value;

            // 금일 지급할 아이템 키
            int todayRewardItemKey = todayRewardItemData.everyday_item;

            // 금일 지급할 아이템 지급 수량
            int todayRewardItemAmount = todayRewardItemData.everyday_item_amount;

            // 찾은 키로 아이템 가져오기
            ItemData todayRewardItem = dm.GetItemData(todayRewardItemKey);
            todayRewardItem.amount = todayRewardItemAmount;

            this.ItemGet(todayRewardItem, todayRewardItemAmount);

            //연속 보상 ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
            var awChack = this.info.chainDayList.Contains(this.info.rewardedCount);
            if (awChack)
            {
                switch (this.info.rewardedCount)
                {
                    case 5:
                        this.info.chainDayList.Remove(this.info.rewardedCount);
                        this.ChainDayPrint(5, dm.GetItemData(1008), 1);
                        break;
                    case 10:
                        this.info.chainDayList.Remove(this.info.rewardedCount);
                        this.ChainDayPrint(10, dm.GetItemData(1004), 200);
                        break;
                    case 20:
                        this.info.chainDayList.Remove(this.info.rewardedCount);
                        this.ChainDayPrint(20, dm.GetItemData(1004), 500);
                        break;
                    default:
                        break;
                }
            }
        }

        public void ItemGet(ItemData rewardedItem, int amount)
        {
            // 일일 보상 획득
            this.GetItemPrint(rewardedItem);
            bool reuslt = this.info.RewardedItem(this.info.userId, rewardedItem);
        }

        public void Login()
        {
            this.info.LoadUserInfoData();
        }
    }

 

4. UserInfo.cs

더보기
    class UserInfo
    {
        public string userId;
        public string rewardedDate;

        public int dayCount;
        public int rewardedCount;

        public List<int> chainDayList;

        public Dictionary<int, ItemData> dicRewardedItems;

        public UserInfo()
        {
            this.dicRewardedItems = new Dictionary<int, ItemData>();
            
        }

        public UserInfo(string userId, string rewardedDate, Dictionary<int, ItemData> dicRewardedItems)
        {
            this.userId = userId;
            this.rewardedDate = rewardedDate;
            this.dicRewardedItems = dicRewardedItems;
        }

        public bool RewardedItem(string userid, ItemData rewardedItem)
        {
            this.userId = userid;
            this.rewardedDate = App.TODAY.ToString("yyyy-MM-dd HH:mm:s"); ;
            // 같은 아이템의경우 수량만 추가
            if (!this.dicRewardedItems.ContainsKey(rewardedItem.id))
            {
                this.dicRewardedItems.Add(rewardedItem.id, rewardedItem);
            }
            else
            {
                this.dicRewardedItems[rewardedItem.id].amount += rewardedItem.amount;
                Console.WriteLine("{0}(소지수량:{1}) + {2}획득",
                    this.dicRewardedItems[rewardedItem.id].item_name,
                    this.dicRewardedItems[rewardedItem.id].amount,
                    rewardedItem.amount
                    );
                Console.WriteLine();
            }
            return this.SaveUserInfoData();
        }

        public bool SaveUserInfoData()
        {
            bool result = false;
            var json = JsonConvert.SerializeObject(this);

            try
            {
                File.WriteAllText("./info/userInfo.json", json);

                result = true;
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
                throw;
            }
            return result;
        }

        public void LoadUserInfoData()
        {
            DirectoryInfo folder = new DirectoryInfo("./info");
            if (!folder.Exists)
            {
                folder.Create();
            }

            var path = "./info/userInfo.json";
            try
            {
                if (File.Exists(path))
                {
                    var json = File.ReadAllText(path);
                    UserInfo readInfo = new UserInfo();
                    readInfo = JsonConvert.DeserializeObject<UserInfo>(json);
                    this.rewardedDate = readInfo.rewardedDate;
                    this.userId = readInfo.userId;
                    this.dicRewardedItems = readInfo.dicRewardedItems;
                    this.dayCount = readInfo.dayCount;
                    this.rewardedCount = readInfo.rewardedCount;
                    this.chainDayList = readInfo.chainDayList;
                }
                else
                {
                    Console.WriteLine("-신규유저입니다.");
                    Console.WriteLine("-ID는 lion 입니다.");
                    this.userId = "lion";
                    this.chainDayList = new List<int> { 5, 10, 15 };
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e);
                throw;
            }

            this.dayCount++;

            if (!this.RewardedCountCheck())
            {
                this.rewardedCount = 0;
            }
            this.rewardedCount++;
        }

        public bool RewardedCountCheck()
        {
            DateTime loadDate = Convert.ToDateTime(this.rewardedDate);
            if (this.rewardedDate != null)
            {
                if (App.TODAY.AddDays(-1).Day == loadDate.Day)
                {
                    return true;
                }
            }
            this.rewardedDate = App.TODAY.ToString("yyyy-MM-dd HH:mm:s");
            return false;
        }
    }

 

 

매일매일 페키지는 매일 자정 구매제한 초기화 개념

 


> App.cs

더보기
using Microsoft.SqlServer.Server;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace _20200428_1
{
    class App
    {
        Info info;
        public App()
        {
            DataManager dm = DataManager.GetInstance();

            this.Init();


            //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
            // test용 데이터 주입

            //ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

            this.Load();
            this.info.myDia = 2000;
            this.info.myGold = 10000000;
            this.info.myLevel = 60;

            this.info.PrintInfo();
            this.PackageList();

            // 패키지 구매 테스트
            this.BuyPackage(10000);
            this.BuyPackage(10000);
            this.BuyPackage(10001);
            this.BuyPackage(10002);
            /*  
              this.BuyPackage(10000);
              this.BuyPackage(10001);
              this.BuyPackage(10002);
              this.BuyPackage(10003);
              this.BuyPackage(10004);
              this.BuyPackage(10005);
            */

            // this.everyDayPackageCount();
            this.info.Save();
        }

        public void Init()
        {
            DataManager dm = DataManager.GetInstance();

            info = new Info();

            Console.WriteLine();
            dm.LoadDatas();
        }

        // 판매 종료일 계산
        public void convertDate(string[] getDate)
        {
            DataManager dm = DataManager.GetInstance();

            System.DateTime endDate = new System.DateTime(int.Parse(getDate[0]), int.Parse(getDate[1]), int.Parse(getDate[2]));
            TimeSpan ddayDate = endDate - DateTime.Now;

            Console.Write($"-판매종료까지: ");
            if (ddayDate.Days > 0) { Console.Write($"{ddayDate.Days}일 "); };
            Console.WriteLine($"{ ddayDate.Hours }시간 { ddayDate.Minutes }분 { ddayDate.Seconds }초 남음");

        }

        //매일매일 초기화
        public void everyDayPackageCount()
        {
            Timer timaer = null;
            int FixHours = 12;
            var now = DateTime.Now;
            var scheduledTime = new DateTime(now.Year, now.Month, now.Day, FixHours, 0, 0);
            if (scheduledTime < now)
                scheduledTime = scheduledTime.AddDays(1);

            var timeout = scheduledTime - now;

            var timer = new Timer(timeout.TotalMilliseconds);
            timer.Enabled = true;
            timer.Elapsed += OnTimeEvent;

            Console.Write($"-판매종료까지: ");
            Console.WriteLine($"{ timeout.Hours }시 { timeout.Minutes }분 { timeout.Seconds }초 남음");

        }

        public void OnTimeEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            // 해당 이벤트 발생한다면 매일 자정 이후 매일매일 패키지 구매 카운트 초기화
            Console.WriteLine(e.SignalTime);
            this.info.dicBuyedPackageData[10005] = 0;
        }

        public void BuyPackage(int buyNum)
        {
            DataManager dm = DataManager.GetInstance();
            var data = dm.GetItemDatas(buyNum);

            Console.WriteLine();
            Console.WriteLine("ㅡㅡㅡㅡㅡㅡ 구매 ㅡㅡㅡㅡㅡㅡ");
            Console.WriteLine(data.item_name);
            this.info.BuyPackage(buyNum);
        }

        public void PackageList()
        {
            DataManager dm = DataManager.GetInstance();
            Dictionary<int, ItemData> data = dm.GetAllItemDatas();
            List<int> list = new List<int>(data.Keys);

            foreach (var key in list)
            {
                var cType = dm.GetCurrencyDataById(data[key].item_type);
                var desc = string.Format(data[key].level_limit_desc, data[key].level_limit);
                string money = String.Format("{0:#,###}", data[key].price);
                string mileage = String.Format("{0:#,###}", data[key].mileage);
                string[] testdate = new string[3];

                Console.WriteLine("ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ");
                Console.WriteLine(" *" + data[key].item_name);


                if (data[key].mileage > 0)
                {
                    Console.WriteLine($"-마일리지: {mileage}");
                }

                if (data[key].level_limit > 0) { Console.WriteLine("-" + desc); }
                Console.Write($"[{cType.name}]");
                Console.WriteLine($"-가격: {money}");
                if (data[key].everyday_package) { Console.WriteLine("★매일매일 패키지★"); }


                if (data[key].buy_end_date != "null")
                {
                    testdate = data[key].buy_end_date.Split('.');
                    this.convertDate(testdate);
                }

                if (key == 10005)
                {
                    this.everyDayPackageCount();
                }

                if (data[key].buy_limit > 0)
                {
                    Console.Write("-구매가능수량: (");
                    if (this.info.dicBuyedPackageData.ContainsKey(key))
                    {
                        this.info.count = this.info.dicBuyedPackageData[key];
                    }
                    Console.Write(this.info.count);
                    Console.WriteLine($"/{data[key].buy_limit})");
                }

            }//forEach end
        }

        public void MyinfoPrint()
        {
            Info myInfo = this.info.GetInfoData();
            Console.WriteLine("ㅡㅡㅡㅡㅡㅡㅡㅡㅡ 내 정보 ㅡㅡㅡㅡㅡㅡㅡㅡ");
            Console.WriteLine("[다이아:{0}][골드:{1}][마일리지:{2}][레벨:{3}]",
                myInfo.myDia, myInfo.myGold, myInfo.myLevel);
        }

        public void Load()
        {
            var path = "./info/info.json";
            if (File.Exists(path))
            {
                //파일 읽기 
                var json = File.ReadAllText("./info/info.json");

                //역직렬화 
                //이때 배열이 아니라는점 주의 
                this.info = JsonConvert.DeserializeObject<Info>(json);
                Console.WriteLine(this.info.myLevel);
            }
        }
    }
}

 

> DataManager.cs

더보기
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices;
using Newtonsoft.Json;

namespace _20200428_1
{
    class DataManager
    {
        private static DataManager singleTone;

        private Dictionary<int, CurrencyData> dicCurrencyData;
        private Dictionary<int, ItemData> dicItemData;

        private DataManager()
        {
            this.dicCurrencyData = new Dictionary<int, CurrencyData>();
            this.dicItemData = new Dictionary<int, ItemData>();
        }

        public static DataManager GetInstance()
        {
            if (DataManager.singleTone == null)
            {
                DataManager.singleTone = new DataManager();
                return DataManager.singleTone;
            }
            else
            {
                return DataManager.singleTone;
            }
        }

        public void LoadDatas()
        {
            string json = "";
            string path = "";

            try
            {
                // 아이템 
                path = "./data/item_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicItemData = JsonConvert.DeserializeObject<ItemData[]>(json).ToDictionary(x => x.id, x => x);
                }

                // 재화
                path = "./data/currency_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicCurrencyData = Newtonsoft.Json.JsonConvert.DeserializeObject<CurrencyData[]>(json).ToDictionary(x => x.id, x => x);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("* catch");
                Console.WriteLine(e.Message);
                throw;
            }

        } //Loaddata() end

        public CurrencyData GetCurrencyDataById(int id)
        {
            return dicCurrencyData[id];
        }

        public ItemData GetItemDatas(int id)
        {
            return this.dicItemData[id];
        }

        public Dictionary<int, ItemData> GetAllItemDatas()
        {
            return this.dicItemData;
        }

    }// class end
}

 

> Info.cs

더보기
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200428_1
{
    class Info
    {
        public int myDia; // 소지 다이아 갯수
        public int myGold; // 소지 골드 갯수
        public int myLevel; // 현재 레벨
        public int myMileage; // 현재 누적 마일리지
        public int count;

        public Dictionary<int, int> dicBuyedPackageData; // 구매한 페키지 id, 수량 추가


        public Info()
        {
            this.dicBuyedPackageData = new Dictionary<int, int>();
        }

        public Info(int myDia, int myGold, int myLevel, int myMileage, Dictionary<int, int> dicBuyedPackageData)
        {
            this.myDia = myDia;
            this.myGold = myGold;
            this.myLevel = myLevel;
            this.myMileage = myMileage;
            this.dicBuyedPackageData = dicBuyedPackageData;
        }

        public void BuyPackage(int buyNum)
        {
            DataManager dm = DataManager.GetInstance();

            ItemData data = dm.GetItemDatas(buyNum);

            // 보유 재화 확인
            if (data.item_type == 100)
            {
                if (this.myDia >= data.price)
                {
                    // 구매가능 수량 확인
                    this.PackageBuyLimitCheck(data);
                }
                else
                {
                    Console.WriteLine("구매 다이아 부족");
                }
            }

            if (data.item_type == 101)
            {

                if (this.myGold >= data.price)
                {
                    // 구매가능 수량 확인
                    this.PackageBuyLimitCheck(data);
                }
                else
                {
                    Console.WriteLine("구매 골드 부족");
                }
            }

            this.PrintInfo();
        }

        // 수매수량, 레벨 체크
        public void PackageBuyLimitCheck(ItemData data)
        {
            if (this.dicBuyedPackageData.ContainsKey(data.id))
            {
                this.count = this.dicBuyedPackageData[data.id];
            }

            // 수량 체크
            if (data.buy_limit != 0 && data.buy_limit <= this.count) { Console.WriteLine("더이상 구매불가"); return; }

            // 레벨 체크
            if (data.level_limit != 0 && data.level_limit > this.myLevel) { Console.WriteLine("레벨부족으로 구매불가"); return; }

            if (data.item_type == 100)
            {
                Console.WriteLine("-다이아");
                this.count++;
                this.myDia -= data.price;
                this.myMileage += data.mileage;
                this.dicBuyedPackageData[data.id] = this.count;
            }

            if (data.item_type == 101)
            {
                Console.WriteLine("-골드");
                this.count++;
                this.myGold -= data.price;
                this.myMileage += data.mileage;
                this.dicBuyedPackageData[data.id] = this.count;
            }
        }

        public void PrintInfo()
        {
            DataManager dm = DataManager.GetInstance();

            Console.WriteLine($"-다이아:{this.myDia} -골드:{this.myGold} -레벨:{this.myLevel} -마일리지:{this.myMileage}");

            Console.WriteLine("ㅡㅡㅡㅡㅡ 구매 이력 ㅡㅡㅡㅡ");

            if (this.dicBuyedPackageData.Count > 0)
            {
                foreach (var item in this.dicBuyedPackageData)
                {
                    Console.WriteLine($"{item.Key } {item.Value}");
                }
            }
        }

        public void Save()
        {
            try
            {
                var json = JsonConvert.SerializeObject(this);
                File.WriteAllText("./info/info.json", json);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw;
            }
            Console.WriteLine("데이터 저장");
        }

        public Info GetInfoData()
        {
            return this;
        }
    }
}

 

> data파일들

더보기
namespace _20200428_1
{
    class ItemData
    {
        public int id;
        public int item_type;
        public string item_name;
        public int mileage;
        public int price;
        public int level_limit;
        public string level_limit_desc;
        public int buy_limit;
        public string buy_start_date;
        public string buy_end_date;
        public bool everyday_package;
    }
}
namespace _20200428_1
{
    class CurrencyData
    {
        public int id;
        public string name;
        public int currency_type;
        public string icon_currency;
    }
}

 

'c# 강의 > 과제' 카테고리의 다른 글

20200505 - winForm + 2048 게임 만들기  (0) 2020.05.04
20200429 - 일일보상 + 연속보상 + Date연산  (0) 2020.05.01
20200427 - 싱글톤  (0) 2020.04.28
20200421 - File 읽기 (JSON)  (0) 2020.04.22
20200420 - List 과제  (0) 2020.04.20

1. Year 활용

 System.DateTime endDate = new System.DateTime(2020, 4, 30);
 //endDate 원하는 년,월,일 생성
 	TimeSpan ddayDate = endDate - DateTime.Now;
 // 현재데이터와 연산하여 TimeSpan에 남은 day를 알 수 있다.
 
 /*
   ddayDate.Days 일
   ddayDate.Hours 시간 
   ddayDate.Minutes 분  
   ddayDate.Seconds 초 남음
 */

2. 문자열 -> DateTime

-  년,월,일 구분값은 [스페이스값],[/],[-] 으로만 구분가능하다. 

public void ToDateTimeTest1()
{
    DateTime dti01 = Convert.ToDateTime("2015 11 13");      //변환 가능 (2015년 11월 13일 오후 12:00:00)
    DateTime dti02 = Convert.ToDateTime("2015-11-13");      //변환 가능 (2015년 11월 13일 오후 12:00:00)
    DateTime dti03 = Convert.ToDateTime("2015/11/13");      //변환 가능 (2015년 11월 13일 오후 12:00:00)
    DateTime dti04 = Convert.ToDateTime("2015-11/13");      //변환 가능 (2015년 11월 13일 오후 12:00:00)
    DateTime dti05 = Convert.ToDateTime("2015/11 13");      //변환 가능 (2015년 11월 13일 오후 12:00:00)
    DateTime dti06 = Convert.ToDateTime("20151113");        //에러 (구분값 없음)
    DateTime dti07 = Convert.ToDateTime("2015_11_13");      //에러 (구분값 에러)
    DateTime dti08 = Convert.ToDateTime("2015:11:13");      //에러 (구분값 에러 :는 시간에서 사용가능)
}

3. 데이터 보기 좋게 가공

        public void test()
        {
            var result = DateTime.Now.ToString("yyyy-MM-dd HH:mm:s");
            Console.WriteLine(result);
        }


 

2. Timer 는 테스트 후 다시 기록하기로 한다.

 

 

1. 라이브러리로 생각되긴하는데, C#에서의 솔루션용 Nuget 패키지 의미를 잘모르겠다.

 

using Newtonsoft.Json;

 


2. File 클래스를 사용하려면 추가

using System.IO;

> 읽기 활용

1. 바로 해당 인스턴스 Dictionary로 전환

 try
            {
                path = "./data/hero_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicHeroData = JsonConvert
                        .DeserializeObject<HeroData[]>(json)
                        .ToDictionary(x => x.id, x => x);
                }
                //Newtonsoft.Json 축약가능 using Newtonsoft.Json; 하면

 

2. 배열타입 인스턴스에서 다시 Dictionary로 전환

  var json = File.ReadAllText("./achievement_data.json");
            var arrAchievementDatas = JsonConvert.DeserializeObject<AchievementData[]>(json);
            foreach (var data in arrAchievementDatas) {
                this.dicAchievementDatas.Add(data.id, data);
            }

 


> 쓰기

        public void Save()
        {
            try
            {
                var json = JsonConvert.SerializeObject(this);
                File.WriteAllText("./info/info.json", json);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw;
            }
        }

 


> 폴더 생성

            DirectoryInfo folder = new DirectoryInfo("./info");
            if (!folder.Exists)
            {
                folder.Create();
            }

'c# 강의 > 수업내용(문법 관련)' 카테고리의 다른 글

20200505 - 2차원 배열 (캐릭터 이동)  (0) 2020.05.06
DateTime / Timer 활용  (0) 2020.04.29
20200428 - 문자열 콤마 찍기  (0) 2020.04.28
20200427 - 싱글톤  (0) 2020.04.28
20200423 - Achievement  (0) 2020.04.23
 string money = String.Format("{0:#,###}", data[key].price);


- 맴버로 private static 자신 타입 변수 준비(인스턴스) 

 class DataManager
    {
        private static DataManager singleTone;
        
        private Dictionary<int, HeroData> dicHeroData;
        private Dictionary<int, CurrencyData> dicCurrencyData;
        private Dictionary<int, ItemData> dicItemData;


- 생성자 private 으로 선언 및  컬렉션 초기화

 private DataManager()
        {
            this.dicCurrencyData = new Dictionary<int, CurrencyData>();
            this.dicItemData =  new Dictionary<int, ItemData>();
            this.dicHeroData = new Dictionary<int, HeroData>();
        }

 

- GetInstance 메소드 준비

        public static DataManager GetInstance()
        {
            if (DataManager.singleTone == null)
            {
                DataManager.singleTone = new DataManager();
                return DataManager.singleTone;
            }
            else
            {
                return DataManager.singleTone;
            }
        }

> 기능 및 특징

1. 싱글톤  ManagerData.cs

2. Chatacter.cs 상속

   - Hero.cs

   - Monster.cs

3. HeroInfo.cs 저장될 데이터 클래스, 선택적 매개변수 생성자 활용

4. Data파일들

- HeroData

- ClassData

- ExpData

- GoldData

- ItemData

- MonsterData

 

> 추후 개선시 참고사항

- UI  / 기능,데이터의  명확한  역할 구분 

- 매니저클래스에 제너릭 활용

- enum 및 데이터 파일 저장 등

 

 

> JSON Data

더보기

1. class_data.json

[{
        "id": 100,
        "class_type": 0,
        "class_name": "초보자",
        "require_level": 0
    },
    {
        "id": 101,
        "class_type": 1,
        "class_name": "검사",
        "require_level": 10
    },
    {
        "id": 102,
        "class_type": 1,
        "class_name": "파이터",
        "require_level": 30
    },
    {
        "id": 103,
        "class_type": 1,
        "class_name": "크루세이더",
        "require_level": 50
    },
    {
        "id": 104,
        "class_type": 1,
        "class_name": "히어로",
        "require_level": 90
    },
    {
        "id": 105,
        "class_type": 1,
        "class_name": "하이퍼 히어로",
        "require_level": 120
    },
    {
        "id": 106,
        "class_type": 2,
        "class_name": "아처",
        "require_level": 10
    },
    {
        "id": 107,
        "class_type": 2,
        "class_name": "헌터",
        "require_level": 40
    },
    {
        "id": 108,
        "class_type": 2,
        "class_name": "레인저 ",
        "require_level": 80
    },
    {
        "id": 109,
        "class_type": 2,
        "class_name": "보우마스터",
        "require_level": 120
    },
    {
        "id": 110,
        "class_type": 2,
        "class_name": "하이퍼 보우마스터",
        "require_level": 160
    }
]

 

2. exp_data.json

[
	{
		"exp_id": 100000,
		"level": 1,
		"require_exp": 50
	},
	{
		"exp_id": 100001,
		"level": 2,
		"require_exp": 100
	},
	{
		"exp_id": 100002,
		"level": 3,
		"require_exp": 150
	},
	{
		"exp_id": 100003,
		"level": 4,
		"require_exp": 225
	},
	{
		"exp_id": 100004,
		"level": 5,
		"require_exp": 337
	},
	{
		"exp_id": 100005,
		"level": 6,
		"require_exp": 506
	},
	{
		"exp_id": 100006,
		"level": 7,
		"require_exp": 759
	},
	{
		"exp_id": 100007,
		"level": 8,
		"require_exp": 1139
	},
	{
		"exp_id": 100008,
		"level": 9,
		"require_exp": 1708
	},
	{
		"exp_id": 100009,
		"level": 10,
		"require_exp": 2562
	},
	{
		"exp_id": 100010,
		"level": 11,
		"require_exp": 3844
	}
]

 

3. gold_data.json

[{
	"id": 100,
	"name": "골드"
}]

 

4. hero_data.json

[{
    "id": 1000,
    "class_id": 100,
    "hp": 50,
    "mp": 30,
    "damage": 1.5
}]

 

5. item_data.json

[
	{
		"id": 100,
		"name": "초록 달팽이 껍질",
		"resource_name": "green_snail_shell",
		"icon_name": "ico_green_snail_shell",
		"sell_price": 1,
		"item_type": 0
	},
	{
		"id": 101,
		"name": "파란 달팽이 껍질",
		"resource_name": "bule_snail_shell",
		"icon_name": "ico_bule_snail_shell",
		"sell_price": 1,
		"item_type": 0
	},
	{
		"id": 102,
		"name": "빨간 달팽이 껍질",
		"resource_name": "red_snail_shell",
		"icon_name": "ico_red_snail_shell",
		"sell_price": 1,
		"item_type": 0
	},
	{
		"id": 103,
		"name": "매소 (소 )",
		"resource_name": "meso_small",
		"icon_name": "ico_meso_small",
		"sell_price": 0,
		"item_type": 4
	},
	{
		"id": 104,
		"name": "매소 (중)",
		"resource_name": "meso_midium",
		"icon_name": "ico_meso_midium",
		"sell_price": 0,
		"item_type": 4
	},
	{
		"id": 105,
		"name": "매소 (대)",
		"resource_name": "meso_large",
		"icon_name": "ico_meso_large",
		"sell_price": 0,
		"item_type": 4
	}
]

 

6. monster_data.json

[
  {
    "id": 1000,
    "name": "초록 달팽이",
    "hp": 25,
    "damage": 2.5,
    "exp": 1,
    "drop_item_id": 100
  },
  {
    "id": 1001,
    "name": "파란 달팽이",
    "hp": 25,
    "damage": 2.8,
    "exp": 2,
    "drop_item_id": 101
  },
  {
    "id": 1002,
    "name": "빨간 달팽이",
    "hp": 25,
    "damage": 3,
    "exp": 3,
    "drop_item_id": 102
  },
  {
    "id": 2000,
    "name": "머쉬맘",
    "hp": 1000,
    "damage": 8,
    "exp": 10,
    "drop_item_id": 103
  }
]

 

 

> Code

1. Data 클래스

더보기
    class MonsterData
    {
        public int id;
        public string name;
        public int hp;
        public float dmage;
        public int exp;
        public int drop_item_id;

    }
    class ItemData
    {
        public int id;
        public string name;
        public string resource_name;
        public string icon_name;
        public int sell_price;
        public int item_type;

    }
class HeroData
    {
        public int id;
        public int class_id;
        public int hp;
        public int mp;
        public float damage;

        public HeroData(int id, int class_id, int hp, int mp, float damage)
        {
            this.id = id;
            this.class_id = class_id;
            this.hp = hp;
            this.mp = mp;
            this.damage = damage;
        }
    }
    class GoldData
    {
        public int id;
        public string name;
    }
    class ExpData
    {
        public int exp_id;
        public int level;
        public int require_exp;
    }
    class ClassData
    {
        public int id;
        public int class_type;
        public string class_name;
        public int require_level;

    }

    class Character
    {
        public Character()
        {
        }
        public virtual void Attack(Character target) { }

        public virtual void Hit(float damamge) { }

        public virtual void Die() { }
    }

 

 

2. Info 클래스

더보기
    class HeroInfo
    {
        public string name;
        public int level;
        public int classType; // 직업타입
        public int classGrade; // 등급 id 검사or 파이터등 등급을 말하는 것?
        public float damage;
        public int hp;
        public int mp;
        public int exp;
        public int gold;

        // 선택적 매개변수 뒤쪽에 배치 필요
        public HeroInfo(string name, int hp, int mp, float damage,
             int level = 1, int classType = 0, int classGrade = -1, int exp = 0, int gold=0)
        {
            this.name = name;
            this.level = level;
            this.classType = classType;
            this.classGrade = classGrade;
            this.hp = hp;
            this.mp = mp;
            this.damage = damage;
            this.exp = exp;
            this.gold = gold;
        }
    }

 

3. 싱글톤 매니저 클래스

더보기
    class DataManager
    {
        private static DataManager singleTone;

        private Dictionary<int, HeroData> dicHeroData;
        private Dictionary<int, ClassData> dicClassData;
        private Dictionary<int, ExpData> dicExpData;
        private Dictionary<int, GoldData> dicGoldData;
        public Dictionary<int, ItemData> dicItemData;
        private Dictionary<int, MonsterData> dicMonsterData;

        public static DataManager GetInstance()
        {

            if (DataManager.singleTone == null)
            {
                DataManager.singleTone = new DataManager();
                return DataManager.singleTone;
            }
            else
            {
                return DataManager.singleTone;
            }

        }// GetInstance end;

        public void LoadDatas()
        {
            string json = "";
            string path = "";

            try
            {
                // 영웅 생성
                path = "./data/hero_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicHeroData = JsonConvert.DeserializeObject<HeroData[]>(json).ToDictionary(x => x.id, x => x);
                }

                // 몬스터 생성
                path = "./data/monster_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicMonsterData = JsonConvert.DeserializeObject<MonsterData[]>(json).ToDictionary(x => x.id, x => x);
                }

                // 아이템 생성
                path = "./data/item_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicItemData = JsonConvert.DeserializeObject<ItemData[]>(json).ToDictionary(x => x.id, x => x);
                }

                // 전직 데이터
                path = "./data/class_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicClassData = JsonConvert.DeserializeObject<ClassData[]>(json).ToDictionary(x => x.id, x => x);
                }

                // 경험치 데이터
                path = "./data/exp_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicExpData = JsonConvert.DeserializeObject<ExpData[]>(json).ToDictionary(x => x.exp_id, x => x);
                }

                // 골드 데이터
                path = "./data/gold_data.json";
                if (File.Exists(path))
                {
                    json = File.ReadAllText(path);
                    this.dicGoldData = JsonConvert.DeserializeObject<GoldData[]>(json).ToDictionary(x => x.id, x => x);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw;
            }
        }

        public HeroData GetCharacterDataById(int id)
        {
            return this.dicHeroData[id];
        }

        public MonsterData GetMonsterDataById(int id)
        {
            return this.dicMonsterData[id];
        }

        public ExpData GetExpDataByLevel(int level){
            var result = this.dicExpData.FirstOrDefault(v => v.Value.level == level).Value;
            return result;
        }

        public ClassData GetClassDataByClassType(int classType){ 
            var result = this.dicClassData.FirstOrDefault(v => v.Value.class_type == classType).Value;
            return result;
        }

        public GoldData GetGoldDataById(int id){
            return this.dicGoldData[id];
        }

        public ItemData GetItemDataById(int dropItemId){
            return this.dicItemData[dropItemId];
        }
    }

 

4. Monster / Hero 클래스

더보기
    class Monster : Character
    {
        public int id;
        public string name;
        public float hp;
        public float damage;
        public int exp;
        public int drop_item_id;
        public float maxHp;

        public Monster(MonsterData data)
        {
            this.id = data.id;
            this.name = data.name;
            this.hp = data.hp;
            this.damage = data.dmage;
            this.exp = data.exp;
            this.drop_item_id = data.drop_item_id;
            this.maxHp = data.hp;

            Console.WriteLine(this.name + " 이 생성되었습니다.");
        }

        public override void Attack(Character target)
        {
            Console.WriteLine(target);
            target.Hit(this.damage);
        }

        public override void Hit(float damage)
        {
            Console.WriteLine("몬스터 hit");
            this.hp -= damage;
            if (this.hp <= 0)
            {
                this.Die();
            }
        }

        public override void Die()
        {
            Console.WriteLine("몬스터가 죽었습니다.");
        }

        public bool IsDie() {
            this.hp = 0; //강제 죽임 test
            if (this.hp <= 0) {
                return true;
            }
            return false;
        }
    }

    class Hero : Character
    {
        // 데이터 변경과 에니메이션 담당 -> 외부에 결과 전달(App())
        public HeroInfo info;
        public Hero()
        {
            Console.WriteLine("영웅이 생성되었습니다.");
        }

        public void Init(HeroInfo info)
        {
            this.info = info;
        }

        public override void Attack(Character target)
        {
            target.Hit(this.info.damage);
        }

        public override void Hit(float damage)
        {
            Console.WriteLine($"{this.info.name}이  {damage} 피해를 입어습니다.");
        }

        public override void Die()
        {
           this.info.hp = 0;
            Console.WriteLine("- game over 주인공이 죽었습니다.");
        }

        // 경험치 획득
        public void GetExp(int getExp) {
            this.info.exp += getExp;
            Console.WriteLine($"{this.info.exp} 경험치 획득");
            Console.WriteLine();
        }

        // 경험치 확인
        public void CheckExp(Hero hero) {
          var dataManager = DataManager.GetInstance();
          var exp = hero.info.exp; // 현재 경험치

          //현재 레벨로 가져온 exp데이터
          var expData = dataManager.GetExpDataByLevel(hero.info.level); 
            
          //다음레벨 exp데이터 
          var nextData = dataManager.GetExpDataByLevel(hero.info.level+1); 

          // 레벨업 체크
          if(exp >= expData.require_exp){
             this.LevelUp(hero);
          }else{
            Console.WriteLine($"-Lev{hero.info.level} / {hero.info.exp} -> -Lev{nextData.level} / {expData.require_exp} 필요");
          }
            Console.WriteLine();
        }

        // 레벨 업
        public void LevelUp(Hero hero)
        {
            // 전직 여부 체크
            var dataManager = DataManager.GetInstance();

            if(hero.info.classType == 0 ){ // 초보자 일경우
                Console.WriteLine("- 축하합니다. 전직이 가능합니다.");
                this.ClassChange();
                this.HeroPrint();
            }else{
                // 레벨업
                Console.WriteLine("- 레벨이 올랐습니다.");
                this.UpGrage();
                this.HeroPrint();
            }
        }

        // 스텟 상향
        public void UpGrage(){
             var dataManager = DataManager.GetInstance();

              var classData = dataManager.GetClassDataByClassType(this.info.classGrade+1);

              this.info.classGrade = classData.id;
              this.info.name = classData.class_name;
              this.info.level +=1;
        }

        public void HeroPrint(){
            var hero = this.info;
            Console.WriteLine($"name:{hero.name}/ Lev:{hero.level} / (hp:{hero.hp}/hp:{hero.mp})");
        }

        // 전직
        public void ClassChange()
        {
            var dataManager = DataManager.GetInstance();
            var choiceClass1 = dataManager.GetClassDataByClassType(1);
            var choiceClass2 = dataManager.GetClassDataByClassType(2);

            Console.WriteLine($"1.{choiceClass1.class_name} / 2.{choiceClass2.class_name} 선택");
            Console.WriteLine("1번 선택");
            var userInput=1;

            switch (userInput)
	        {
                case 1:
                    Console.WriteLine("검사를 선택하셨습니다.");
                    this.info.name = choiceClass1.class_name;
                    this.info.classType = choiceClass1.class_type;
                    this.info.classGrade = choiceClass1.id; // 검사 101
                    this.info.level +=1;
                    break;
                case 2:
                    Console.WriteLine("아처를 선택하셨습니다.");
                    this.info.name = choiceClass2.class_name;
                    this.info.classType = choiceClass2.class_type;
                    this.info.classGrade = choiceClass2.id; // 아처 10
                    this.info.level +=1;
                    break;
		        default:
                    break;
	        }
                    Console.WriteLine();
        }

        //아이템 획득
        public void PickItem(Monster target){
            var dataManager = DataManager.GetInstance();
            var getItem = dataManager.GetItemDataById(target.drop_item_id);

            Console.WriteLine($"- 아이템획득: {getItem.name} / 판매가격:{getItem.sell_price} / {getItem.resource_name}");
            Console.WriteLine();
        }

        //골드 획득
        public void PickGold(int id){
            var dataManagere = DataManager.GetInstance();
            GoldData goldData = dataManagere.GetGoldDataById(id);

            this.info.gold += goldData.id;

            Console.WriteLine($"- {goldData.name}({goldData.id}) 획득!");
            Console.WriteLine();
        }
    }

 

5. App 클래스

더보기
    class App
    {
        public App()
        {
            // 데이터 로드
            // 영웅 생성
            // 몬스터 생성
            // 몬스터 공격
            // 몬스터 처치
            // 아이템 드랍
            // 경험치, 아이템 획득
            // 레벨업
            // 전직

            var dataManager = DataManager.GetInstance();
            dataManager.LoadDatas();


            Hero hero  = this.CreateDefaultHero();
            Monster monster = this.CreateMonster(1000);

            //몬스터 공격
            hero.Attack(monster);

            Console.WriteLine($"({monster.hp}/{monster.maxHp})" );

            // 죽임
            monster.Die();
            monster.IsDie();


            // 경험치 획득 
            if (monster.IsDie())
            {
                hero.GetExp(monster.exp);
                hero.CheckExp(hero);

                // 강제 레벨업 - 전직
                hero.LevelUp(hero);

                // 아이템 획득
                hero.PickItem(monster);

                // 골드획득 - 몬스터 고유 id 전달하여 해당 수치만큼 골드 수급
                hero.PickGold(100);
            }
        }


        
        public Monster CreateMonster(int id)
        {
            var monsterData = DataManager.GetInstance().GetMonsterDataById(id);

            return new Monster(monsterData);
        }

        public Hero CreateDefaultHero()
        {
            var characterData = DataManager.GetInstance().GetCharacterDataById(1000);

            var heroInfo = new HeroInfo("홍길동", characterData.hp, characterData.mp, characterData.damage);
            Hero hero = new Hero();
            hero.Init(heroInfo);
            Console.WriteLine(hero.info.name + " 님이 입장하셨습니다.");
            return hero;
        }
    }

 

JSON Data

 

 

 


 

 

> AchievementInfo.cs

더보기
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200423
{
    class AchievementInfo
    {
        public int id;
        public int count;

        public AchievementInfo() { }

        public AchievementInfo(int id, int count)
        {
            this.id = id;
            this.count = count;
        }
    }
}

 

> AchievementData.cs

더보기
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200423
{
    class AchievementData
    {
        public int id;
        public string name;
        public int reward_type;
        public int reward_amount;
        public int goal;
        public string desc;
    }
}

 

> App.cs

더보기
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace _20200423
{
    class App
    {
        Dictionary<int, AchievementData> dicAchievementDatas;
        Dictionary<int, AchievementInfo> dicAchievementInfos;

        public App()
        {
            this.dicAchievementDatas = new Dictionary<int, AchievementData>();
            this.dicAchievementInfos = new Dictionary<int, AchievementInfo>();
            // data 파일 로드
            this.DataFileLoad();

            this.DoAchievement(1000);
            this.PrintAllActhievement();
            this.SaveAchievements();
            this.PrintAllActhievement();
        }

        public void DataFileLoad()
        {
            string json = "";
            string dataPath = "./data/achievement_data3.json";

            if (File.Exists(dataPath))
            {
                Console.WriteLine("data 파일있음");
                try
                {
                    json = File.ReadAllText(dataPath);
                    Console.WriteLine(json);

                    AchievementData[] achievementDatas = JsonConvert.DeserializeObject<AchievementData[]>(json);

                    foreach (var data in achievementDatas)
                    {
                        this.dicAchievementDatas.Add(data.id, data);
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("achievement_data3.json 파일 불러오기 실패");
                    throw;
                }
                InfoFileLoad();
            }
            else
            {
                Console.WriteLine("data 파일 없음");
            }
            Console.WriteLine();
        }

        public void InfoFileLoad()
        {
            string infoJson = "";
            string infoPath = "./info/achievement_info.json";

            if (File.Exists(infoPath))
            {
                Console.WriteLine("info 파일 있음");
                Console.WriteLine("ㅡㅡㅡ 기존유저 ㅡㅡㅡ");
                try
                {
                    infoJson = File.ReadAllText(infoPath);
                }
                catch (Exception)
                {
                    Console.WriteLine("achievement_info.json 파일 불러오기 실패");
                    throw;
                }

                // 문자열 -> 객체 (역직렬화)
                AchievementInfo[] arrInfos = JsonConvert.DeserializeObject<AchievementInfo[]>(infoJson);

                foreach (var info in arrInfos)
                {
                    this.dicAchievementInfos.Add(info.id, info);
                }
                Console.WriteLine(infoJson);
            }
            else
            {
                Console.WriteLine("info 파일 없음");
                Console.WriteLine("ㅡㅡㅡ 신규유저 ㅡㅡㅡ");

                // info 객체 생성하고 사전에 추가
                foreach (var pair in this.dicAchievementDatas)
                {
                    Console.WriteLine($"{pair.Key} / {pair.Value}");

                    AchievementData data = pair.Value;

                    AchievementInfo info = new AchievementInfo(data.id, 0);
                    this.dicAchievementInfos.Add(info.id, info);
                } //forEach end
                // 업적 저장하기
                this.SaveAchievements();
            }
            Console.WriteLine();
        }

        public void DoAchievement(int id)
        {
            var data = this.dicAchievementDatas[id];
            Console.WriteLine($"{this.dicAchievementDatas[id].name} 업적을 1개 했습니다.");

            var info = this.dicAchievementInfos[id];

            if (info.count >= data.goal)
            {
                Console.WriteLine("해당 업적은 완료되었습니다.");
                return;
            }

            info.count += 1;
            //info객체의 count값을 출력한다.
            Console.WriteLine("id: {0} name: {1} goal: {2}/{3}", data.id, data.name, info.count, data.goal);
            Console.WriteLine();
        }


        // 업적 저장
        public void SaveAchievements()
        {
            // 사전에 있는 info 객체 배열에 담는다.
            var length = this.dicAchievementInfos.Count;

            AchievementInfo[] arr = new AchievementInfo[length];
            int index = 0;
            foreach (var pair in this.dicAchievementInfos)
            {
                arr[index++] = pair.Value;
            }

            // 배열 확인
            foreach (var info in arr)
            {
                var format = string.Format($"id: {info.id} count: {info.count}");
                Console.WriteLine(format);
            }

            // 객체 -> json 형식의 문자열로 반환
            string json = JsonConvert.SerializeObject(arr);
            Console.WriteLine("json 으로 변환");
            Console.WriteLine(json);

            //파일 저장
            string path = "./info/achievement_info.json";

            try
            {
                File.WriteAllText(path, json);
            }
            catch (Exception)
            {
                Console.WriteLine("info 파일쓰기 에러");
                throw;
            }
            Console.WriteLine();
        }

        public void PrintAllActhievement()
        {
            Console.WriteLine("ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ");
            var data = this.dicAchievementDatas;
            var info = this.dicAchievementInfos;

            foreach (var item in data)
            {
                var completMsg = info[item.Key].count >= item.Value.goal ? "완료" : "미완료";
                Console.WriteLine($"[{item.Key}] / [{item.Value.name}] / [{item.Value.desc}] / [({info[item.Key].count}/{item.Value.goal})] / {completMsg}");
            }
            Console.WriteLine();
        }
    }
}

 


 

> File.ReadAllText() -- 모든 문자열 읽기

더보기
 public void ReadAllTextTest()
        {
            string path = "./cookie_data.json";

            string json = File.ReadAllText(path);

            Console.WriteLine(json);

            CookieData[] arrCookieDatas = JsonConvert.DeserializeObject<CookieData[]>(json);

            foreach (var item in arrCookieDatas)
            {
                Console.WriteLine($"{item.id} / {item.name} / {item.grade}");
            }
        }

 

> File.ReadAllLines() -- 문자열 한줄씩 읽어오기

더보기
 public void ReadAllLinesTest()
        {
            string path = "./cookie_data.json";

            string[] textValue = File.ReadAllLines(path);

            string fullTextValue = "";
            foreach (var item in textValue)
            {
                fullTextValue += item;
            }

            Console.WriteLine(fullTextValue);

            CookieData[] arrCookieDatas = JsonConvert.DeserializeObject<CookieData[]>(fullTextValue);
            foreach (var item in arrCookieDatas)
            {
                Console.WriteLine($"{item.id} / {item.name} / {item.grade}");
            }
        }

 

> File.OpenRead() / new StreamReader() -- 파일 읽어와 textReader 스트림에서 문자열 읽기

더보기
public void FileStreamTest()
        {
            string path = "./cookie_data.json";

            FileStream fs = File.OpenRead(path); 
            StreamReader sr = new StreamReader(fs);

            // sr.ReadToEnd() 스트림 끝까지 모든 문자를 읽기
            CookieData[] arrCookieDatas = JsonConvert.DeserializeObject<CookieData[]>(sr.ReadToEnd());

            foreach (var item in arrCookieDatas)
            {
                Console.WriteLine($"{item.id} / {item.name} / {item.grade}");
            }
        }

 

> File.ReadAllLines()

더보기

            string[] jsonLines = File.ReadAllLines(fileDir);      


 

> CookieData.cs

더보기
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200421_json
{
    class CookieData
    {
        public int id;
        public string name;
        public int grade;
    }
}

            > 바닥 수량보다 많이 입력시, 바닥 최대수량 획득 후 바닥 아이템 목록에서 제거

 

> 수량 반영

 


> App 생성자

더보기
        List<Item> dropItemList;
        Inventory inventory;


        public App()
        {
            ListApp3();
        }

 

> ListApp3()

더보기
        public void ListApp3()
        {
            this.dropItemList = new List<Item>();

            this.dropItemList.Add(new Item("장검", 10));
            this.dropItemList.Add(new Item("단검", 2));
            this.dropItemList.Add(new Item("활", 5));

            string dropItemName;
            int dropItemAmount;

            this.inventory = new Inventory();

            while (true)
            {
                PrintDropList(dropItemList);
                Console.WriteLine();

                Console.Write("아이템을 획득하려면 명령어를 입력해주세요: ");
                var input = Console.ReadLine();

                string[] cInput = input.Split(' ');

                dropItemName = cInput[0];
                dropItemAmount = int.Parse(cInput[1]);

                GetItemList(dropItemName, dropItemAmount);

                this.inventory.PrintAllItems();

            }
        }

 

> PrintDropList()

더보기
        public void PrintDropList(List<Item> list)
        {

            Console.WriteLine("■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
            Console.WriteLine("길바닥에 떨어져있는 아이템");
            foreach (var item in list)
            {
                if (item != null)
                {
                    Console.WriteLine($"{item.name}, {item.amount}");
                }
            }
            Console.WriteLine("■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
            Console.WriteLine();
        }

 

> GetItemList()

더보기
        public void GetItemList(string dropItemName, int dropItemAmount)
        {
            var findDropitem = this.dropItemList.Find(v => v.name == dropItemName);

            if (findDropitem == null)
            {
                Console.WriteLine(">입력한 아이템은 획득 할 수 없습니다.");
                Console.WriteLine();
                return;
            }

            // 바닥에 있는 수량보다 많이 획득 할 경우
            if (findDropitem.amount <= dropItemAmount)
            {
                Console.WriteLine($"최대 {findDropitem.amount}개 를 획득했습니다.");
                this.inventory.Add(new Item(dropItemName, findDropitem.amount));
                this.dropItemList.Remove(findDropitem);
            }
            else
            {
                this.inventory.Add(new Item(dropItemName, dropItemAmount));
                findDropitem.amount -= dropItemAmount;
            }
        }

 

> 레시피 구매(습득)

> 구매(습득)한 레시피 확인

> 레시피의 재료 확인 / 레시피 배우기

> 배운 레시피 요리 목록

> 요리 하기(가방x - 재료확인 후 요리시작)


 

> Food.cs

더보기
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200417_Recipe
{
    class Food
    {
        public string name;

        public Food(string name)
        {
            this.name = name;
        }
    }
}

 

> Recipe.cs

더보기
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200417_Recipe
{
    class Recipe
    {
        public string name; // 레시피 이름(만들어질 음식 이름)
        public FoodIngredient[] arrFoodIngredientNames;

        public Recipe(string name, FoodIngredient[] arrFoodIngredientNames)
        {
            this.name = name;
            this.arrFoodIngredientNames = arrFoodIngredientNames;
        }

        public string GetName()
        {
            return "조리법: " + this.name;
        }
    }
}

 

> FoodIngredient

더보기
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200417_Recipe
{
    class FoodIngredient
    {
        public string name;
        public int amount;

        public FoodIngredient(string name, int amount)
        {
            this.name = name;
            this.amount = amount;
        }
    }
}

 

> Character.cs

더보기
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200417_Recipe
{
    class Character
    {
        public string name; //캐릭터 이름
        public Recipe[] arrRecipe; //소지중인 레시피들
        public Recipe[] arrCookRecipe; //소지중인 레시피들 
        public int recipeIndex; // 레시피 배열의 인덱스
        public int cookRecipeIndex; // 레시피 배열의 인덱스

        public Character(string name)
        {
            this.name = name;
            this.arrRecipe = new Recipe[10];
            this.arrCookRecipe = new Recipe[10];
            Console.WriteLine($"{this.name}이 생성되었습니다.");
        }

        public void PickRecipe(Recipe recipe)
        {
            Console.WriteLine("-- 구매 --");
            Console.WriteLine($"{recipe.name}");
            this.arrRecipe[this.recipeIndex++] = recipe;
        }

        public void UseRecipe(string recipe)
        {
            Recipe[] newArr = new Recipe[10];
            int idx = 0;

            for (int i = 0; i < this.arrRecipe.Length; i++)
            {
                if (this.arrRecipe[i].name == recipe)
                {
                    this.arrCookRecipe[this.cookRecipeIndex++] = this.arrRecipe[i];
                    Console.WriteLine(recipe + "레시피를 배웠습니다.");
                    this.arrRecipe[i] = null;

                    foreach (var item in arrRecipe)
                    {
                        if (item != null)
                        {
                            newArr[idx++] = item;
                        }
                    }
                    this.arrRecipe = newArr;
                    this.recipeIndex = -1;

                    break;
                }
            }
        }

        public Recipe[] PrintMyRecipe()
        {
            Console.WriteLine("** 소지하고있는 레시피 **");
            foreach (var item in this.arrRecipe)
            {
                var idx = Array.IndexOf(this.arrRecipe, item);
                if (item != null)
                {
                    Console.WriteLine($"{idx + 1}.{item.name}");
                }
            }
            return this.arrRecipe;
        }

        public Recipe[] PrintCookRecipe()
        {
            Console.WriteLine("** 요리가능한 레시피 **");
            foreach (var item in this.arrCookRecipe)
            {
                var idx = Array.IndexOf(this.arrCookRecipe, item);
                if (item != null)
                {
                    Console.WriteLine($"{idx}.{item.name}");
                }
                else
                {
                    Console.WriteLine("없음");
                }
            }
            return this.arrCookRecipe;
        }


        public Recipe infoRecipe(string recipeName, Recipe[] checkRecipeList)
        {
            Recipe recipe = null;
            foreach (var item in checkRecipeList)
            {
                if (item != null)
                {
                    if (item.name == recipeName)
                    {
                        return item;
                    }
                }
            }
            return recipe;
        }


        public string Cook(string recipeName)
        {
            // 재료 확인
            // 재료 수량 확인
            foreach (var item in this.arrCookRecipe)
            {
                if (item != null)
                {
                    if (item.name == recipeName)
                    {
                        Console.Write("-- 재료를 사용합니다: ");
                        foreach (var ingredient in item.arrFoodIngredientNames)
                        {
                            if (ingredient != null)
                            {
                                Console.Write($"[{ingredient.name}({ingredient.amount})] ");
                            }
                        }
                        Console.WriteLine();
                    }
                }
            }
            Console.WriteLine(recipeName + "를 요리합니다.");
            return "";
        }
    }
}

 

> App.cs

더보기
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _20200417_Recipe
{
    class App
    {
        Character hong;
        FoodIngredient[] arrFoodIngredientNames;
        Recipe recipe;
        string input = "";
        bool buyed1 = false;
        bool buyed2 = false;

        public App()
        {
            this.hong = new Character("홍길동");
            while (true)
            {
                MainView();
                Console.Write(">입력: ");
                input = Console.ReadLine();
                SubView(input);
            }
        }

        public void MainView()
        {
            Console.WriteLine();
            Console.WriteLine("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
            Console.WriteLine("[1.요리하기] [2.레시피 구매] [3.가방 레시피 확인]");
            Console.WriteLine("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
        }

        public void SubView(string inputNum)
        {
            switch (inputNum)
            {
                case "1":
                    Recipe[] result = this.hong.PrintCookRecipe();
                    CookRecipe(result);
                    break;
                case "2":
                    BuyRecipe();
                    break;
                case "3":
                    Recipe[] arrRecipeList = this.hong.PrintMyRecipe();
                    Console.WriteLine();
                    Console.WriteLine("> [1.레시피 재료확인] [2.요리배우기] [9.돌아가기]");
                    Console.Write("> 입력: ");
                    input = Console.ReadLine();
                    if (input == "9") { Console.WriteLine(">이전으로 돌아갑니다!"); return; }
                    if (input == "1")
                    {
                        Console.Write("> 확인하려는 요리 번호를 입력해주세요: ");
                        input = Console.ReadLine();
                        infoRecipe(input, arrRecipeList);
                    }
                    Console.WriteLine();
                    Console.WriteLine("> 배우시려면 해당 번호 입력, [9.돌아가기]");
                    Console.Write(">입력: ");
                    input = Console.ReadLine();
                    if (input == "9") { Console.WriteLine(">이전으로 돌아갑니다!"); return; }
                    UseRecipe(input, arrRecipeList);
                    break;
                default:
                    break;
            }
        }

        public void infoRecipe(string input, Recipe[] checkRecipeList)
        {
            int check = int.Parse(input);

            Recipe result = hong.infoRecipe(checkRecipeList[check - 1].name, checkRecipeList);
            if (result != null)
            {
                Console.WriteLine("> 찾은 요리정보 <");
                Console.Write($"{result.name} : 필수재료--");
                foreach (var item in result.arrFoodIngredientNames)
                {
                    Console.Write($"[{item.name}({item.amount})] ");
                }
            }
            else
            {
                Console.WriteLine("찾는 요리 없음");
            }
            Console.WriteLine();
        }

        public void CookRecipe(Recipe[] arrCookRecipe)
        {
            Console.WriteLine("ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ");
            Console.WriteLine("> 요리시려면 해당 번호 입력, [9.돌아가기]");
            Console.Write("> 입력: ");
            input = Console.ReadLine();
            if (input == "9") { Console.WriteLine(">이전으로 돌아갑니다!"); return; }
            switch (input)
            {
                case "0":
                    if (arrCookRecipe[0] == null) { return; }
                    this.hong.Cook(arrCookRecipe[0].name);

                    break;
                case "1":
                    if (arrCookRecipe[1] == null) { return; }
                    this.hong.Cook(arrCookRecipe[1].name);

                    break;
                default:
                    Console.WriteLine("> 없는번호입니다.");
                    break;
            }
            Console.WriteLine();
        }

        public void UseRecipe(string input, Recipe[] arrRecipeList)
        {
            switch (input)
            {
                case "1":
                    if (arrRecipeList[0] == null) { return; }
                    this.hong.UseRecipe(arrRecipeList[0].name);
                    break;
                case "2":
                    if (arrRecipeList[1] == null) { return; }
                    this.hong.UseRecipe(arrRecipeList[1].name);
                    break;
                default:
                    Console.WriteLine("> 없는번호입니다.");
                    break;
            }
            Console.WriteLine();
        }


        public void BuyRecipe()
        {
            FoodIngredient foodIngredient1;
            FoodIngredient foodIngredient2;

            Console.WriteLine("> [1.햄버거] [2.괴물 오믈렛]");
            Console.Write(">입력: ");
            input = Console.ReadLine();
            switch (input)
            {
                case "1":
                    if (!buyed1)
                    {
                        // 기본 레시피1 생성
                        foodIngredient1 = new FoodIngredient("쇠고기 패티", 1);
                        foodIngredient2 = new FoodIngredient("빵", 1);

                        this.arrFoodIngredientNames = new FoodIngredient[2];
                        this.arrFoodIngredientNames[0] = foodIngredient1;
                        this.arrFoodIngredientNames[1] = foodIngredient2;
                        this.recipe = new Recipe("햄버거", this.arrFoodIngredientNames);
                        this.hong.PickRecipe(this.recipe);
                        this.buyed1 = true;
                    }
                    else
                    {
                        Console.WriteLine("> 해당 레시피는 더이상 구매 불가");
                    }
                    break;
                case "2":
                    if (!buyed2)
                    {
                        // 기본 레시피2 생성
                        foodIngredient1 = new FoodIngredient("거대한 알", 1);
                        foodIngredient2 = new FoodIngredient("독특한 양념", 1);

                        this.arrFoodIngredientNames = new FoodIngredient[2];
                        this.arrFoodIngredientNames[0] = foodIngredient1;
                        this.arrFoodIngredientNames[1] = foodIngredient2;
                        this.recipe = new Recipe("괴물 오믈렛", this.arrFoodIngredientNames);
                        this.hong.PickRecipe(this.recipe);
                        this.buyed2 = true;
                    }
                    else
                    {
                        Console.WriteLine("> 해당 레시피는 더이상 구매 불가");
                    }
                    break;
                default:
                    break;
            }
            Console.WriteLine();
        }
    } //class end
}

'c# 강의 > 과제' 카테고리의 다른 글

20200421 - File 읽기 (JSON)  (0) 2020.04.22
20200420 - List 과제  (0) 2020.04.20
20200415 - 아이템 생성, 검색, 꺼내기, 출력 과제  (0) 2020.04.16
20200414 - 테란~아카데미까지  (0) 2020.04.14
20200413 - 슈팅 게임  (0) 2020.04.13

+ Recent posts