낑깡의 게임 프로그래밍 도전기

C# Queue(큐), 반복자 패턴, ?표 시리즈 본문

카테고리 없음

C# Queue(큐), 반복자 패턴, ?표 시리즈

낑깡겜플밍 2023. 11. 15. 21:23
반응형
SMALL
using System;

public class Queue<T>
{
    private const int DefaultCapacity = 4;

    private T[] array;
    private int head;
    private int tail;

    public Queue()
    {
        array = new T[DefaultCapacity];
        head = 0;
        tail = 0;
    }
    public int Count
    {
        get
        {
            if (head <= tail)
                return tail - head;
            else
                return tail + (array.Length - head);
        }
    }
    private bool IsFull()
    {
        if (head > tail)
        {
            return head == tail + 1;
        }
        else
        {
            return head == 0 && tail == array.Length - 1;
        }
    }
    private bool IsEmpty()
    {
        return head == tail;
    }

    public void Clear()
    {
        array = new T[DefaultCapacity];
        head = 0;
        tail = 0;
    }

    public void Enqueue(T item)
    {
        if (IsFull())
        {
            Grow();
        }

        array[tail] = item;
        MoveNext(ref tail);
    }
    public T Dequeue()
    {
        if (IsEmpty())
            throw new InvalidOperationException();

        T result = array[head];
        MoveNext(ref head);
        return result;
    }
    public T Peek()
    {
        if (IsEmpty())
            throw new InvalidOperationException();

        return array[head];
    }
    private void Grow()
    {
        int newCapacity = array.Length * 2;
        T[] newArray = new T[newCapacity];
        if (head < tail)
        {
            Array.Copy(array, head, newArray, 0, tail);
        }
        else
        {
            Array.Copy(array, head, newArray, 0, array.Length - head);
            Array.Copy(array, 0, newArray, array.Length - head, tail);
        }

        tail = Count;
        head = 0;
        array = newArray;
    }

    private void MoveNext(ref int index)
    {
        index = (index == array.Length - 1) ? 0 : index + 1;//끝에도달하면 0으로 가고 아니면 전진
    }

}

카운트는 꽉찬경우에 확장할때만 쓴다

 

반복자패턴
아래 셋다 전달해줄 순서를 가지고 있다.
반복자는 요소들을 접근하는 순서를 알켜준다. 그게 IEnnumarator
그걸 가능하게 하는게 IEnumarable  
그래서 Foreach문은 반복자가 가능한 애만 들어올 수 있다.

IEnumerator(순서) 를 가지고 있는것  
IEnumerable은 연결 시켜주는 것임.

Foreach문은 IEnumerable을 상속받은 객체의 IEnumerator(순서)를 기준으로 반복한다. 

foreach문 풀어쓰기 리셋을 안하면 한번만 반복된다

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;


namespace CustomCollections
{
    public class FloatListEnumerator : IEnumerator
    {
        public event Action onEnd;
        FloatList floatList = null;
        int currentIndex;
        public FloatListEnumerator(FloatList floatList)
        {
            this.floatList = floatList;
            currentIndex = floatList.Count;
        }

        public object Current
        {
            get
            {
                return floatList[currentIndex];
            }
        }
   

        public bool MoveNext()
        {
            currentIndex--;
            bool isNextCheck = currentIndex >= 0;
            if(isNextCheck == false)
            {
                onEnd();
            }
            return isNextCheck;
        }

        public void Reset()
        {
            currentIndex = floatList.Count;
        }
    }
    public class FloatList : IEnumerable
    {
        int type = 0;
        const int defaultCapacity = 4;
        float[] items;
        int size = 0;
        public int Capacity {  get { return items.Length; } }
        public int Count { get { return size; } }

        public float this[int index]
        {
            get
            {
                return items[index];
            }
            set
            {
                items[index] = value;
            }
        }
        public FloatList()
        {
            items = new float[defaultCapacity];
        }

        public void Add(float item)
        {
            if (size >= items.Length)
                Grow();

            items[size] = item;
            size++;
        }

        public void RemoveAt(int index)
        {
            for(int i=index;i<items.Length-1; i++)
            {
                items[i] = items[i + 1];
            }
            size--;
        }
        public void Grow()
        {
            int newCapacity = items.Length * 2;
            float[] newItems = new float[newCapacity];

            Array.Copy(items, 0, newItems, 0, size);
            items = newItems;
        }

        public IEnumerator GetEnumerator()
        {
            return new FloatListEnumerator(this);
        }
    }

    public class GameManager : MonoBehaviour
    {
        IEnumerator listEnumerator = null;
        FloatList list = new FloatList();

        List<string> conversationScripts = new List<string>();
        //반복자 패턴
        void Start()
        {
            conversationScripts.Add("안녕");
            conversationScripts.Add("난 감자야");
            conversationScripts.Add("사실");
            conversationScripts.Add("고구마야");
           
            listEnumerator = conversationScripts.GetEnumerator();
        }

        private void Update()
        {
            if(Input.GetKeyDown(KeyCode.Space))
            {
                if(listEnumerator.MoveNext())
                {
                    Debug.Log(listEnumerator.Current);
                }
            }
        }
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;
using static System.Runtime.CompilerServices.RuntimeHelpers;


namespace CustomCollections
{

    public class WaitForKeyDown : CustomYieldInstruction
    {
        KeyCode keyCode;
        public WaitForKeyDown(KeyCode keycode) 
        {
            this.keyCode = keycode;
        }

        public override bool keepWaiting
        {
            get
            {
                return Input.GetKeyDown(keyCode) == false;
            }
        }
    }
    public class GameManager : MonoBehaviour
    {
        IEnumerator testCo;

        void Start()
        {
            testCo = TestCo();
            StartCoroutine(testCo);
        }

        IEnumerator TestCo()
        {
            yield return new WaitForKeyDown(KeyCode.S);
            Debug.Log("TEST1");
            yield return new WaitForSeconds(1);
            Debug.Log("TEST2");
            yield return new WaitForSeconds(1);
            Debug.Log("TEST3");
            yield return new WaitForSeconds(1);
            Debug.Log("TEST4");
        }
     
    }

}

 

yield return은 해당 조건이 완료될때까지 기다려 주는 것이다.

위랑 같은 구문인데 null이아닐때만 체크해준다
왼쪽 조건이 널이면 추가해서 들어가는 것

 

null터트림 해결

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Unity.VisualScripting;
using static System.Runtime.CompilerServices.RuntimeHelpers;
using static CustomCollections.GameManager;


namespace CustomCollections
{
    public class GameManager : MonoBehaviour
    {
        //? 시리즈 null과 관련됨
        Action action = null;
        //값타입? 변수명;  값타입이 null을 가질 수 있게 해줌
        bool? isCheck;//구조체에도 null을 쓰고 싶을땐 물음표를 붙이면 해결
        private void Start()
        {
            int value;
            //3항연산자
            //(조건) ? 참일때 : 거짓일때
            value = (bool)isCheck ? 10 : 20;

            if (action != null)
                action();

            action?.Invoke();

            //Rigidbody rb =  GetComponent<Rigidbody>();
            //rb?.velocity = Vector3

            //null병합연산자 앞??뒤
            //앞에꺼가 null이면 뒤에것도 가져다 쓰는 것
            Rigidbody rb = GetComponent<Rigidbody>()??gameObject.GetComponent<Rigidbody>();
        }
    }
}

 

반응형
LIST