<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Bimtaeur30</title>
    <link>https://bimtaeur30.tistory.com/</link>
    <description>김태준의 포트폴리오 블로그</description>
    <language>ko</language>
    <pubDate>Mon, 11 May 2026 01:30:29 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>bimtaeur30</managingEditor>
    <image>
      <title>Bimtaeur30</title>
      <url>https://tistory1.daumcdn.net/tistory/7828334/attach/63538406af404e88885e7b27508fa403</url>
      <link>https://bimtaeur30.tistory.com</link>
    </image>
    <item>
      <title>[공부 블로그] DependencyInjector(의존성 주입기)</title>
      <link>https://bimtaeur30.tistory.com/134</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요.&lt;br /&gt;오늘은 엔진 심화 교과에서 배운 'DependencyInjector'(이하 DI로 생략)에 대해서 복습 겸 공부 블로그를 작성하게 되었습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DI는 유니티에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;컴포넌트 간 결합도를 낮추고&lt;/span&gt; 테스트 가능성을 높이기 위해 사용합니다. 예를 들어서 오디오 매니저와 플레이어가 있다고 가정해 봅시다. 플레이어가 걷는 소리를 내기 위해 AudioManager.Instance.PlaySFX(); 로 오디오 매니저의 메서드를 직접 호출하게 되면 이것은 두 클래스 간 강한 결합이 됩니다. 이때 직접 참조를 끊어내기 위해 DI를 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 DependencyInjector 코드를 구현해 보면서 하나씩 설명해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 커스텀 어트리뷰트인 &lt;span style=&quot;color: #ee2323;&quot;&gt;InjectAttribute, ProvideAttribute&lt;/span&gt;를 만들어줘야 합니다. 의존성을 주입할 때 의존성을 제공할 대상, 제공받을 대상이 명시되어야 하기 때문입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777448009419&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[AttributeUsage(AttributeTargets.Field | AttributeTargets.Method)]
public class InjectAttribute : Attribute { }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1777448021377&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ProvideAttribute : Attribute { }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위 코드에서 각각 Attribute를 상속받음으로써 커스텀 어트리뷰트를 만들 수 있었고, AttributeUsage로 해당 커스텀 어트리뷰트를 어디에 붙일 수 있는지 제한합니다. 다음으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;IDependencyProvider&lt;/span&gt;를 만들어보겠습니다. IDependencyProvider는 IDependencyProvider를 구현한 클래스는 의존성을 제공할 수 있다는 것을 명시하는 인터페이스로써 역할합니다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1777515792852&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface IDependencyProvider { }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본격적으로 DI클래스 구현을 해보겠습니다. DI클래스는 씬에 있는 모든 모노비헤이비들을 자동으로 스캔해서, &lt;span style=&quot;color: #ee2323;&quot;&gt;의존성을 등록하고 주입하는 역할&lt;/span&gt;을 합니다. DI클래스의 동작 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777516095568&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;씬에 있는 모든 모노비헤이비어 탐색
&amp;darr;
IDependencyProvider 구현체 수집
RegisterProvider() 호출
_registry에 {타입:인스턴스} 저장
&amp;darr;
[Inject] 어트리뷰트가 달린 모노비헤이비어 탐색
Inject() 호출
필드 또는 메서드에 _registry에서 꺼낸 인스턴스 주입&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 먼저 클래스를 만들고 _bindingFlags, _registry 딕셔너리를 선언해 주겠습니다. 여기서 &lt;span style=&quot;color: #ee2323;&quot;&gt;BindingFlags&lt;/span&gt;란, 리플렉션으로 맴버를 탐색할 때 범위를 지정해 주는 '필터'입니다. 또한 &lt;span style=&quot;color: #ee2323;&quot;&gt;DefaultExecutionOrder&lt;/span&gt;는 스크립트의 Awake/OnEnable 실행 순서를 제어하는 어트리뷰트입니다. 이때 숫자가 작을수록 먼저 시작됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777516372186&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[DefaultExecutionOrder(-10)]
public class DependencyInjector : MonoBehaviour
{
    private const BindingFlags _bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
    private readonly Dictionary&amp;lt;Type, object&amp;gt; _registry = new Dictionary&amp;lt;Type, object&amp;gt;();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Awake를 구현해보겠습니다. Awake에서는 씬의 모노비헤이비어를 탐색하고, 구현체를 수집한 후&amp;nbsp;RegisterProvider를 수집하고, 마지막으로 Inject 어트리뷰트가 달린 모노비헤이비어를 탐색한 후 인스턴스 주입 메서드 Inject를 호출해 줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777516845792&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void Awake()
{
    IEnumerable&amp;lt;IDependencyProvider&amp;gt; providers = FindMonoBehaviours().OfType&amp;lt;IDependencyProvider&amp;gt;(); // 모든 모노비헤이비어중 IDependencyProvider를 구현한 클래스들을 찾아서 providers에 넣는다.

    foreach (IDependencyProvider provider in providers)
    {
        RegisterProvider(provider);
    }   

    IEnumerable&amp;lt;MonoBehaviour&amp;gt; injectables = FindMonoBehaviours().Where(IsInjectable);
    foreach(MonoBehaviour injectable in injectables)
    {
        Inject(injectable);
    }
}

private bool IsInjectable(MonoBehaviour mono)
{
    MemberInfo[] members = mono.GetType().GetMembers(_bindingFlags);
    return members.Any(member =&amp;gt; Attribute.IsDefined(member, typeof(InjectAttribute)));
}

private static MonoBehaviour[] FindMonoBehaviours()
{
    return FindObjectsByType&amp;lt;MonoBehaviour&amp;gt;(FindObjectsSortMode.None);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;RegisterProvider&lt;/span&gt;메서드를 구현해 보겠습니다. RegisterProvider는 _registry딕셔너리에 구현체를 등록해 주는 역할을 합니다. RegisterProvider는 클래스와 메서드들을 검사하여 [Provide]가 클래스에 붙은 경우 클래스를 키로 딕셔너리에 등록하고 클래스에 [Provide]가 붙지 않을 경우 메서드들을 전부 구해서 순회하고 [Provide]가 붙은 메서드인 경우 반환타입을 키로 딕셔너리에 등록해 주었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777519157557&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void RegisterProvider(IDependencyProvider provider)
{
    if (Attribute.IsDefined(provider.GetType(), typeof(ProvideAttribute)))
    {
        _registry.Add(provider.GetType(), provider);
        return;
    }

    // 해당 클래스에서 Provide되고 있는 메서드가 있는지를 찾아서 그걸 실행해서 값을 가져온다.
    MethodInfo[] methods = provider.GetType().GetMethods(_bindingFlags);
    foreach(MethodInfo method in methods)
    {
        if (Attribute.IsDefined(method, typeof(ProvideAttribute)))
        {
            Type returnType = method.ReturnType; // 메서드의 반환타입
            object providedInstance = method.Invoke(provider, null); // 메서드 실행
            Debug.Assert(providedInstance != null, $&quot;Provide 메서드에서 null이 반환되었습니다. : {method.Name}&quot;);

            _registry.Add(returnType, providedInstance);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 구현체를 주입해 주는 &lt;span style=&quot;color: #ee2323;&quot;&gt;Inject&lt;/span&gt;메서드를 구현해 보겠습니다. 매개변수로 들어온 injectableMono클래스의 타입을 받고 [Inject] 어트리뷰트가 붙은 모든 필드를 탐색해 fields에 등록합니다. 이후에 fields를 순회하면서 해당 필드가 필요로 하는 필드타입을 구하고 _registry에 등록된 구현체를 받아와서 값을 넣어줍니다. 필드에 값을 모두 넣어준 후 [Inject]가 붙은 어트리뷰트를 메서드를 구해서 해당 메서드의 파라미터 타입 목록을 추출합니다. 각 파라미터 타입으로 _registry에서 인스턴스를 꺼내서 주입할 인자 배열 생성했습니다. 배열을 생성한 후 메서드를 실행시켜서 메서드 주입을 완료시켜 주었습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1777519297621&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private void Inject(MonoBehaviour injectableMono)
{
    Type type = injectableMono.GetType();
    IEnumerable&amp;lt;FieldInfo&amp;gt; fields = type.GetFields(_bindingFlags).Where(field =&amp;gt; Attribute.IsDefined(field, typeof(InjectAttribute)));

    foreach (FieldInfo item in fields)
    {
        Type fieldType = item.FieldType;
        object injectInstance = Resolve(fieldType);
        Debug.Assert(injectInstance != null, $&quot;필드 타입에 대한 인스턴스가 등록되어 있지 않습니다. : {fieldType.FullName}&quot;);

        item.SetValue(injectableMono, injectInstance);
    }

    IEnumerable&amp;lt;MethodInfo&amp;gt; injectableMethods= type.GetMethods(_bindingFlags).Where(method =&amp;gt; Attribute.IsDefined(method, typeof(InjectAttribute)));

    foreach(MethodInfo method in injectableMethods)
    {
        Type[] requiredParams = method.GetParameters().Select(p =&amp;gt; p.ParameterType).ToArray();
        object[] parameters = requiredParams.Select(Resolve).ToArray();
        method.Invoke(injectableMono, parameters);
    }
}

private object Resolve(Type fieldType)
{
    _registry.TryGetValue(fieldType, out object instance);
    return instance;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 오늘은 DependencyInjector에 대해서 복습하고 공부해 보았습니다. 수업을 들을 때는 이해가 잘 되지 않았던 부분이었는데 복습하며 공부해 보니 이해가 잘 되어서 앞으로 프로젝트에 적극 활용해 볼 생각입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>공부블로그</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/134</guid>
      <comments>https://bimtaeur30.tistory.com/134#entry134comment</comments>
      <pubDate>Thu, 30 Apr 2026 12:40:17 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 코드포스 1829E번 문제풀이</title>
      <link>https://bimtaeur30.tistory.com/133</link>
      <description>&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제번호: 1829E&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제명:&lt;span&gt; &lt;span style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot;&gt;E. The Lakes&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제링크:&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://codeforces.com/problemset/problem/1829/E&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/problemset/problem/1829/E&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;문제내용과 예제 입/출력은 위 문제 링크에서 확인해 주시기 바랍니다&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;오늘은 BFS를 활용하는 문제를 풀었습니다. NxM 크기의 사각형이 주어질 때, 사각형 내부에서 가장 넓은 부피의 호수 크기를 구하는 문제입니다. &lt;span style=&quot;color: #666666; text-align: justify;&quot;&gt;방문하지 않은 지점을&amp;nbsp;&lt;/span&gt; 찾아내면 BFS를 활용하여 호수의 넓이를 구하고 최대 부피를 갱신하고 출력해주었습니다. 또한 BFS 탐색 중 각 사분면에 대해서 이동할 수 있도록 정적 dx, dy int형 배열을 선언하여 각각 { 1, -1, 0, 0 }, { 0, 0, 1, -1 }을 넣어주었습니다. 위 dx, dy를 활용해 int nx = x + dx[i]; int ny = y + dy[i]; 와 같이 다음 이동할 정점을 구하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;다음은 정답코드입니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1777446010844&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static int[] dx = { 1, -1, 0, 0 };
static int[] dy = { 0, 0, 1, -1 };

static void Main()
{
    int t = int.Parse(Console.ReadLine());
    for (int i = 0; i &amp;lt; t; i++)
    {
        int[] nm = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
        int n = nm[0];
        int m = nm[1];

        int[,] grid = new int[n, m];
        bool[,] visited = new bool[n, m];

        for (int j = 0; j &amp;lt; n; j++)
        {
            var row = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
            for (int k = 0; k &amp;lt; m; k++)
                grid[j, k] = row[k];
        }

        int maxVolume = 0;

        for (int j = 0; j &amp;lt; n; j++)
        {
            for (int k = 0; k &amp;lt; m; k++)
            {
                if (grid[j, k] &amp;gt; 0 &amp;amp;&amp;amp; !visited[j, k])
                {
                    int volume = BFS(j, k, grid, visited, n, m);
                    maxVolume = Math.Max(maxVolume, volume);
                }
            }
        }

        Console.WriteLine(maxVolume);

    }
}

static int BFS(int sx, int sy, int[,] grid, bool[,] visited, int n, int m)
{
    Queue&amp;lt;(int, int)&amp;gt; queue = new Queue&amp;lt;(int, int)&amp;gt; ();
    queue.Enqueue((sx, sy));
    visited[sx, sy] = true;

    int sum = 0;

    while(queue.Count &amp;gt; 0)
    {
        var (x, y) = queue.Dequeue ();
        sum += grid[x, y];
        for (int i = 0; i &amp;lt; 4; i++)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];


            if (nx &amp;lt; 0 || ny &amp;lt; 0 || nx &amp;gt;= n || ny &amp;gt;= m)
                continue;

            if (grid[nx, ny] == 0 || visited[nx, ny])
                continue;

            visited[nx, ny] = true;
            queue.Enqueue((nx, ny));
        }
    }

    return sum;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>알고리즘 풀이</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/133</guid>
      <comments>https://bimtaeur30.tistory.com/133#entry133comment</comments>
      <pubDate>Wed, 29 Apr 2026 16:00:18 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 코드포스 71A번 문제풀이</title>
      <link>https://bimtaeur30.tistory.com/131</link>
      <description>&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제번호: 71A&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제명: &lt;span style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot;&gt;A. Way Too Long Words&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제링크:&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://codeforces.com/problemset/problem/71/A&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeforces.com/problemset/problem/71/A&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;문제내용과 예제 입/출력은 위 문제 링크에서 확인해 주시기 바랍니다&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요. 오늘은 매우 슬프지만 백준 서버가 서비스를 종료한다는 소식을 접하게 되어 미리 알고리즘 풀이 사이트 갈아탈 겸 코드포스 문제를 간단하게 풀어보았습니다. 너무 긴 문자열을 쓰기 귀찮은 주인공이 단어 길이가 10개가 넘어가면 양 끝쪽에 시작문자, 끝 문자를 적고 그 사이에는 양쪽 끝 문자를 제외한 문자의 개수를 다음과 같이 적기로 하였습니다. (10개 이하라면 입력으로 들어온 단어 그대로 출력)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776482382480&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;s.Length - 2; Console.WriteLine(s[0] + count.ToString() + s[s.Length - 1]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 정답코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1776482425593&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void Main()
{
    int n = int.Parse(Console.ReadLine());
    for (int i = 0; i &amp;lt; n; i++)
    {
        string s = Console.ReadLine();
        if (s.Length &amp;gt; 10)
        {
            int count = s.Length - 2;
            Console.WriteLine(s[0] + count.ToString() + s[s.Length - 1]);
        }
        else
            Console.WriteLine(s);
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘 풀이</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/131</guid>
      <comments>https://bimtaeur30.tistory.com/131#entry131comment</comments>
      <pubDate>Sat, 18 Apr 2026 12:20:29 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 백준 9935번 문제풀이</title>
      <link>https://bimtaeur30.tistory.com/130</link>
      <description>&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제번호: 9935&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제명: 뮨자열 폭발&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제링크:&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://www.acmicpc.net/problem/9935&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/9935&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;문제내용과 예제 입/출력은 위 문제 링크에서 확인해 주시기 바랍니다&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 문자열 폭발이라는 문제를 풀어보았습니다. 주어진 문자열에 폭발 문자열이 포함되어있으면 폭발 문자열은 삭제되고 나머지 문자열은 붙게됩니다. 붙은 문자열이 다시 폭발 문자열을 만들어 연쇄적인 폭발이 일어날 수 있다는 점에 유의해서 코드를 작성해야합니다. 구현은 다음과 같이 했습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;br /&gt;&amp;nbsp;char형 List를 이용해서 주어진 문자열을 하나씩 List에 담아주는 동시에 List의 크기가 폭발문자열 크기 이상이고 List의 마지막 문자가 폭발 문자열의 마지막 문자와 일치한다면 반복문으로 List는 뒤부터 폭발 문자열이 포함되는지 검사합니다. 참이라면, List에서 폭발 문자열 길이만큼 뒤에서 삭제하고 진행합니다. 모든 반목문이 종료되면 List의 요소 개수를 확인하고 0일경우 FRULA, 아닐경우 요소를 하나씩 출력합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;br /&gt;다음은 정답코드입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1776164752764&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void Main()
{
    using StreamReader sr = new StreamReader(Console.OpenStandardInput());
    using StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());

    string str = sr.ReadLine();
    string bomb = sr.ReadLine();

    int len = bomb.Length;
    char last = bomb[len - 1];

    List&amp;lt;char&amp;gt; list = new List&amp;lt;char&amp;gt;();
    for (int i = 0; i &amp;lt; str.Length; i++)
    {
        char c = str[i];
        list.Add(c);

        if (c == last &amp;amp;&amp;amp; list.Count &amp;gt;= len)
        {
            bool match = true;

            for (int j =0; j &amp;lt; len; j++)
            {
                if (list[list.Count - len + j] != bomb[j])
                {
                    match = false;
                    break;
                }
            }

            if (match)
            {
                list.RemoveRange(list.Count - len, len);
            }
        }

    }

    if (list.Count == 0)
        Console.WriteLine(&quot;FRULA&quot;);
    else
        Console.WriteLine(new string(list.ToArray()));
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘 풀이</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/130</guid>
      <comments>https://bimtaeur30.tistory.com/130#entry130comment</comments>
      <pubDate>Tue, 14 Apr 2026 20:05:57 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 백준 2096번 문제풀이</title>
      <link>https://bimtaeur30.tistory.com/129</link>
      <description>&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제번호: 2096&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제명: 내려가기&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제링크:&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://www.acmicpc.net/problem/2096&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/2096&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;문제내용과 예제 입/출력은 위 문제 링크에서 확인해 주시기 바랍니다&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 dp문제인 '내려가기' 문제를 풀었습니다. 3개의 숫자로 이루어진 배열이 n줄 주어졌을 때, 바로 위의 숫자를 선택하거나 바로 위 숫자와 바로 인접한 숫자를 선택하며 내려가는 숫자의 최대 합, 최소 합을 구하는 문제입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;dp[i, j]에서 선택할 수 있는 경우의 수는 바로 위, 위에 인접한 숫자를 선택하는 경우입니다. 이때 i는 3으로 고정된 값이므로&lt;/p&gt;
&lt;pre id=&quot;code_1775966035602&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dpMax[0, i] = Math.Max(dpMax[0, i - 1], dpMax[1, i - 1]) + NumberPad[0, i]; // 왼쪽
dpMax[1, i] = Math.Max(dpMax[0, i - 1], Math.Max(dpMax[1, i - 1], dpMax[2, i - 1])) + NumberPad[1, i]; // 가운데
dpMax[2, i] = Math.Max(dpMax[2, i - 1], dpMax[1, i - 1]) + NumberPad[2, i]; // 오른쪽&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 점화식을 세웠습니다. 시간복잡도는 O(n^2) 입니다. (최소값 구하기도 동일.)&lt;br /&gt;다음은 정답코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1775966093579&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void Main()
{
    using StreamReader sr = new StreamReader(Console.OpenStandardInput());
    using StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());

    int n = int.Parse(sr.ReadLine());
    int[,] NumberPad = new int[3, n];

    for (int i = 0; i &amp;lt; n; i++)
    {
        int[] nums = Array.ConvertAll(sr.ReadLine().Split(), int.Parse);
        NumberPad[0, i] = nums[0];
        NumberPad[1, i] = nums[1];
        NumberPad[2, i] = nums[2];
    }

    int[,] dpMax = new int[3, n];
    dpMax[0, 0] = NumberPad[0,0];
    dpMax[1, 0] = NumberPad[1,0];
    dpMax[2, 0] = NumberPad[2,0];

    int[,] dpMin = new int[3, n];
    dpMin[0, 0] = NumberPad[0, 0];
    dpMin[1, 0] = NumberPad[1, 0];
    dpMin[2, 0] = NumberPad[2, 0];


    for (int i  = 1; i &amp;lt; n; ++i) // 최대
    {
        dpMax[0, i] = Math.Max(dpMax[0, i - 1], dpMax[1, i - 1]) + NumberPad[0, i]; // 왼쪽
        dpMax[1, i] = Math.Max(dpMax[0, i - 1], Math.Max(dpMax[1, i - 1], dpMax[2, i - 1])) + NumberPad[1, i]; // 가운데
        dpMax[2, i] = Math.Max(dpMax[2, i - 1], dpMax[1, i - 1]) + NumberPad[2, i]; // 오른쪽
    }

    for (int i  = 1; i &amp;lt; n; ++i) // 최소
    {
        dpMin[0, i] = Math.Min(dpMin[0, i - 1], dpMin[1, i - 1]) + NumberPad[0, i]; // 왼쪽
        dpMin[1, i] = Math.Min(dpMin[0, i - 1], Math.Min(dpMin[1, i - 1], dpMin[2, i - 1])) + NumberPad[1, i]; // 가운데
        dpMin[2, i] = Math.Min(dpMin[2, i - 1], dpMin[1, i - 1]) + NumberPad[2, i]; // 오른쪽
    }

    sw.Write(Math.Max(dpMax[0, n - 1], Math.Max(dpMax[1, n - 1], dpMax[2, n - 1])) + &quot; &quot;); // 최대
    sw.Write(Math.Min(dpMin[0, n - 1], Math.Min(dpMin[1, n - 1], dpMin[2, n - 1]))); // 최소
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘 풀이</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/129</guid>
      <comments>https://bimtaeur30.tistory.com/129#entry129comment</comments>
      <pubDate>Sun, 12 Apr 2026 12:55:02 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 백준 9657번 문제풀이</title>
      <link>https://bimtaeur30.tistory.com/128</link>
      <description>&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제번호: 9657&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제명: 돌 게임3&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제링크:&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://www.acmicpc.net/problem/9657&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/9657&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;문제내용과 예제 입/출력은 위 문제 링크에서 확인해 주시기 바랍니다&lt;br /&gt;&lt;br /&gt;오늘은 돌게임 3번째 문제를 풀었습니다. 문제를 풀기 위해 SK과 CY가 이기는 경우를 나열해보았습니다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1775283693375&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dp[1] = 1
dp[2] = 0
dp[3] = 1
dp[4] = 1
dp[5] = 1
dp[6] = 1
dp[7] = 0
dp[8] = 1
dp[9] = 0
dp[10] = 1&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;br /&gt;여기서 7로 나누었을때 나머지가 0 또는 2라면 CY가 이기고 아니라면 SK가 이긴다는것을 알 수 있습니다. 이유로는 &lt;span style=&quot;color: #666666; text-align: start;&quot;&gt;이전 상태의 조합으로 패턴이 고정되는 &lt;/span&gt;'필패상태'가 주기적으로 반복되기 때문입니다.&lt;br /&gt;다음은 정답코드입니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1775286104535&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void Main()
{
    using var sr = new StreamReader(Console.OpenStandardInput());
    using var sw = new StreamWriter(Console.OpenStandardOutput());

    int n = int.Parse(sr.ReadLine()!);

    sw.WriteLine((n % 7 == 0 || n % 7 == 2) ? &quot;CY&quot; : &quot;SK&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>알고리즘 풀이</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/128</guid>
      <comments>https://bimtaeur30.tistory.com/128#entry128comment</comments>
      <pubDate>Sat, 4 Apr 2026 16:01:50 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 백준 1912번 문제풀이</title>
      <link>https://bimtaeur30.tistory.com/127</link>
      <description>&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제번호: 1912&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제명: 연속&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제링크:&lt;span&gt;&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://www.acmicpc.net/problem/1912&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1912&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;문제내용과 예제 입/출력은 위 문제 링크에서 확인해 주시기 바랍니다&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 최대 연속 구간합을 구하는 문제를 풀었습니다. 해당 문제의 시간제한부터 살펴보겠습니다.&lt;br /&gt;&lt;/span&gt;1초 (추가 시간 없음)이네요. 완전탐색(O(n^3))으로 풀기엔 시간이 턱없이 부족하다고 판단했습니다. 그래서 동적할당(dp)로 접근을 시도했습니다. thisSum과 maxSum 변수를 이용해 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;thisSum = Math.Max(thisSum + arr[k], 0);&lt;/span&gt; 으로 자신과 arr[k]을 더한값을 0과 비교하여 값을 할당하고, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;maxSum = Math.Max(maxSum, thisSum);&lt;/span&gt; 으로 최댓값을 할당했습니다. 마지막으로 maxSum이 0일경우 모든 수가 음수이라는 뜻이기 때문에 가장 작은 수를 정답으로 출력해주었습니다.&lt;br /&gt;다음은 정답코드입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1775089889213&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void Main()
{
    using StreamReader sr = new StreamReader(Console.OpenStandardInput());
    using StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());

    int n = int.Parse(sr.ReadLine());
    int[] nums = Array.ConvertAll(sr.ReadLine().Split(), int.Parse);
    sw.WriteLine(MaxSubArray(nums, n));
}

static int MaxSubArray(int[] arr, int n)
{
    if (n == 1)
        return arr[0];

    int maxSum, thisSum;
    maxSum = 0;
    thisSum = 0;

    for (int k = 0; k &amp;lt; n; k++)
    {
        thisSum = Math.Max(thisSum + arr[k], 0);
        maxSum = Math.Max(maxSum, thisSum);
    }

    if (maxSum == 0)
        return arr.Max();
    return maxSum;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘 풀이</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/127</guid>
      <comments>https://bimtaeur30.tistory.com/127#entry127comment</comments>
      <pubDate>Thu, 2 Apr 2026 09:31:35 +0900</pubDate>
    </item>
    <item>
      <title>[C#] 백준 14911번 문제풀이</title>
      <link>https://bimtaeur30.tistory.com/126</link>
      <description>&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제번호: 14911&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제명: 궁합 쌍 찾기&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제링크:&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://www.acmicpc.net/problem/14911&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/14911&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;문제내용과 예제 입/출력은 위 문제 링크에서 확인해 주시기 바랍니다&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 '궁합 쌍 찾기' 문제를 풀었습니다. 해시 셋과 브루트포스 알고리즘을 사용하는 문제입니다. 저는 2중 반복문을 돌면서 입력으로 주어진 숫자들을 i, j로 순회했습니다. i+j가 주어진 숫자와 같다면 쌍을 충족하므로 해시 셋에 두 수중 작은 수를 먼저 오게 해서 Item1, Item2로 삽입해주었습니다. 마지막으로 사전순 정렬을 통해 정답을 출력했습니다.&lt;br /&gt;다음은 정답코드입니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1775052410690&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void Main()
{
    using StreamReader sr = new StreamReader(Console.OpenStandardInput());
    using StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());

    int[] nums = Array.ConvertAll(sr.ReadLine().Split(), int.Parse);
    int target = int.Parse(sr.ReadLine());

    HashSet&amp;lt;(int, int)&amp;gt; set = new HashSet&amp;lt;(int, int)&amp;gt;();

    int n = nums.Length;

    for (int i = 0; i &amp;lt; n; i++)
    {
        for (int j = i + 1; j &amp;lt; n; j++)
        {
            if (nums[i] + nums[j] == target)
            {
                int a = Math.Min(nums[i], nums[j]);
                int b = Math.Max(nums[i], nums[j]);

                set.Add((a, b)); // 중복 제거
            }
        }
    }

    // 사전순 정렬
    var list = new List&amp;lt;(int, int)&amp;gt;(set);
    list.Sort((x, y) =&amp;gt;
    {
        if (x.Item1 != y.Item1)
            return x.Item1.CompareTo(y.Item1);
        return x.Item2.CompareTo(y.Item2);
    });

    foreach (var pair in list)
    {
        sw.WriteLine($&quot;{pair.Item1} {pair.Item2}&quot;);
    }

    sw.WriteLine(list.Count);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘 풀이</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/126</guid>
      <comments>https://bimtaeur30.tistory.com/126#entry126comment</comments>
      <pubDate>Wed, 1 Apr 2026 23:06:57 +0900</pubDate>
    </item>
    <item>
      <title>2025 엔진 팀프로젝트 &amp;lt;미니언1000&amp;gt;</title>
      <link>https://bimtaeur30.tistory.com/125</link>
      <description>&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;프로젝트 정보&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;[ 엔진 팀프로젝트 1등 수상   ]&lt;/b&gt;&lt;br /&gt;대회명: 엔진 팀프로젝트&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666; text-align: start;&quot;&gt;출품작명: 미니언 1000&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;개발기간: 25년 9월 ~ 25년 11월&lt;br /&gt;장르: 2D 탑다운 마을운영 시뮬레이션&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;개발인원: 개발 4명&lt;br /&gt;역할: 팀장, UI, 과부하/외로움 시스템, 상점 시스템, 도구 시스템, 땅 확장 시스템, 아트&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;프로젝트&lt;span&gt;&amp;nbsp;&lt;/span&gt;소개&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이번 프로젝트는 엔진교과 팀프로젝트로 진행한 &quot;미니언 1000&quot;이라는 게임입니다. 클래시 오브 클랜, 트롱렛츠(넷플릭스 블랙미러 게임)를 레퍼런스 삼아 개발하였습니다. 미니언들을 번식시키고 건물을 지어 자원을 획득하고, 미니언들에게 먹이를 주고 보살피면서 동시에 적의 침략도 막아내야 합니다. 미니언들의 개체수가 1000개 이상이 되면 엔딩이 나오며 게임을 클리어할 수 있습니다.&lt;br /&gt;미니언들의 개체수를 1000마리로 만들기 위해 무작정 개체수를 늘리는 건물만 만든다면 결국 땅에 비해 미니언이 많아져서 미니언이 과부하 상태에 돌입하고 땅 크기에 비례한 일정 개체수로 안정화될 때까지 미니언들이 터지게 되고 이는 곧 자원낭비로 이어집니다. 따라서 흙을 얻어 개체수를 늘리기 전 적절한 땅 크기를 확보해야 하고 자원은 돌, 흙, 나무로 총 3가지가 존재하는데, 어떤 자원을 집중적으로 획득할 것인지에 대한 전략적 선택도 요구됩니다.&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;기획 및 개발과정&lt;/h3&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;팀원들과 모여서 처음 기획을 할 때에는 여러 가지 아이디어가 나왔었지만 최근에 제가 우연히 플레이했었던 넷플릭스 블랙미러의 작품 '트롱렛츠' 게임을 레퍼런스 삼아 게임을 만들어보는 것을 제안했습니다. 팀원들은 이에 동의했고 기존 트롱렛츠에서 슈퍼셀의 '클래시 오브 클랜'에서 봇들의 침략 시스템을 추가하기로 했습니다. 그렇게 미니언 1000의 초기 기획이 완성되었습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이번 프로젝트에서 개발을 진행하면서 &lt;span style=&quot;color: #ee2323;&quot;&gt;모노싱글톤&lt;/span&gt;을 처음 도입 및 사용해보았습니다. 전역에서 접근해야 할 스크립트(A)에 계속해서 싱글톤을 구현하자니 보통 귀찮은 일이 아니었습니다. 그래서 모노싱글톤을 구현하고 A에 모노싱글톤을 상속시키는 구조로 개발을 진행했습니다. 또한 UI 전체를 맡아 본격적으로 UI를 개발하면서 &lt;span style=&quot;color: #ee2323;&quot;&gt;엥커와 피봇, 다양한 Rectransform 전용 컴포넌트&lt;span style=&quot;color: #333333;&quot;&gt;들을&lt;/span&gt; &lt;span style=&quot;color: #333333;&quot;&gt;활용하여 개발을 할 수 있게 되었습니다. 또한 파티클 연출 등 시각적인 즐거움을 유저에게 전달하기 위해 노력했고 이외에도 여러 기술을 시도하며 성장할 수 있었습니다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;소감 및 마무리&lt;/h3&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이번 프로젝트에서는 처음으로 1등으로 선정되어 정말 기뻤습니다. 이번 프로젝트를 통해 여러 개발스킬을 향상시킬 수 있어서 정말 좋은 기회였다고 생각하고 아쉬운 점으로는 더 테스트를 많이 해보면서 밸런스 패치를 하면 좋았을걸이라는 후회가 들기도 합니다. 읽어주셔서 감사합니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>프로젝트</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/125</guid>
      <comments>https://bimtaeur30.tistory.com/125#entry125comment</comments>
      <pubDate>Tue, 31 Mar 2026 10:53:48 +0900</pubDate>
    </item>
    <item>
      <title>2025 동아리 팀프로젝트 &amp;lt;배고픈 사람들&amp;gt;</title>
      <link>https://bimtaeur30.tistory.com/124</link>
      <description>&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;프로젝트 정보&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;[ 동아리 팀프로젝트 3등 수상   ]&lt;/b&gt;&lt;br /&gt;대회명: 동아리 팀프로젝트&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666; text-align: start;&quot;&gt;출품작명: 배고픈 사람들&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;개발기간: 25년 11월 ~ 25년 12월 (약 3주)&lt;br /&gt;장르: 2D 전투 시뮬레이션&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;개발인원: 개발 6명, 아트 1명&lt;br /&gt;역할: 기장(팀장), 정비소 시스템, UI&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;프로젝트 소개&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이번 프로젝트는 동아리 '빵인'에서 기장 및 팀장을 맡아 개발한 '배고픈 사람들'이라는 게임입니다.&lt;br /&gt;이 게임속 세계관은 전 세계 모든 사람들이 식량부족으로 인해 배고픔에 굶주리게 되었고 플레이어(푸드트럭)는 트럭 위에 음식 포탑을 설치해 배고픈 사람들이 트럭을 쫓아오면 배고픈 사람들에게 음식을 쏘아준다는 설정으로 이루어져 있습니다. 배고픈 사람들은 굶주림으로 인해 매우 예민해진 상태임으로 난폭한 폭력적인 성향을 띠기 때문에 해당 게임에서 전략적으로 트럭 슬롯을 추가하고 다양한 터렛을 구매/부착하여 빠르게 배고픈 사람들에게 음식을 쏘아 배부르게 만들어 더는 쫓아오지 않게 하는 게 핵심입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그렇게 20번째 마을까지 무사히 도착하면 엔딩 및 크레딧과 함께 게임이 마무리됩니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;기획 및 개발과정&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;처음 기획에서는 푸드트럭을 자유롭게 운영하며 장사하는 푸드트럭 운영 게임을 기획했습니다. 이때는 개발기간을 약 1~2달 정도로 예상하고 기획했던 때라 기획볼륨을 꽤 크게 잡아두었습니다. 하지만, 곧 엔진 팀프로젝트와 해당 프로젝트의 개발기간이 겹칠 수 있다는 사실을 알게 되고 1년에 3번 있는 동아리 팀프로젝트 활동보단 1년에 1번있는 엔진 팀프로젝트에 집중해 보기로 동아리 팀원들과 합의 하에 기획 볼륨을 낮추어 전략적 푸드트럭 전투 시뮬레이션 장르로 기획을 수정하였습니다.&lt;br /&gt;&lt;br /&gt;이번 개발과정에서는 팀원들과 역할을 분담하여 각자 자신의 파트를 개발했습니다. 저는 위에 프로젝트 정보에 적어둔 기장(팀장), 정비소 시스템, UI 를 맡아 개발하였습니다.&lt;br /&gt;&lt;br /&gt;이번 프로젝트를 통해 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;이벤트 채널 시스템&lt;/span&gt;을 처음 도입 및 사용해보았습니다. 이벤트 채널 시스템을 도입한 이유는 객체 간의 참조를 최소화하기 위해서였습니다. 이전 프로젝트들에서는 이벤트를 구독/해제할 때마다 다른 객체들을 직접적으로 참조해서 강한 결합성을 띈다는 점과 확장성에 취약하다는 단점이 있다는 것을 깨달았기 때문입니다.&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;소감 및 마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트에서는 기획 최대점수를 기록했지만 아쉽게도 개발점수가 기대에 미치지 못해 3등이라는 결과를 얻게 되었습니다. 개발점수가 낮다는 것의 의미는 기술적인 면이 부족하다는 것 보단 기획된 내용에 비해 개발된 실제 결과물이 아쉽다는 의미였습니다. 어떤 점이 문제였을까 고민해 본 결과 제가 생각해 낸 답은 플레이어에게 너무 똑같은 플레이환경을 제공한다는 것이었습니다. 스테이지가 증가해도 적의 공격패턴은 비슷하고 난이도만 올라가며 결국엔 정해진 아이템을 살 수밖에 없게 만든다는 것이었습니다. 이는 곳 자유도 부족으로 이어질 수 있습니다. 또한 전투 시뮬레이션을 구경하는 도중 플레이어는 아무것도 할 수 있는 게 없습니다. 차라리 시뮬레이션 도중 사용할 수 있는 스킬이나 건너뛰기를 추가했으면 좋았을 것이라는 생각이 들기도 했습니다.&lt;br /&gt;앞으로의 동아리 팀 프로젝트에서는 이번 프로젝트에서 느꼈었던 단점들을 보완하고 1등을 목표로 달려보겠습니다.&lt;br /&gt;감사합니다.&lt;/p&gt;</description>
      <category>프로젝트</category>
      <author>bimtaeur30</author>
      <guid isPermaLink="true">https://bimtaeur30.tistory.com/124</guid>
      <comments>https://bimtaeur30.tistory.com/124#entry124comment</comments>
      <pubDate>Sun, 29 Mar 2026 13:51:52 +0900</pubDate>
    </item>
  </channel>
</rss>