텍스트 Rpg - C#

C#으로 만드는 텍스트 Rpg (6)

게임만드는학생 2025. 2. 5. 19:49

 

미션 5: 람다와 LINQ

  • 목표: 람다와 LINQ를 활용해 데이터를 효율적으로 처리한다.
  • 미션:
    1. 몬스터 리스트에서 체력이 가장 낮은 몬스터를 람다와 LINQ로 찾아라.
    2. 아이템 리스트에서 체력 회복 아이템만 추출하는 코드를 작성해라.

 

 

LINQ는 C#에서 지원하는 sql언어 같은 것이다. 

컬렉션이나 json등 여러가지 데이터에서 사용하여 데이터를 가공할 수 있는 아주 편리한 기능이다. 

 

사용법은 sql 처럼 where, orderby, select 등을 사용할 수도 있고, 함수를 사용할 수도 있다. 

 

이번 미션에서는 함수로 사용했다. 

// GameManager.cs

public  List<Monster> monsters;

public List<Monster> FindHalfHpMonster()
{
    return monsters?.Where(n => n.Hp < n.MaxHp / 2).ToList()?? new List<Monster>();
}

체력이 반 이하인 몬스터들만 필터링하여 리턴해주는 함수를 만들었다. 

 

monsters뒤의 ? 은 nullable 이라는 키워드로 널이 들어오는 것이 가능하다는 의미이다. nullable 형식이 아니라면 
null 일 때, 오류가 발생하게 된다. 

그리고 Where 함수는 주어진 람다함수에 맞는 조건만 필터링해서 IEnumerable<Monster> 형태를 반환한다. 

이것을 체이닝해서 .ToList로 리스트화 시킨 것이다.

 

?? 키워드는 왼쪽값이 널이면 오른쪽 값을 사용하라는 의미이다. 삼항연산자랑 비슷하다고 보면 된다.

 

LINQ 와 관련된 함수는 이외에 몇가지 소개하겠다. 

 

var result = numbers.Where(n => n % 2 == 0); // 조건에 맞는 필터링

var squaredNumbers = numbers.Select(n => n * n); // 값 변환

var sorted = numbers.OrderBy(n => n); // 오름차순

var sortedDesc = numbers.OrderByDescending(n => n); // 내림차순

var firstEven = numbers.First(n => n % 2 == 0); // 조건에 맞는 요소 중 첫번째 반환
var firstOrDefaultEven = numbers.FirstOrDefault(n => n > 10);  // 없으면 기본값 반환 (int는 0)

var grouped = numbers.GroupBy(n => n % 2 == 0 ? "짝수" : "홀수"); // 조건에 맞게 그룹화 

var evenCount = numbers.Count(n => n % 2 == 0); // 개수

var sum = numbers.Sum(); // 합
var average = numbers.Average(); // 평균
var min = numbers.Min(); // 제일 작은거
var max = numbers.Max(); // 제일 큰거

bool hasEven = numbers.Any(n => n % 2 == 0); // 하나라도 만족하면 true
bool allEven = numbers.All(n => n % 2 == 0); // 모두 만족해야 true

var distinctNumbers = numbers.Distinct(); // 중복 제거

var firstThree = numbers.Take(3); // 처음 3개 가져오기
var skipTwo = numbers.Skip(2);    // 처음 2개 건너뛰기

여기서 groupby는 요소를 그룹별로 나누는데 dictionary로 변환한다고 생각하면 쉽다. 또한 ToDictionary 함수도 지원된다. 

또한 distinct 같은 경우는 Equals()와 GetHashCode() 함수의 재정의가 필요하다. 

 

다음은 ItemManager에 필터링함수를 추가했다.

 

public List<T> FindItemByType<T>(ItemType type) where T : Item
{
    if (Inventory.ContainsKey(type.ToString()) == false)
        return new List<T>();

    return Inventory[type.ToString()].OfType<T>().ToList();
}

원하는 아이템타입을 넘겨주면 해당 타입인 아이템을 필터링하여 그 타입으로 캐스팅 후, 리스트로 넘겨준다. 

제너릭을 사용했고, where문으로 Item의 하위클래스만 T로 넘길 수 있게 하였다. 

 

OfType또한 LINQ 함수인데, T에 해당하는 클래스만 골라서 캐스팅 후, 리턴값에 추가해준다. 

 

이번미션은 꼭 텍스트 rpg에 필요해서 했다기보다는 LINQ문법을 사용해보는데 의미를 두었다.