강께르의 개발일지

[문제 풀기] Bit Flags, Generics, Delegate에 대하여 본문

프로그래밍/C#

[문제 풀기] Bit Flags, Generics, Delegate에 대하여

강께르 2021. 9. 18. 00:35

1. 비트맵 색상 합치기와 추출을 비트 플래그로 구현

using System;

public class Test
{
    public static uint MergeARGB(uint a, uint r, uint g, uint b)
    {
        uint result = 0;
        result |= b;
        result |= (g << 8);
        result |= (r << 16);
        result |= (a << 24);
        Console.WriteLine(Convert.ToString(a, 16));
        return result;
    }

    public static void ExtractARGB(uint argb, out uint a, out uint r, out uint g, out uint b)
    {
        a = (argb & 0xFF000000) >> 24;
        r = (argb & 0x00FF0000) >> 16;
        g = (argb & 0x0000FF00) >> 8;
        b = (argb & 0x000000FF);
        
        // 위 방법보단 아래 방법을 더 추천
        //a = (argb >> 24) & 0xFF;
        //r = (argb >> 16) & 0xFF;
        //g = (argb >> 8) & 0xFF;
        //b = argb & 0xFF;
    }

    public static void Main()
    {
        uint colorA = MergeARGB(255, 192, 255, 192);
        ExtractARGB(colorA, out uint a, out uint r, out uint g, out uint b);
        Console.WriteLine(a); // 255
        Console.WriteLine(r); // 192
        Console.WriteLine(g); // 255
        Console.WriteLine(b); // 192
    }
}

2. 몬스터 상태에 대한 기능 구현

using System;

var monster = new Monster();
monster.SetStatus(Monster.Status.A | Monster.Status.B);
Console.WriteLine(monster.CurrentStatus);   
monster.RemoveStatus(Monster.Status.B);
Console.WriteLine(monster.CurrentStatus);
monster.RemoveStatus(Monster.Status.C);
Console.WriteLine(monster.CurrentStatus);
monster.RemoveStatus(Monster.Status.A);
Console.WriteLine(monster.CurrentStatus);
monster.ToggleStatus(Monster.Status.All);
Console.WriteLine(monster.CurrentStatus);
monster.RemoveStatus(Monster.Status.A | Monster.Status.B);
Console.WriteLine(monster.CurrentStatus);
monster.AddStatus(Monster.Status.C);
Console.WriteLine(monster.CurrentStatus);   
Console.WriteLine(monster.CheckStatus(Monster.Status.A));   
Console.WriteLine(monster.CheckStatus(Monster.Status.B));   
Console.WriteLine(monster.CheckStatus(Monster.Status.C));   
monster.ToggleStatus(Monster.Status.B);
Console.WriteLine(monster.CurrentStatus);   
monster.RemoveStatus(Monster.Status.C);
Console.WriteLine(Enum.IsDefined(typeof(Monster.Status), monster.CurrentStatus)); // test 원래는 플래그 enum엔 사용하면 안됨

class Monster
{
    [Flags]
    public enum Status
    {
        None = 0,
        A = 1 << 0,
        B = 1 << 1,
        C = 1 << 2,
        All = A | B | C
    }

    private Status currentStatus;

    public Status CurrentStatus
    {
        get { return currentStatus; }
    }

    public void SetStatus(Status status)
    {
        currentStatus &= 0b000;
        currentStatus |= status;
    }

    public bool CheckStatus(Status status)
    {
        return (currentStatus & status) == status;
    }

    public void AddStatus(Status status)
    {
        currentStatus |= status;
    }

    public void ToggleStatus(Status status)
    {
        currentStatus ^= status;
    }
    public void RemoveStatus(Status status)
    {
        currentStatus = currentStatus ^ status & currentStatus;

        // 다른 방법
        //currentStatus &= ~status;
    }
}

3. MyArray 메소드 추가 / 델리게이트와 일반화를 이용

  • Find 씨리즈
  • FindAll 씨리즈
  • Exists
  • Clear
  • Fill
  • Sort<T>(T[], Comparison<T>)
  • ForEach<T> (T[] array, Action<T> action);
class MyArray<T> where T : IComparable<T>, IEquatable<T>
{
    public static void Copy(T[] sour, T[] dest, int length)
    {
        for (int i = 0; i < length; i++)
        {
            dest[i] = sour[i];
        }
    }
    public static void Copy(T[] sour, int sourStart, T[] dest, int destStart, int length)
    {
        for (int i = 0; i < length; i++)
        {
            dest[destStart + i] = sour[sourStart + i];
        }
    }
    public static int IndexOf(T[] array, T number)
    {
        for (int idx = 0; idx < array.Length; idx++)
        {
            if (array[idx].Equals(number))
            {
                return idx;
            }
        }

        return -1;
    }
    public static void Sort(T[] array)
    {
        for (int idx = 0; idx < array.Length - 1; idx++)
        {
            for (int innerIdx = 0; innerIdx < array.Length - 1 - idx; innerIdx++)
            {
                if (array[innerIdx].CompareTo(array[innerIdx + 1]) > 0)
                {
                    T temp = array[innerIdx];
                    array[innerIdx] = array[innerIdx + 1];
                    array[innerIdx + 1] = temp;
                }
            }
        }
    }
    public static void Sort(T[] array, Comparison<T> comparison, bool order = true)
    {
        for (int idx = 0; idx < array.Length - 1; idx++)
        {
            for (int innerIdx = 0; innerIdx < array.Length - 1 - idx; innerIdx++)
            {
                if (comparison(array[innerIdx], array[innerIdx + 1]) > 0)
                {
                    T temp = array[innerIdx];
                    array[innerIdx] = array[innerIdx + 1];
                    array[innerIdx + 1] = temp;
                }
            }
        }
    }
    public static int BinarySearch(T[] array, T number)
    {
        int mid = array.Length / 2;
        int min = 0;
        int max = array.Length - 1;
        while (true)
        {
            if (array[mid].Equals(number))
                return mid;

            if (min > max)
                return -1;

            if (array[mid].CompareTo(number) > 0) // 왼쪽
            {
                max = mid - 1;
                mid = (min + max) / 2;
            }
            else if (array[mid].CompareTo(number) < 0) // 오른쪽
            {
                min = mid + 1;
                mid = (min + max) / 2;
            }
        }
    }
    public static void Clear(T[] array, int index, int length)
    {
        for (int idx = index; idx < length; idx++)
        {
            array[idx] = default(T);
        }
    }
    public static void Fill(T[] array, T value)
    {
        for (int idx = 0; idx < array.Length; idx++)
        {
            array[idx] = value;
        }
    }
    public static T Find(T[] array, Predicate<T> match)
    {
        foreach (var elem in array)
        {
            if (match(elem))
                return elem;
        }
        return default(T);
    }
    public static T[] FindAll(T[] array, Predicate<T> match)
    {
        List<T> temp = new List<T>();
        foreach (var elem in array)
        {
            if (match(elem))
            {
                temp.Add(elem);
            }
        }

        return temp.ToArray();
    }
    public static int FindIndex(T[] array, Predicate<T> match)
    {
        for (int idx = 0; idx < array.Length; idx++)
        {
            if (match(array[idx]))
                return idx;
        }
        return -1;
    }
    public static T FindLast(T[] array, Predicate<T> match)
    {
        T result = default(T);
        foreach (var elem in array)
        {
            if (match(elem))
                result = elem;
        }
        return result;
    }
    public static int FindLastIndex(T[] array, Predicate<T> match)
    {
        int result = -1;
        for (int idx = 0; idx < array.Length; idx++)
        {
            if (match(array[idx]))
                result = idx;
        }
        return result;
    }
    public static void ForEach(T[] array, Action<T> action)
    {
        foreach (var elem in array)
        {
            action(elem);
        }
    }
    public static bool Exists(T[] array, Predicate<T> match)
    {
        foreach (var elem in array)
        {
            if (match(elem))
                return true;
        }
        return false;
    }
}