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