내일배움캠프 Unity 2일차 TIL - 게임개발종합반 강의 3,4주차

Wooooo·2023년 10월 31일
0

내일배움캠프Unity

목록 보기
4/94

오늘의 키워드

4주차 강의 중에 배열의 원소를 무작위 순서로 정렬하는 구현 과정이 있었는데, 내가 생각했던 것과 다르게 간단하게 코드 한 줄로 구현할 수 있었다.

내가 생각한 방법

정렬할 배열을 arr라 치자. 길이가 같은 arr2 배열과 visited 배열을 선언해둔다. arr의 첫번째 원소부터 반복문을 돌면서 arr2배열의 무작위 인덱스에 넣고 visited 배열에 해당 인덱스에는 값이 들어왔다고 기록한다. 만약 이미 값이 들어 있는 인덱스 (visited[i] == true)라면 무작위 인덱스를 다시 뽑는다.

int[] rtans = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
int[] arr2 = new int[rtans.Length];
bool[] visited = new bool[rtans.Length];
for (int i = 0; i < rtans.Length; i++)
{
	while (true)
	{
    	int randomIndex = Random.Range(0, arr2.Length);

		if (!visited[randomIndex])
        {
        	arr2[randomIndex] = rtans[i];
            visited[randomIndex] = true;
            break;
        }
    }
}
rtans = arr2;

길다.. 그리고 while (true)라니 무섭다.. 만약 배열의 길이가 수억개로 아주 길었다면, 마지막 원소를 정렬할 때 (1/수억) 확률을 뚫어야 정렬이 완료된다. 만약에 강의에서 나온 방법이 아니라 이런식으로 구현하려 했다면 인덱스 번호를 key, -1 ~ 1 사이의 랜덤한 실수값을 value로 갖는 pair를 만들어서 value를 기준으로 정렬하는 heap에 넣어 heap sort를 하는게 더 빠르지 않았을까 싶다.

강의에서 나온 방법

int[] rtans = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
rtans = rtans.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();

Linq의 기능인 OrderBy를 이용해서 간단하게 한줄로 구현할 수 있었다.
그렇다면 Linq는 무엇인가? 그리고 item => Random.Range(-1.0f, 1.0f)는 뭘 의미하길래 랜덤으로 정렬이 되는걸까? 일단 =>는 람다(lambda)라고 한다. Linqlambda식에 대해 알아보자.

Linq

Linq는 c# 3.0에서 생긴 기능이라고 한다. 간단하게 말하면 언어에 통합된 쿼리이다. 배열에다 SQL을 이용해 값을 찾거나, 정렬할 수도 있다. 다음은 Linq의 대표적인 SQL 연산자이다.

  1. Where : 질의 조건에 맞는 데이터를 추출하는데 사용합니다.

  2. Select : 질의 결과를 원하는 형식으로 변환할 때 사용합니다.

  3. OrderBy : 질의 결과를 원하는 순서대로 정렬할 때 사용합니다.

  4. GroupBy : 질의 결과를 특정 조건 기준으로 묶을 때 사용합니다.

  5. Join : 두개의 질의 결과를 연결하여 하나의 질의 결과로 만들 때 사용합니다.

여기에서 Linq에 대해 다 정리하면 글이 너무 길어질 것 같으니 우리가 궁금한 OrderBy 부분을 알아보자.

Lambda식

lambda 역시 c# 3.0에서 생긴 기능이라고 한다. c#에서 lambda는 c#의 delegate 키워드에서 발전된 형태라고 생각하면 된다. delegate는 또 뭔데? 라고 한다면 우리말로는 대리자라고도 하며, c++의 함수포인터와 비슷한 역할을 한다. 파라미터와 리턴값의 type이 같은 메서드를 가리킬 수 있는데, 이를 이용하여 event나 callback을 만들 수 있다.

lambda는 간결하고 간편한 문법을 사용하여 개발자가 작성한 코드를 더 간결하고 가독성 있게 만들어 주는 기능이라고 한다. 람다식을 통해 인자를 넘길 수 있으며 기존에 사용한 delegate나 익명 메서드를 대신하여 간단한 작성과 코드 이해도를 높일 수 있댄다..

lambdadelegate 대신 =>(람다연산자)를 사용한다. 예를 들어 ..

다음의 경우

var list = students.OrderBy(x => x.score).ToList();

에서의 람다식 x => x.score를 해석해보자면, students 배열의 임의의 요소 xx.score를 우선순위로 정렬한다. 쯤으로 이해하면 될 것 같다.

오늘 강의에서 나온

rtans = rtans.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();

에서의 람다식 item => Random.Range(-1.0f, 1.0f)를 해석해보자면, rtans배열의 임의의 요소 item-1 ~ 1 사이의 랜덤한 실수의 우선순위로 정렬한다. 쯤으로 이해하면 될 것 같다. item마다 우선순위가 다르니 결과적으로 배열 안의 원소들은 무작위 순서로 정렬될 것이다.

delegatelambda의 차이를 자세하게 설명한 글이 있다. 두고 두고 읽어보면 좋을 것 같다.

마무리

람다식은 아직 많이 생소하다. 간결함과 가독성을 위해 만들어졌다는데 아직 한 눈에 안들어오는 것을 보니깐 앞으로 많이 써봐야겠다. c++의 sort() 함수처럼 OrderBy 역시 사용자가 직접 만든 compare()함수를 이용하여 입맛대로 정렬할 수도 있다는데, 정렬은 정말 자주 쓰고 중요한 기능이니까 까먹지 말아야겠다.

참고

https://centbin.com/%EB%9E%8C%EB%8B%A4%EC%8B%9D%EA%B3%BC-linq-%EA%B8%B0%EC%B4%88/
https://koco-pot.co.kr/c-%EC%96%B8%EC%96%B4%EC%97%90%EC%84%9C%EC%9D%98-linq%EC%99%80-%EB%9E%8C%EB%8B%A4%EC%8B%9D-%ED%99%9C%EC%9A%A9-%EB%B0%A9%EB%B2%95/
https://learn.microsoft.com/ko-kr/dotnet/api/system.linq.enumerable.orderby?view=net-7.0

profile
game developer

1개의 댓글

comment-user-thumbnail
2023년 11월 1일

와 글 정말 잘쓰신 것같습니다!

답글 달기