<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>pht_974.log</title>
        <link>https://velog.io/</link>
        <description>초보개발자</description>
        <lastBuildDate>Thu, 04 Apr 2024 12:40:01 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>pht_974.log</title>
            <url>https://velog.velcdn.com/images/pht_974/profile/260f56dc-443a-4ae4-8238-7fcf1d8b59dd/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. pht_974.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/pht_974" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[4월4일 최종프로젝트]]></title>
            <link>https://velog.io/@pht_974/4%EC%9B%944%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@pht_974/4%EC%9B%944%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Thu, 04 Apr 2024 12:40:01 GMT</pubDate>
            <description><![CDATA[<h2 id="기술면접">기술면접</h2>
<p>오버라이딩은 자식클래스가 부모클래스에서 물려받은 메소드를 자유롭게 변형해서 사용가능한 기능이다. 단 메소드의 이름, 메소드의 매개변수의 개수,순서,데이터타입,return타입이 일치해야한다.
오버로딩 같은 클래스 내부에서 메소드를 확장하기 위한 개념이다. 같은 이름의 메서드를 다양한 매개변수 타입과 개수로 오버로딩하여 사용가능하다. 이때 메소드 매개변수의 개수또는 타입이 달라야 하며 return타입도 달라야한다.</p>
<h2 id="최종프로젝트">최종프로젝트</h2>
<p>JSON 다루기 힘들다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[4월3일 최종프로젝트]]></title>
            <link>https://velog.io/@pht_974/4%EC%9B%943%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@pht_974/4%EC%9B%943%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Wed, 03 Apr 2024 12:06:07 GMT</pubDate>
            <description><![CDATA[<h2 id="기술면접">기술면접</h2>
<blockquote>
<p>상속이란 무엇인지 프로젝트 내에 적용해 본 부분과 함께 예를 들어 설명해주세요.</p>
</blockquote>
<p>상속이란 하나의 클래스가 기존에 정의된 클래스의 필드와 메서드를 물려받는것입니다.
상속을 함으로써 코드의 재사용성을 높일수 있고 중복을 줄일수있습니다.
사용해본 예로는 부모클래스로 CharacterStatsHandler를 제작한 다음 그것을 Player와 Enemy에게 상속시켜 각각의 상태를 두며 작업을 했던적이 있습니다.</p>
<h2 id="최종프로젝트">최종프로젝트</h2>
<p>어제의 작업을 이어서 진행하였다. 상점을 제작하는것에대한 로드맵을 완성시켰고 작업을 어떻게해야할지 몰라 튜터님에게 다녀왔었다. 일단 엑셀로 데이터테이블을 만들고 그것을 JSON으로 저장해보는것이 좋을거같다고하셔서 염예찬튜터님의 퀘스트특강을 다시들으며 제작을 했었다. 문제는 이과정이 정말 순탄치않았다...
처음 필요한것을 import하는데 git을 최신화시켜도 계속 설치가 되지않아 따로 다운받은후 Asset에 추가하는 방식으로 작업을 진행했다. 그러나 엑셀을 변환하는과정에서
<img src="https://velog.velcdn.com/images/pht_974/post/00211ddf-90e5-44bc-bcfc-51062f70d776/image.PNG" alt="">
계속 이런오류가 발생하였다. 무슨문제인지 전혀감이안잡혀 강의를 돌려보며 제작해보고 관련된오류가있나 구글링도해봤는데 안나와 튜터님에게 다시가보니 엑셀이아니라 한셀로 제작한파일을 넣고 실행시켜서 그런거라는 답변을받았다....
이제 두번다시 한셀을 쓰지않을것같다.
일단 제일문제였던것이 끝났으니 내일부턴 작업속도가 나올거같다..아마도..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[4월2일 최종프로젝트TIL]]></title>
            <link>https://velog.io/@pht_974/4%EC%9B%942%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8TIL</link>
            <guid>https://velog.io/@pht_974/4%EC%9B%942%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8TIL</guid>
            <pubDate>Tue, 02 Apr 2024 11:49:40 GMT</pubDate>
            <description><![CDATA[<h2 id="기술면접">기술면접</h2>
<blockquote>
<ol start="20">
<li>객체지향이란 무엇인지 설명해주세요.<ol>
<li>(꼬리질문) 객체지향의 특징은 무엇이 있나요?</li>
<li>(꼬리질문) OOP란?</li>
<li>(꼬리질문) SOLID 원칙은 무엇인가요?</li>
</ol>
</li>
</ol>
</blockquote>
<p>객체지향이란 문제를 여러개의 객체 단위로 나누어 작업하는 방식으로 객체들이 서로 유기적으로 상호작용하는 프로그래밍 이론입니다. 이때 객체는 상태와 행위를 하나로 묶은 그룹입니다. 코드의 재사용성과 유지보수성이 높습니다.</p>
<p>객체지향의 특징으론
데이터와 해당데이터를 처리하는 메서드를 하나의 단위로 묶어 외부에서 직접적으로 접근할수없도록 보호하는 캡슐화</p>
<p>객체가 상황에따라 여러 가지 형태를 가질수 있는 다형성 (ex오버라이딩, 오버로딩)
[오버라이딩 – 부모클래스 메서드를 자식클래스에서 재정의하여 사용]
[오버로딩 – 같은 이름의 메서드를 다양한 매개변수 타입과 개수로 오버로딩하여 사용]</p>
<p>객체들의 공통된 특징, 본질만 모아 추출, 설계(역할)와 구현을 분리하는 추상화</p>
<p>여러 객체들이 지닌 공통된 특성을 부각시켜 하나의 개념이나 법칙으로 성립되는 상속
이 있습니다.</p>
<p>OOP는 객체지향 프로그래밍(Object Oriented Progtamming)의 약자로 프로그램을 객체들의 모임으로보고 이 객체들이 서로 상호작용 하도록 설계하는 프로그래밍 패러다임입니다.</p>
<p>SOLID 원칙으로는
단일책임원칙(Single Responsibility Principle)
클래스 모듈 또는 함수가 단 하나의 주요 책임만을 가져야 한다는 원칙
개방/폐쇄원칙(Open-Closed Principle)
클래스,모듈,함수등은 확장에는 열려있어야하고 변경에는 닫혀있어야한다.
리스코프치환원칙(Liskov Substitution Principle)
상위타입객체를 하위타입 객체로 대체해도 프로그램의 정확성은 유지되어야한다.
인터페이스 분리원칙(Interface Segregation Principle)
클라이언트가 사용하지 않는 메서드에 의존하지 않아야 한다는 원칙
의존성 역전원칙(Dependency Inversion Princicle)
고소준 모듈은 저수준모듈에 의존하지 말아야 하며 양쪽모두 추상화에 의존해야한다.
는 원칙들입니다.</p>
<h2 id="최종프로젝트">최종프로젝트</h2>
<p>에어의 캐릭터구현에 더이상 진전이 없어보여 팀원들에게 상태를 공유하고 다른 부분을 잡아 진행하기 시작하였다.
상점시스템을 구현하기위해 자료와 설계도를 제작하느라 오늘하루가 전부 소요되었다.
<img src="https://velog.velcdn.com/images/pht_974/post/4005279b-68af-4287-bbf3-2bf85c3f9a62/image.png" alt="">
오늘하루 고민하면서 제작한 내용이다. 이부분은 최종본이아니기때문에 언제든 수정및 보완이 될수있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3월29일 TIL]]></title>
            <link>https://velog.io/@pht_974/3%EC%9B%9429%EC%9D%BC-TIL</link>
            <guid>https://velog.io/@pht_974/3%EC%9B%9429%EC%9D%BC-TIL</guid>
            <pubDate>Fri, 29 Mar 2024 11:55:27 GMT</pubDate>
            <description><![CDATA[<h2 id="최종프로젝트">최종프로젝트</h2>
<p>코드가 너무 난잡하게 작성되어 내가 내코드를 이해하지못하는지경에 이르러 전체적으로 코드를 돌아보고 그려보는것을 어제했으나 난잡하게 그려져있어 다시 그리며 코드를 이해했다.
<img src="https://velog.velcdn.com/images/pht_974/post/9edc05f1-07a8-4117-be78-d1b4b5abd2ee/image.png" alt="">
문제는 이렇게봐도 정신이없다는것이다... 저게 기능하나인데...
그래도 코드이해도가 올라 제작하려했던부분을 제작하는데 도움이 되긴했다.
오늘 진행사항은 후크가 매달려있는 판정일때 흡입액션이 제대로 동작하지 않는 문제가있었는데
그부분을 수정하면서 자잘한 버그를 수정하였다.
현재는 에어가 후크를 바라보며 1초동안 흡입액션을 지속하면 함수가 불려지는것까지 완료가 되었으나 함수가 1번만 호출되어 날아가다 끊기는 문제가 있다. 이것을 수정할 계획이다.
그리고 기술면접공부는 내일할 예정이다. 지금 공부보다 작업이 급하다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3월28일 최종프로젝트]]></title>
            <link>https://velog.io/@pht_974/3%EC%9B%9428%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@pht_974/3%EC%9B%9428%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Thu, 28 Mar 2024 13:34:10 GMT</pubDate>
            <description><![CDATA[<h2 id="최종프로젝트">최종프로젝트</h2>
<p>오늘은 후크가 매달려있는상태라면 에어가 흡입액션을 했을경우 후크에게 날아가도록 코드를 작성하려고했으나 코드를 너무 난잡하게 작성해둔 상태라 내가 내코드를 이해못해 제대로 작성하지 못하는 상황이 발생하였다. 그래서 코드를 전부 천천히 뜯어보면서 어떻게 돌아가고있는지 체크했다.
<img src="https://velog.velcdn.com/images/pht_974/post/b0abd933-68d2-4e6e-b83d-616f974ff1d5/image.png" alt="">
처음 작성해보는내용이라 엄청 난잡하게 작성이되었다. 이것을 좀더 깔끔하게 정리할수있다면 다시 정리해봐야겠다.
일단 제일 왼쪽에 존재하는 내용을 작성해본 다음 필요한코드는 이미 전부 구현이 되어있는 상태이기때문에 잘 요리해봐야겠다.</p>
<h2 id="기술면접">기술면접</h2>
<blockquote>
<p> 스택, 힙 메모리란 무엇이며 어떤 차이가 있는지 비교해서 설명해주세요.</p>
</blockquote>
<p>스택은 정적으로 메모리가 할당되는 영역이다. 함수의 호출과 함께 할당되며 함수의 호출과 관계되는 지역변수와 매개변수가 저장되는 영역이고 함수의 호출이 완료되면 소멸된다.
푸시으로 데이터를 저장하고 팝으로 데이터를 꺼낸다.
후입선출 구조를 가지고있다.
매우빠르게 액세스가 가능하지만 메모리크기가 제한되어있다는 단점이있다.</p>
<p>힙은 사용자에 의해 메모리 공간이 동적으로 할당되고 해제되는 영역이다. 전역변수를 다루고 사용자가 직접 관리해야하는 메모리 영역이다.
메모리크기에 제한은없지만 상대적으로 액세스가 느리다는 단점이있다.</p>
<h4 id="주저리">주저리</h4>
<p>분명 다 작성해둔코드인데 내가 이해를못하고 제대로 활용못해 금방끝날작업이 계속 오래걸리니 현타가 온다...
최종프로젝트의 마지막까지 고민을 해봐야할것같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3월27일 최종프로젝트 TIL]]></title>
            <link>https://velog.io/@pht_974/3%EC%9B%9427%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL</link>
            <guid>https://velog.io/@pht_974/3%EC%9B%9427%EC%9D%BC-%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-TIL</guid>
            <pubDate>Wed, 27 Mar 2024 12:28:00 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<blockquote>
<ol start="52">
<li>콜라문제</li>
</ol>
</blockquote>
<pre><code>using System;

public class Solution {
    public int solution(int a, int b, int n) {
        int answer = 0;

        while(n &gt;= a)
        {
            answer += (n / a) * b;
            n = (n / a) * b + n % a;
        }
        return answer;
    }
}</code></pre><p>변수 a,b,c는 a : 내가 줘야하는 양, b : 내가 받는 양, n : 가지고 있는 빈병 개수 를 의미합니다. 반복문으로 n이 a보다 크거나 같으면 코드를 계속진행하고 answer에 n을 a로 나눈값에 b를 곱한것을 더해주고 n에다(n / a) * b + n % a; 를 넣어주고 리턴합니다.</p>
<p>이문제는 너무어려워서 찾아보고 공부한다음 작성했다. 조금있으면 레벨3인데 걱정이된다..</p>
<h2 id="기술면접">기술면접</h2>
<blockquote>
<p>16.선택 정렬과 버블 정렬에 대해 설명해주시고, 코드를 작성해보세요.</p>
</blockquote>
<p>선택정렬은 숫자를 넣을 자리를 선택하고 그 자리에 가장작은 숫자를 찾아 넣어주는 알고리즘입니다. 코드는</p>
<pre><code>static void Main(string[] args)
{
    int[] array = { 10, 5, 6, 8, 9, 2, 3, 1, 7, 4 };
    int target, temp;

    for(int i = 0; i &lt; array.Length - 1; i++)
    {
        target = i;

        for(int j = i + 1; j &lt; array.Length; j++)
        {
            if (array[j] &lt; array[target])
                target = j;
        }
        if( i != target )
        {
            temp = array[i];
            array[i] = array[target];
            array[target] = temp;
        }
    }
    for(int i = 0;i &lt; array.Length; i++)
    {
        Console.WriteLine(array[i]);
    }
}</code></pre><p>배열중 제일앞에있는 숫자를 target으로 지정한다음 i뒤의 숫자와 일일히 비교하고 target숫자보다 j숫자가 작으면 교환을 해줍니다. 마지막으로 i와 target이 일치하지않는다면 두 숫자를 교환해줍니다. 이과정을 끝까지 반복하는것이 선택정렬입니다.</p>
<p>버블정렬은 두 개의 인접한 원소를 비교하여 작은값을 앞쪽으로 큰값을 뒤쪽으로 교환하는 정렬 알고리즘입니다. 코드는</p>
<pre><code>internal class Program
{
    static void Main(string[] args)
    {
        int[] array = { 10, 5, 6, 8, 9, 2, 3, 1, 7, 4 };
        int n = array.Length;

        for(int i = 0; i &lt; n - 1; i++)
        {
            for(int j = 0; j &lt; n - i - 1; j++)
            {
                if (array[j] &gt; array[j + 1])
                {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }

        for(int i = 0; i &lt; array.Length; i++)
        {
            Console.WriteLine(array[i] + &quot; &quot;);
        }
    }
}</code></pre><p>이중반복문을 설정합니다. 앞의 숫자와 뒤의숫자를 비교해 뒤숫자가 작다면 두숫자를 교환해줍니다.</p>
<h2 id="최종프로젝트">최종프로젝트</h2>
<p>어제 오늘 2일간
흡입 발사액션 유도선제작을 오브젝트로 보여주도록 제작하였고 발사액션 코드를 일부수정하였다.
또 끌고와야하는 오브젝트가 벽뒤에 존재할경우 끌고오지못하도록 처리했으며 총구앞 일정거리 이내에 오브젝트 및 플레이어 이외에 다른것들이 존재하면 총구위치에서 발사하는것이아닌 플레이어 몸체위치에서 발사가 되도록 코드를 제작하였다. 내일부턴후크가 벽에 고정되어있을 경우 후크를 끌고오는것이아니라 에어가 끌려가도록</p>
<p>_latestTarget.transform.position = Vector3.Slerp(target, _weaponPoint.position, 0.05f);
이것을 AddForce로 변환(약간 곡선느낌나게 베지어곡선으로 곡선모양을 구한다음 해당방향으로 AddForce하도록)</p>
<p>나중에 총구위치에서 바닥으로 레이를쏴서 바닥이체크되면 돌리기제한
체크되지않으면 좀더 돌릴수있도록제작</p>
<p>라인렌더러로 유도선 변경
등등을 구현할예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 프로젝트 13일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-13%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-13%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Mon, 25 Mar 2024 11:43:54 GMT</pubDate>
            <description><![CDATA[<p>오늘은 중간발표를 통해 다른팀들의 작업현황과 현재 우리팀의 제작된 부분까지 공개하였다. 에어캐릭터가 약 7~80% 구현이 완료된상황이라 내일안에 유도선 작업을 마무리하고 끌어오는 로직을 베지어곡선으로 변경, 후크가 고정되어있을경우 에어가 끌려가도록 변경하면 에어캐릭터가 완성된다.</p>
<h2 id="기술면접">기술면접</h2>
<blockquote>
<ol start="14">
<li>콜백이란 무엇인가요? 사용해봤는지?</li>
</ol>
</blockquote>
<p>콜백은 특정 이벤트나 조건이 발생했을 때 함수 또는 메서드를 다른 함수나 메서드의 매개변수로 전달해서 호출되도록 합니다. 델리게이트 Action Func등에서 사용 가능합니다.
InputSystem에서 event action을 사용해 사용자의 입력을 받고 다른 함수가 불려지도록 작성해본 경험이 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 12일]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-12%EC%9D%BC</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-12%EC%9D%BC</guid>
            <pubDate>Thu, 21 Mar 2024 13:13:10 GMT</pubDate>
            <description><![CDATA[<p>에어의 흡입액션으로 빨려오는부분까지 완성되었다.
이제 오브젝트의 위치와 총구의위치가 0.1f 이내일때 흡입액션을 끝내고 발사준비액션으로 전환하는코드를 작성하면된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 11일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-11%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-11%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Wed, 20 Mar 2024 12:09:19 GMT</pubDate>
            <description><![CDATA[<p>어제 TIL을 작성하지 못해서 오늘 2일치분량의 TIL을 작성할것이다.</p>
<blockquote>
<ol start="46">
<li>숫자 문자열과 영단어</li>
</ol>
</blockquote>
<pre><code>using System;
public class Solution {
    public int solution(string s) {
        int answer = 0;

        //string.Replace(&quot;해당 문자열을&quot;, &quot;해당 문자열로&quot;);
        s = s.Replace(&quot;zero&quot;, &quot;0&quot;);
        s = s.Replace(&quot;one&quot;, &quot;1&quot;);
        s = s.Replace(&quot;two&quot;, &quot;2&quot;);
        s = s.Replace(&quot;three&quot;, &quot;3&quot;);
        s = s.Replace(&quot;four&quot;, &quot;4&quot;);
        s = s.Replace(&quot;five&quot;, &quot;5&quot;);
        s = s.Replace(&quot;six&quot;, &quot;6&quot;);
        s = s.Replace(&quot;seven&quot;, &quot;7&quot;);
        s = s.Replace(&quot;eight&quot;, &quot;8&quot;);
        s = s.Replace(&quot;nine&quot;, &quot;9&quot;);

        int k;
        bool strToInt = int.TryParse(s, out k);     //변환 후 해당 문자열이 숫자이면
        if(strToInt) answer = k;                    //answer에 숫자 대입

        return answer;                              //answer 반환
    }
}</code></pre><p>처음엔 딕셔너리를 사용해야하나? 생각을 하고 코드를 작성하다 string.Replace라는 코드가 현재 문자열에서 발견되는 지정된 유니코드 문자 또는 String을 모두 지정된 다른 유니코드 문자 또는 String으로 바꾼 새 문자열을 반환하는 기능을 가지고 있는것을 알게되었다.
그래서 영단어와 숫자를 지정해준다음 반환해주는 코드를 작성하였다.</p>
<blockquote>
<ol start="47">
<li>문자열 내 마음대로 정렬하기</li>
</ol>
</blockquote>
<pre><code>using System;

public class Solution {
    public string[] solution(string[] strings, int n) {
        string[] answer = new string[] {};
        // Sort 에 간단한 문자의 비교 연산을 추가하여 실행
            Array.Sort(strings, (str1, str2) =&gt; {
                // 문자 추출
                var word1 = str1.Substring(n, 1);
                var word2 = str2.Substring(n, 1);

                // 같은 단어면 사전순 정렬, 아니라면 해당 문자 기준으로 비교
                if(word1 == word2)
                {
                    return str1.CompareTo(str2);
                }
                else
                {
                    return word1.CompareTo(word2);
                }

            });

            answer = strings;
        return answer;
    }
}</code></pre><h2 id="기술면접">기술면접</h2>
<p>화요일 면접및 기술면접때 질문에 대한 키워드가 없어서 두루뭉실하게 답변을 한다는 피드백을 받았었다. 주말간 1~9번 질문에 대해 키워드를 설정하고 그것에 대해 답변을 준비할 예정이다.(이것은 주말에 TIL을 한번 작성해 정리할예정이다.)</p>
<blockquote>
<p>10.제네릭이란 무엇인가요?</p>
</blockquote>
<p>제네릭은 데이터형식을 일반화하여 코드의 재사용성과 유연성을 향상시켜주는 도구입니다.
여러 데이터형식에 대해 동일한 로직을 적용해야할때나 데이터 형식에 따라 다른연산을 수행해야 할 때 제네릭함수를 사용하면 유용합니다.
키워드 : 데이터형식을 일반화하여 코드의 재사용성</p>
<blockquote>
<p>11.델리게이트(Delegate)의 개념에 대해 설명해주세요.</p>
</blockquote>
<p>델리게이트는 대리자 라는 의미를 가지고있는데 말 그대로 메서드를 대신 호출해주는 기능을 하는데 대리자가 메서드의 주소를 참조하기때문에 메서드를 대신 호출이 가능합니다. 예를들면 KeyDown같은 이벤트처리기를 통해 등록된 메서드를 호출하는 방식이 있습니다.</p>
<h2 id="최종-프로젝트">최종 프로젝트</h2>
<p>기존코드는 velocity를 이용해 움직임을 받아오도록 코드를작성하였는데 후크의 스윙액션과 충돌이 일어나는 경우가 발생하여 AddForce방식으로 전면교체를 했다.</p>
<pre><code>//플레이어 이동속도 코드
        var groundForce = _moveSpeed * 5f;
        _rigidbd.AddForce(new Vector2((_horizontal * groundForce - _rigidbd.velocity.x) * groundForce, 0f));
        _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _rigidbd.velocity.y);</code></pre><pre><code>//점프
        if (_coyoteTimeCount &gt; 0f &amp;&amp; (_isJumpPerformed || (_isJumping &amp;&amp; _isJumpBufferCheck)))
        {
            _coyoteTimeCount = 0f;
            _isJumping = false;
            _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _jumpingPower);
        }</code></pre><p>주요코드는 이렇게 바꾸었고 세세한 bool값과 float값을 새로 설정해 점프버퍼와 움직임 코요테타임도 정상적으로 작동하게 제작하였다.</p>
<p>이어서 현재까지 진행된 에어코드이다.
먼저 에어의 무기회전은 스파르타코딩클럽 입문주차에서 사용했던 내용을 그대로 가져와 적용시켰다. </p>
<pre><code>//감지거리
    [SerializeField] public float detectionDistance = 3f;
    private LayerMask _objectMask;  //이것은 열쇠등등 오브젝트
    private LayerMask _hookMask;  //이걸 후크레이어로 설정해둬야할듯
    private LayerMask _collisionLayerMask;  //두개 레이어 
    private float _shortestDistance;</code></pre><p>이것들로 오브젝트와 후크레이어감지, 총구에서 탐지하는거리, 가장가까운거리탐지를 하는 값을 설정해줬다.</p>
<pre><code>//가장 가까운 객체
    private Collider2D _closestTarget;
    private Collider2D _latestTarget;</code></pre><p>가장가까운 객체 1개만 가져와야하기때문에 선언했다.</p>
<pre><code>private void Awake()
    {
        _camera = Camera.main;
        _closestTarget = null;
        _shortestDistance = float.MaxValue;
        _objectMask = LayerMask.GetMask(&quot;Object&quot;);
        _hookMask = LayerMask.GetMask(&quot;Hook&quot;);
        _collisionLayerMask = _objectMask | _hookMask;
    }</code></pre><p>시작하면서 필요한것들을 선언하였다.</p>
<pre><code>public PlayerInput playerInput { get; private set; }

    private void Start()
    {
        playerInput = GetComponent&lt;PlayerInput&gt;();

        playerInput.playerActions.Look.performed += Look;
        playerInput.playerActions.Action.performed += PlayerActionPerformed;
        playerInput.playerActions.Action.canceled += PlayerActionCanceled;
    }</code></pre><p>inputAction을 사용하기때문에 구독및 선언을 해주었다.</p>
<pre><code>private void FixedUpdate()
    {
        RotateArm();
        if (_isClick)
        {
            ObjectCheck();
        }
    }</code></pre><p>무기가 회전하는것과 클릭하였을때 함수가 실행되도록 FixedUpdate를 제작하였다.</p>
<p>이제 오브젝트를 체크하는것인데 OverlapCircleAll메서드를 활용해 원형거리안에있는 오브젝트 전부 체크하여 리스트에 넣었다.
그리고 최단거리물체 1개가 필요하기때문에 가장가까운 오브젝트를 체크하는 코드를 제작하였고 총구위치벡터와 오브젝트위치벡터의 각도가 40도 이내라면 감지하는것까지 코드가 완성되었다.
이제 감지된물체가 곡선을그리며 총구위치로 끌여당겨와지는것을 구현하면된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 9일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-9%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-9%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Mon, 18 Mar 2024 14:25:05 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<blockquote>
<ol start="45">
<li>시저암호</li>
</ol>
</blockquote>
<p>이 문제는 각 알파벳을 일정한 거리만큼 밀어서 다른알파벳으로 바꾸는 암호화방식을 만드는것이다.</p>
<pre><code>using System;
public class Solution {
    public string solution(string s, int n) {
        string answer = &quot;&quot;;
        foreach(char c in s)
        {
            if(c!=&#39; &#39;)
            {
                int tmp = 0;
                //아스키 코드 A=65, Z=90, a=97, z=122
                if((int)c&lt;91)
                {
                    tmp = (int)c + n;
                    if(tmp&gt;90) tmp = 64 + (tmp-90);
                }
                else
                {
                    tmp = (int)c + n;
                    if(tmp&gt;122) tmp = 96 + (tmp-122);
                }

                answer += Convert.ToChar(tmp);    
            }else
                answer += &#39; &#39;;    
        }
        return answer;
    }
}</code></pre><p>알파벳의 아스키코드를 이용하여 문제를 풀면 쉽게 해결가능할거라 판단하여 코드를 작성하였다.
숫자를 대, 소문자로 정확히 구분하는법은 검색을통해 코드에 입력하였다.</p>
<h2 id="기술면접">기술면접</h2>
<blockquote>
<ol start="9">
<li>배열과 List, ArrayList, Dictionary 의 차이점을 설명해주세요.<ol>
<li>(꼬리질문) Dictionary는 어떻게 구현해야 하나요? </li>
<li>(꼬리질문) Dictionary 검색이 빠른 이유는 무엇인가요?</li>
</ol>
</li>
</ol>
</blockquote>
<p>배열은 생성시 크기할당이 필요하고 인덱스를 통해 접근이 가능합니다.
리스트는 크기할당이 필요없고 인덱스없이 접근이 가능합니다. 또한 앞의 요소가 삭제되면 새로추가되는 요소가 그 공간에 저장가능합니다.
ArrayList는 인덱스로 식별자를 쓰는것이 가능하고 크기를 동적으로 사용할수 있습니다.
Dictionary는 해시테이블을 기반으로 Key-Value Pair형태로 데이터를 저장합니다.
Dictionary의 구현은 키와 값의 쌍으로 이루어진 자료구조 해시함수를 이용해야하며 검색이 빠른 이유는 어떠한 임의의 값에 대하여 고정된 크기의 고유한 값으로 매핑된 해시값을 이용해 찾기때문입니다.</p>
<h2 id="최종-프로젝트">최종 프로젝트</h2>
<p>주말동안 캐릭터 점프버퍼와 일정값이내로 머리가 천장에 부딪히면 부드럽게 밀려나면서 점프가 지속되도록하는 코드를 제작하였다.
먼저 점프버퍼이다.</p>
<pre><code>[SerializeField] private float _jumpBufferTime = 0.2f;
    private float _jumpBufferCount;
    //점프타임
    private float _jumpingTime;
    //플레이어 점프 체크
    private bool _isJumping;</code></pre><p>점프버튼을 누르고 0.2초 이내로 땅에 닿는다면 점프버튼이 입력된값을 기억하고있다 점프를 할수 있게 하는것이 점프버퍼이다.
먼저 0.2의 값을 가지고있는 _jumpBufferTime과 점프버튼을 누른순간 값이들어가 Time.deltaTime으로 값이 떨어지는 _jumpBufferCount를 선언해주었다.
그리고 점프시간의 최대시간을 체크해주기위해 _jumpingTime을 선언해주어 너무 오래 점프를 할수없게 만들었다.
마지막으로 플레이어의 점프상태를 체크하는 _isJumping을 선언해주면 준비는 끝난다.</p>
<pre><code>//점프를 눌렀을 때
        if (_isJumping)
        {
            _jumpBufferCount = _jumpBufferTime;
        }
        else
        {
            _jumpBufferCount -= Time.deltaTime;
        }

        //점프
        if (_coyoteTimeCount &gt; 0f &amp;&amp; _jumpBufferCount &gt; 0f &amp;&amp; _jumpingTime &gt; 0f)
        {
            _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _jumpingPower);
            _jumpBufferCount = 0f;
        }

        public void JumpStarted(InputAction.CallbackContext context)
    {
        _jumpingTime = 0.05f;
        _isJumping = true;
    }

    public void JumpCanceled(InputAction.CallbackContext context)
    {
        if (_rigidbd.velocity.y &gt;= 0f)
        {
            _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _rigidbd.velocity.y * 0.6f);
            _coyoteTimeCount = 0f;
        }
        _isJumping = false;
    }</code></pre><p>점프버튼을 누르면 _isJumping이 true로 바뀌며 _jumpingTime에 0.05f값이 들어간다. 점프코드에선 3가지 조건이 전부 충족되면 점프가 실행된다. 만약 플레이어가 땅에닿기 0.2초전에 점프버튼을 누르게되면 코요테타임을제외한 2값이 0보다커지게되고 땅에닿는순간 코요테타임도 0.2값을 가지게되어 3가지조건이 전부충족되기때문에 Update문이 돌아가 점프를 하게된다.</p>
<p>다음으로 머리충돌체크이다.</p>
<pre><code>//오른쪽 머리 충돌체크
    private bool IsRightHead()
    {
        //레이 발사 / 정상 작동
        for (int i = -4; i &lt; 5; i++)
        {
            if(Physics2D.Raycast(transform.position + (Vector3.right * 0.125f * i), Vector2.up, 1.5f, _floorLayer))
            {
                if(i == 4)
                {
                    transform.position = new Vector3(transform.position.x - 0.127f, transform.position.y);
                }
                return true;
            }
        }
        return false;
    }

    //왼쪽 머리 충돌체크
    private bool IsLeftHead()
    {
        for (int j = -4; j &lt; 5; j++)
        {
            if (Physics2D.Raycast(transform.position + (Vector3.right * -0.125f * j), Vector2.up, 1.5f, _floorLayer))
            {
                if (j == 4)
                {
                    transform.position = new Vector3(transform.position.x + 0.127f, transform.position.y);
                }
                return true;
            }
        }
        return false;
    }</code></pre><p>캐릭터의 중앙기준 0.125씩 레이를쏴서 총9개의 레이를 쏜다. 만약 좌,우 맨 마지막 레이만 _floorLayer에 닿게되면 플레이어의 위치가 0.127f만큼 밀려나면서 점프력은 유지되어 머리가 레이어에 부딪치지않고 점프를 유지하게된다. 
이 코드에서 버그가 있었는데 레이캐스트가 _floorLayer에 부딪혀 플레이어가 이동하기전에 점프속도가빨라 이동하기전 머리가 부딪힌판정이 나는것이었다. 이것은 레이의 길이를 1.1에서 1.5로 늘리는방식으로 해결하였다.
그리고 레이를 2개쏘는것은 한개를 쏘게되면 4 또는 -4에서 제일먼저 부딪힌 판정이나 플레이어가 무조건 밀리는 현상이 발생하여 좌 우 두개의 레이어에 다른조건을 주는방식으로 해결하였다.</p>
<p>이것으로 플레이어의 이동, 점프, 점프버퍼, 코요테타임, 일정값이내로 머리를 부딪혔을때 부드럽게 점프가 계속되도록하는 기능을 구현완료하였다. 오늘부터는 에어 캐릭터로직작업에 들어갔다.</p>
<p>먼저 캐릭터의 무기가 마우스의 위치를 바라보면서 회전하도록 제작아였다.</p>
<pre><code>//에어 무기 회전
    [SerializeField] private SpriteRenderer _armRenderer;
    //총구위치
    [SerializeField] private Transform _armPivot;
    [SerializeField] private SpriteRenderer _characterRenderer;
    [SerializeField] private SpriteRenderer _weaponSprite;

    //마우스가 움직인 값
    private Vector2 _mouseDelta;
    private Camera _camera;

    private void Awake()
    {
        _camera = Camera.main;
    }

    private void FixedUpdate()
    {
        RotateArm();
    }

    public void Look(InputAction.CallbackContext context)
    {
        _mouseDelta = context.ReadValue&lt;Vector2&gt;();
    }

    //에어 무기회전 및 방향전환
    private void RotateArm()
    {
        Vector2 worldPos = _camera.ScreenToWorldPoint(_mouseDelta);

        Vector2 newAim = worldPos - (Vector2)_armPivot.position;

        float rotZ = Mathf.Atan2(newAim.y, newAim.x) * Mathf.Rad2Deg;


        _armRenderer.flipY = Mathf.Abs(rotZ) &gt; 90f;
        _characterRenderer.flipX = _armRenderer.flipY;
        _weaponSprite.flipX = _armRenderer.flipY;

        _armPivot.rotation = Quaternion.AngleAxis(rotZ, Vector3.forward);
    }</code></pre><p>스파르타코딩클럽 입문강의에서 사용했던 탑다운코드를 인용하여 코드를 제작하였다. 입문강의에서 사용했던코드와 우리팀이 제작하는 코드에서 사용하는 코드가 달라 적용하는데 상당히 애를 먹었었다. 모르는 부분은 같은조원에게 물어보고 같이 고민하면서 해결해 현재 정상적으로 작동을하는모습을 보니 마음에 든다.</p>
<p>이제 에어의 캐릭터로직에 대해 고민을 해야한다.
먼저 클릭을 지속하는동안 overlapCircleAll메서드를 통해 총구를 기준으로 일정범위내 원형범위내에 존재하는 모든 오브젝트의 위치를 알아내고 마우스위치를 기준으로 일정각도이내에 존재하는 오브젝트중 제일 가까운 오브젝트를 끌어당기는 코드를 작성하면된다. 빨아들인 오브젝트는 라인렌더러를 사용해 날아가는모션이 보이도록 제작을해야한다.
일단 제일먼저 overlapCircleAll을 했을때 거리체크를 한다음 가까운거리에 저장, 계속검사를하면서 제일 가까운 오브젝트를 찾아내 가져온다.</p>
<p>말로 적으니 좀 정신없는거같다..
일단 마우스클릭을 하고있는동안 Debug.Log가 작동하도록 코드를 제작한상태이다. 내일은 가장가까운 오브젝트가 총구위치로 이동하는코드를 제작할예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 8일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-8%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-8%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Fri, 15 Mar 2024 12:00:55 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<p>오늘의 알고리즘문제이다.</p>
<blockquote>
<ol start="44">
<li>최소 직사각형</li>
</ol>
</blockquote>
<pre><code>using System;

public class Solution {
    public int solution(int[,] sizes) {
        int answer = 0;
        int max1 = 0;
        int max2 = 0;

        for(int i = 0; i &lt; sizes.GetLength(0); i++){
            max1 = Math.Max(max1, Math.Max(sizes[i, 0], sizes[i, 1]));
            max2 = Math.Max(max2, Math.Min(sizes[i, 0], sizes[i, 1]));
        }
        answer = max1 * max2;

        return answer;
    }
}</code></pre><p>풀이 : 먼저 가로길이와 세로길이중 최대값을 저장할 max1,2를 선언한다. 그리고 배열 sizes를 돌면서 가로, 세로 길이를 비교하고 최대값을 찾아서 저장한다. 반복문을 끝까지 돌게되면 max1은 가로길이중 가장 큰 값이 되고, max2는 세로길이중 가장 큰 값이 된다. 마지막으로 두값을 곱해 가장작은 지갑크기를 계산하고 이를 answer에 저장한다.</p>
<h2 id="기술면접">기술면접</h2>
<blockquote>
<ol start="8">
<li>박싱과 언박싱에 대하여 설명해주세요.
(꼬리질문) 박싱, 언박싱을 사용할 때 주의해야 할 점이 있다면 무엇이 있나요?</li>
</ol>
</blockquote>
<p>  박싱은 값 형식 데이터를 참조 형식으로 변환하는것이고
  언박싱은 반대로 참조형식 데이터를 값 형식으로 변환하는것이다.
  이때 주의해야할 점은
  참조형식을 값형식으로 바꾸는 것이 무조건 언박싱은 아니라는 것이다. 언박싱은 박싱된 데이터를 다시 값형식으로 돌려놓는 것이기때문에 박싱이 있어야 언박싱이 가능하다.</p>
<h2 id="최종-프로젝트">최종 프로젝트</h2>
<p>오늘은 플레이어의 점프부분을 고쳤다.
원래코드는</p>
<pre><code>Physics2D.OverlapCircle(_floorCheck.position, 0.7f, _floorLayer);</code></pre><p>를 사용하여 플레이어의 발 아래부분에 원을생성해 그 범위안에 바닥이있으면 점프하게 제작을 했었다. 그러나 천장이 낮아 플레이어가 높게점프하지못하고 바로바닥으로 떨어지면 낮은확률로 2단점프가되는 상황이 발생하여 Raycast를 사용하는것으로 변경하였다.
유니티강의에서 사용했던 Physics를 사용하여 제작을 하였는데 강의는 3D였고 내가제작하는것은 2D였다는것을 깜빡한나머지 Physics2D로 변환하지않아 Raycast가 제대로 동작하지않았었다...(이것을 너무늦게발견해버렸다.)
그래서 기존에 작성했던코드를 전부 갈아엎고 새롭게 코드를 작성하였다.</p>
<pre><code>public void JumpStarted(InputAction.CallbackContext context)
    {
        if (_coyoteTimeCount &gt; 0f)
        {
            _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _jumpingPower);
        }
    }

    public void JumpCanceled(InputAction.CallbackContext context)
    {
        if (_rigidbd.velocity.y &gt; 0f)
        {
            _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _rigidbd.velocity.y * 0.6f);

            _coyoteTimeCount = 0f;
        }
    }

    //점프체크
    private bool IsFloor()
    {
        //Ray발사
        for (int i = -1; i &lt; 2; i++)
        {
            if (Physics2D.Raycast(transform.position + (Vector3.right * 0.5f * i), Vector2.down, 0.1f, _floorLayer))
            {
                return true;
            }
        }
        return false;
    }</code></pre><p>이제 남은부분은 점프버퍼와 머리가 천장에 부딪혔을때 일정부분 이내라면 부드럽게 밀려올라가도록 제작을 하는것이다.
먼저 머리가 천장에 부딪혔는지 확인하는코드를 작성해두었다.</p>
<pre><code>//머리 충돌처리 정상작동
    //이제 부드럽게 밀려나서 점프되도록 제작
    private bool IsHead()
    {
        //레이 발사
        for(int i = -2; i &lt; 3; i++)
        {
            if(Physics2D.Raycast(transform.position + (Vector3.right * 0.25f * i), Vector2.up, 1.1f, _floorLayer))
            {
                Debug.Log(&quot;Head Hit!!&quot;);
                return true;
            }
        }
        return false;
    }</code></pre><p>주말동안 제작하고 확인해봐야하는것들이 남아있어서 주말에 틈틈히작업을할것같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 7일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-7%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-7%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Thu, 14 Mar 2024 13:02:12 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<p>오늘의 문제는 43번 크기가 작은 부분문자열을 풀었다.</p>
<pre><code>using System;

public class Solution {
    public int solution(string t, string p) {
        int answer = 0;
        long num = 0;
        for(int i = 0; i &lt; t.Length - p.Length + 1; i++)
        {
            num = long.Parse(t.Substring(i, p.Length));
            if(num &lt;= long.Parse(p)) { answer++; }
        }
        return answer;
    }
}</code></pre><p>오버플로우가 걸릴수있으니 int가 아닌 long으로 num을 선언해주고 for문을 돌렸다. 실행범위는 t의 길이에서 p의 길이를뺀 숫자 +1만큼이다. 반복문 안에서 t에 Substring()을 사용하여 i부터 p의 길이까지 자르고 long타입으로 변환 시킨다음 num에 넣어준 다음 num이 long타입으로 변환시킨 p보다 작거나 같다면 answer을 더해준다.</p>
<h2 id="기술면접">기술면접</h2>
<p>오늘은 6번 7번 문제에 대해 답변하겠다</p>
<blockquote>
<p>6.가비지 컬렉터를 회피하기 위한 전략은 무엇이 있나요?</p>
</blockquote>
<p>가비지 컬렉터는 힙메모리 영역을 관리하기때문에 힙메모리를 사용하는 참조타입의 인스턴스 사용을 줄이는 것이 가비지 컬렉터를 회피하는 전략입니다.
예를들면 값타입 인스턴스를 사용할수있습니다. 기본적으로 스택 메모리 영역을 사용하기때문에 가비지 컬렉터를 회피할수 잇습니다.</p>
<blockquote>
<ol start="7">
<li>가비지 컬렉션이란 무엇인지 설명해주세요.</li>
</ol>
</blockquote>
<p>가비지 컬렉션은 프로그램이 사용하지 않는 메모리를 자동으로 해제하는 프로세스입니다. 이를 통해 메모리 누수를 방지하고 시스템의 안정성을 유지합니다.</p>
<h2 id="최종프로젝트-진행">최종프로젝트 진행</h2>
<p>Player의 움직임을 InputAction을 사용해 구독하는 형식으로 프로젝트를 진행하고있다.
먼저 플레이어의 InputAction을 받아올 PlayerInput.cs를 생성한다음</p>
<pre><code>public class PlayerInput : MonoBehaviour
{
    public PlayerInputAction playerInputAction { get; private set; }
    public PlayerInputAction.PlayerActions playerActions { get; private set; }

    private void Awake()
    {
        playerInputAction = new PlayerInputAction();
        playerActions = playerInputAction.Player;
    }

    private void OnEnable()
    {
        playerInputAction.Enable();   
    }
    private void OnDisable()
    {
        playerInputAction.Disable();
    }
}</code></pre><p>로 작성하였다.</p>
<p>다음 Player.cs 스크립트에서 동작을 구독하고 실행시켰다.</p>
<pre><code>    [SerializeField] private Rigidbody2D _rigidbd;
       [SerializeField] private Transform _floorCheck;
    [SerializeField] private LayerMask _floorLayer;
    public PlayerInput playerInput { get; private set; }

    private float _horizontal;
    private float _speed = 4f;
    private float _jumpingPower = 20f;</code></pre><p>플레이어의 이동 및 점프를 구현하기위해 사용한 변수들이다.
public PlayerInput playerInput { get; private set; }을 통해 앞서 만들었던 PlayerInput.cs를 선언하였다.</p>
<p>다음은 Start()이다.</p>
<pre><code>private void Start()
    {
        playerInput = GetComponent&lt;PlayerInput&gt;();

        playerInput.playerActions.Move.started += Move;
        playerInput.playerActions.Jump.started += JumpStarted;
        playerInput.playerActions.Jump.canceled += JumpCanceled;
        playerInput.playerActions.Look.started += Look;
        playerInput.playerActions.Action.started += PlayerAction;
    }</code></pre><p>구독을 한다음 playerInput.playerActions.Move.started +=를 사용하여 플레이어의 InputAction을 선언해주었다.</p>
<p>플레이어의 움직임 부분이다.</p>
<pre><code>private void FixedUpdate()
    {
        _rigidbd.velocity = new Vector2(_horizontal * _speed, _rigidbd.velocity.y);
    }
    public void Move(InputAction.CallbackContext context)
    {
        _horizontal = context.ReadValue&lt;Vector2&gt;().x;
    }</code></pre><p>플랫포머 게임이기때문에 A,D를 이용하여 좌우움직임만 구현했다. 따라서 x좌표만 움직이면 되고 FixedUpdate를 통해 실시간움직임을 구현했다.</p>
<p>플레이어의 점프부분이다.</p>
<pre><code>public void JumpStarted(InputAction.CallbackContext context)
    {
        if (context.started &amp;&amp; _coyoteTimeCount &gt; 0f)
        {
            _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _jumpingPower);
        }
    }
    public void JumpCanceled(InputAction.CallbackContext context)
    {
        if (context.canceled &amp;&amp; _rigidbd.velocity.y &gt; 0f)
        {
            _rigidbd.velocity = new Vector2(_rigidbd.velocity.x, _rigidbd.velocity.y * 0.6f);

            _coyoteTimeCount = 0f;
        }
    }
    private bool IsFloor()
    {
        // OverlapCircle &lt;- 매개변수로 전달할 위치를 기준으로 반지름만큼 원 생성
        //그 영역 내에 충돌체를 가진 게임오브젝트가 있는지 검사
        return Physics2D.OverlapCircle(_floorCheck.position, 0.7f, _floorLayer);
    }</code></pre><p>점프버튼을 눌렀을때인 JumpStarted, 뗐을때의 JumpCanceled를 이용해 점프를 구현하였다. 중간에있는 _coyoteTimeCount는 바로아래에 설명하겠다.
플레이어는 땅에 닿아있어야만 점프를 할 수 있기 때문에 bool값인 IsFloor를 통해 체크를 하게된다. 이때 플레이어의 아래쪽에 땅인지 체크하기위한 GroundCheck를 생성해두어야 한다.</p>
<p>오늘작업중 제일 맘에 들었던 코요테시간이다.
코요테 시간은 기본적으로 플랫폼을 떠난 직후 점프하는 경우에도 지상에 있지않는거로 처리되기 때문에점프가 등록되지않는다.
따라서 플레이어가 플랫폼을 떠난후 몇프레임동안 플랫폼에 있었고 그시간동안 점프할수 있도록 허용해야한다.</p>
<pre><code>//코요테시간
    [SerializeField] private float _coyoteTime = 0.2f;
    private float _coyoteTimeCount;

    //중략
    private void Update()
    {
        if (IsFloor())
        {
            _coyoteTimeCount = _coyoteTime;
        }
        else
        {
            _coyoteTimeCount -= Time.deltaTime;
        }
    }</code></pre><p>오늘의 작업은 이렇게 끝이나게되었다. 점프버퍼도 구현하려했으나 현재 작업되어있는 부분에서 Raycast를 사용하여 검사를 진행하도록 수정해야하는 부분이 있기때문에 먼저 바닥 및 머리충돌검사를 위한 Raycast작업을 진행한 다음 점프버퍼까지 작업을 진행할 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 프로젝트 6일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-6%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-6%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Wed, 13 Mar 2024 12:45:04 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<p>오늘은 40~42번까지 풀었다. 2일간 제출을 못했어서 오늘 한번에 제출을 했었다.</p>
<blockquote>
<p>3진법 뒤집기</p>
</blockquote>
<p>이문제는 내가 이해를 잘 못하겠어서 검색을 통해 공부를 하고 풀이를 제출하였다.</p>
<pre><code>using System;

public class Solution {
    public int solution(int n) {
        int answer = 0;
        while(n &gt; 0){
            answer *= 3;
            answer += n % 3;
             n /=3;
        }
        return answer;
    }
}</code></pre><p>whlie문으로 n이 0보다 크면 반복문을 계속 실행시켜준다. 내부에서는 answer에 3을곱하고 answer에 n을 3으로 나눈 나머지를 넣어준 다음 n을 3으로 나눠주는 동작을 하게된다.</p>
<blockquote>
<p>41 이상한 문자 만들기</p>
</blockquote>
<p>이문제는 대, 소문자를 만드는 방법만 알면 쉽게 풀이가 가능한 문제였다.</p>
<pre><code>public class Solution {
    public string solution(string s) {
        string answer = &quot;&quot;;
        int num = 0;

        for(int i = 0; i &lt; s.Length; i++){
            if(s[i] == &#39; &#39;){
                answer += s[i];
                num = 0;
                continue;
            }
            if(num % 2 == 0){
                //대문자로 변경
                answer += s[i].ToString().ToUpper();
                num ++;
            }
            else{
                //소문자로 변경
                answer += s[i].ToString().ToLower();
                num++;
            }
        }

        return answer;
    }
}</code></pre><p>먼저 공백을 기준으로 num이 초기화 되어야 하기 때문에 s[i]==&#39; &#39;이면 0으로 초기화를 시켜준다. 그 다음 num을 2로 나눈값이 0이면 대문자로 변경하는 ToString().ToUpper()를 사용하고 0이 아닐경우 ToString().ToLower()를 사용해 소문자로 변경해 answer에 추가시켜주면 해결된다.</p>
<blockquote>
<p>42 삼총사</p>
</blockquote>
<p>이문제는 3중반복문을 통해 해결하였다.</p>
<pre><code>using System;

public class Solution {
    public int solution(int[] number) {
        int answer = 0;
        for(int i = 0; i &lt; number.Length; i++)
        {
            for(int j = i+1; j &lt; number.Length; j++)
            {
                for(int k = j+1; k &lt; number.Length; k++)
                {
                    if(number[i] + number[j] + number[k] == 0)
                    {
                        answer++;
                    }
                }
            }
        }
        return answer;
    }
}</code></pre><p>같은 숫자로 계산을 하면 안되기때문에 1번 2번 3번 원소를 각각 앞의 숫자보다 1큰 숫자로 설정하여 계속 반복문을 돌려 해당되는 조합이 있다면 answer++를 해주는 방법으로 해결하였다.</p>
<h2 id="최종프로젝트">최종프로젝트</h2>
<p>여러가지 이슈들이 전부 해결되어 일주일만에 제대로 작업을 시작하게되었다. inputsystem을 사용하여 플레이어의 이동과 점프를 구현하기위해 스파르타 강의를 먼저 보고 따라해봤는데 원하는 내용과 일치하는 내용이 없고 참고하여 제작하려고 해봤으나 제대로 되지않아 이과정을 포기하였다.
다음으로 여러가지 velog또는 유튜브를 참고하여 제작을 하기위해 노력하였다. 여러가지 방법을 시도하던중 현재 이동과 점프가 구현되긴하였다. 그러나 만족스럽게 움직이지않아 추가적인 작업을 지속할 예정이다. 먼저 플레이어가 낙하상태가 되었을때 중력을추가해 빠르게 떨어지게하고싶고 점프버퍼와 코요테시간을 추가해 만족스러운 경험이 될수 있도록 노력해볼예정이다.
적어도 이번주 주말까지 제작을 완료하고 다음주부터는 캐릭터 로직에 들어가야하니 최대한 빠르게 작업을 진행할예정이다.</p>
<h2 id="기술면접">기술면접</h2>
<p>오늘의 기술면접질문은 </p>
<blockquote>
<p> 가비지 컬렉터에 대해 설명해주세요</p>
</blockquote>
<p>이다.
가비지 컬렉터는 메모리 관리를 담당하는 시스템 또는 프로그램의 구성 요소이며, 메모리에서 더 이상 사용되지 않는 객체를 찾아 제거하여 메모리를 회수하는 역할을 수행한다.</p>
<p>그리고 어제 예비군때문에 하지못했던 기술면접을 진행했었다.</p>
<blockquote>
<p>ref&#39;와 &#39;out&#39;의 사용 시 차이는 무엇인가요?</p>
</blockquote>
<p>답 :ref는 사용전 선언 및 초기화를 해줘야하지만 out은 메서드내부에서만 초기화를 진행한다면 사용하기전에 초기화를 하지않아도 사용가능하다.
여기에 추가로 어디에서 활용가능한지 추가로 설명하면 좋다는 피드백을 받았다.
추가 : ref는 기존변수를 메서드에서 수정하려할때 사용하는 경우가 많고
out은 메서드 내에서 생성되는 값을 반환 할 때 사용하는 경우가 많다.</p>
<blockquote>
<p>struct와 class를 비교해서 설명해주세요</p>
</blockquote>
<p>이 질문은 아예 다르게 찾아보고 답변해 다시 공부하고 정리해야 한다.
답 : Struct는 값 타입이고 Class는 참조 타입이다. 
Struct는 값 그 자체를 가지고 있으며, 변수에 값이 할당될 때 복사되어 메모리에서 스택에 저장됩니다.
Class는 객체의 참조가 변수에 할당되며, 변수가 실제 객체가 저장된 메모리 주소를 가리키는 방식으로 메모리에서는 힙(Heap)에 저장됩니다.
그렇기에 Struct는 복사된 각 값이 서로 독립적이어서 변경되어도 다른 변수에 영향을 주지 않지만, Class는 같은 객체를 참조하는 여러 변수가 있을 시 하나를 변경하면 다른 변수도 변경됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 5일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-5%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-5%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Tue, 12 Mar 2024 11:15:41 GMT</pubDate>
            <description><![CDATA[<p>어제는 사랑니발치, 오늘은 예비군 훈련으로 인해 2일간 전혀 작업과 공부를 진행하지 못했었다. 오늘은 예비군 훈련이 끝난 다음 잠깐동안 기술면접을 준비한 과정을 적으려한다.</p>
<h2 id="기술면접">기술면접</h2>
<p>오늘의 기술면접문제는 &#39;struct와 class를 비교해서 설명해주세요.&#39; 였다.
struct는 기본적으로 public으로 정의되기때문에 변수 및 함수가 외부에서 쉽게 액세스될수있다.
class는 기본적으로 private로 정의되기때문에 변수 및 함수에 대한 액세스를 제한한다. 대신 상속, 다형성 및 캡슐화와 같은 객체지향 개념을 더 잘 지원한다.</p>
<p>저번주 목요일부터 오늘까지 사랑니와 예비군이 연달아닥치면서 작업이 매우 미미하게 진행되었는데 내일부턴 최대한빠르게 작업을 진행해 다른조원들의 속도에 맞출예정이다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트3일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Fri, 08 Mar 2024 12:59:35 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<p>오늘의 문제는 39번 최대공약수와 최소공배수 였다.</p>
<pre><code>﻿using System;
public class Solution
{
    public int[] solution(int n, int m)
    {
        int[] answer = new int[2];
        int min;
        int max;

        min = gcd(n, m);
        max = (n * m) / min;

        answer[0] = min;
        answer[1] = max;
        return answer;
    }

    public int gcd(int n, int m)
    {
        if (m == 0) return n;
        else return gcd(m, n % m);
    }
}</code></pre><h2 id="최종프로젝트">최종프로젝트</h2>
<p>어제부터 사랑니통증이 심해 많은작업을 진행하지못했다.....
주말동안 상태가 좋아지면 작업을 할 예정이지만 상태가 별로라면 월요일에 발치를 한 다음 빡세게 작업을 할 예정이다
(예비군 다녀와서도 작업을 해야될것같다....)</p>
<h2 id="기술면접">기술면접</h2>
<p>오늘의 문제는 &#39;접근제한자란 무엇이며, 각각 어떤 차이가 있는지 비교해서 설명해주세요.&#39; 이다.
접근제한자란 객체지향 프로그래밍에서 클래스 내부의 변수나 메서드, 생성자에 대한 접근권한을 지정해주는것이다.
종류로는 public, private, protected, default 가 있으며
public은 외브클래스에서도 접근 및 사용이 가능, private는 같은 클래스에서만 접근이 가능, protected는 같은 패키지 내부와 상속관계에서만 접근가능, default는 같은 패키지 내부에서만 접근가능하다.</p>
<h2 id="오늘의-한마디">오늘의 한마디</h2>
<p>아프지마요....</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 2일차]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-2%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-2%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Thu, 07 Mar 2024 11:13:38 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<p>오늘의 알고리즘 문제는 38번 직사각형 별찍기 를 풀었다</p>
<pre><code>using System;

public class Example
{
    public static void Main()
    {
        String[] s;

        Console.Clear();
        s = Console.ReadLine().Split(&#39; &#39;);

        int a = Int32.Parse(s[0]);
        int b = Int32.Parse(s[1]);

        for(int i = 0; i &lt; b; i ++){
            for(int j = 0; j &lt; a; j++){
                Console.Write(&quot;*&quot;);
            }
            Console.Write(&quot;\n&quot;);
        }
    }
}</code></pre><p>직사각형모양으로 별을 찍기위해선 가로,세로 두개의 값을 받아야한다.
먼저 입력받은 a, b 두값을 int로 변환시키는 과정을 거친다음 이중반복문을 통해 세로, 가로의 크기만큼 별을 찍어내게 만들었다.</p>
<h2 id="최종프로젝트">최종프로젝트</h2>
<p>어제 거의 대부분의 기획을 끝내놔서 오늘 추가적인 기획을 하려고 브레인스토밍을 진행하였으나 딱히 나오는 내용이 존재하지않아 각자 담당한 부분의공부를 하고 관련자료를 찾아보는 시간을 진행하였다. 나는 캐릭터의 스테이트머신을 제작하기위해 심화과정의 스테이트머신 부분을 복습하고 관련자료영상을 찾아보면서 하루를 보냈다.</p>
<h2 id="기술면접">기술면접</h2>
<p>오늘의 기술면접 문제는 &#39;&#39;ref&#39;와 &#39;out&#39;의 사용 시 차이는 무엇인가요?&#39; 이다.
ref는 변수를 참조형태로 전달하는데 사용되고 변수가 메서드안에서 변경될수 있다.
out또한 변수를 참조형태로 전달하는데 사용된다. 변수를 전달하기전에 변수를 초기화하지 않아도되지만 메서드안에서는 반드시 할당되어야한다.
정리하자면 ref는 사용전 선언 및 초기화를 해줘야하지만 out은 메서드내부에서만 초기화를 진행한다면 사용하기전에 초기화를 하지않아도 사용가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종프로젝트 1일]]></title>
            <link>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%9D%BC</link>
            <guid>https://velog.io/@pht_974/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%9D%BC</guid>
            <pubDate>Wed, 06 Mar 2024 11:50:35 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<p>오늘의 알고리즘 문제는 37번 행렬의 덧셈. 을 풀었다.</p>
<pre><code>public class Solution
{
        public int[,] solution(int[,] arr1, int[,] arr2)
        {
            // 배열의 각 차원에 있는 요소의 수를 구한다
            int length1 = arr1.GetLength(0);
            int length2 = arr1.GetLength(1);

            int[,] answer = new int[length1, length2];

            // 배열의 덧셈 계산
            for (int i = 0; i &lt; length1; ++i)
            {
                for(int j = 0; j &lt; length2; ++j)
                {
                    answer[i,j] = arr1[i,j] + arr2[i,j];
                }
            }

            return answer;
        }
}</code></pre><p>lenght1.2로 각 차원에 있는 요소의 수를 구하였다. 그리고 2차원 배열이기때문에 이중for문을 사용하여 배열의 숫자를 증가시켜가며 덧셈을 진행하는 방식으로 해결하였다.</p>
<h2 id="최종프로젝트-회의">최종프로젝트 회의</h2>
<p>최종프로젝트의 제목은 에어앤후크로 결정하였다.
조원들과 회의를 하면서 다이어그램을 작성하였다.<img src="https://velog.velcdn.com/images/pht_974/post/17a4bc72-3292-4254-b1ab-056af8d4eff5/image.png" alt="">
<img src="https://velog.velcdn.com/images/pht_974/post/9038c79f-7f7d-4a11-87cc-5195b5470cad/image.png" alt=""></p>
<p>나는 최종프로젝트에서 캐릭터를 담당하기로 했는데 총 2개의 캐릭터를 만들고 각각 캐릭터의 로직을 다르게 작성해야하기때문에 관련 자료를 찾아 제작을 이어갈 생각이다. 먼저 갈고리를 사용하는 캐릭터인 후크는 Grappling Hook Rope에 관련된 자료를 찾아보면서 제작하고 산나비관련모작영상이 있어서 그것을 보고 자료를 찾을 예정이다.
다음으로 공기총액션을 사용하는 에어는 커비의 액션이 비슷하다고 판단되어 관련 자료를 찾아보던중 SmoothDamp 메서드를 사용했다는 정보를 찾아냈다. 앞으로 이것에 관해 정보를 찾으면서 제작을 이어갈 예정이다.
일단 캐릭터의 이동과 스테이트머신을 최우선순위로 제작한 다음 로직을 짜는 방식으로 개발할것이다.</p>
<h2 id="기술면접-답변">기술면접 답변</h2>
<p>오늘부터 새로시작하는 기술면접연습하기의 답변을 적어볼것이다.
첫날 기술면접문제는 </p>
<blockquote>
<p>float와 int의 표현 가능한 수의 범위가 다른 이유는 무엇인가요?</p>
</blockquote>
<p>이다. 먼저 내가알고있는점은 소수점까지 표현가능하다 아니다로 구분을 하고있었기때문에 다른이유는 자세히 알지못했다. 또한 double형과 다르게 둘다 4바이트(32비트) 로 크기도 같은걸로 알고있기때문에 다른이유가 더있나? 하는 상태로 검색을 시작하였다.
찾아본결과 두 자료형이 다른 이유는 비트구조가 다르기 때문이었다.
int형은 부호비트 1비트를 제외한 31개의 비트가 수를 표현하기때문에
표현범위는 -2,147,483,648 ~ 2,147,483,647 까지가 된다. (-2^31 ~ 2^31-1)
그러나 float형은 값을 2진수로 표현한 후 부호, 지수, 유효숫자로 나누어 메모리에 저장한다. 이때 부호 1비트, 지수 8비트, 유효자리 23비트로 표현하게된다. 이때 표현가능한값은 3.4E-38 ~ 3.4E+38 ( 3.4 x 10^-38 ~ 3.4 x 10^38 ) 이다. 이방법을 사용했을때 엄청 큰 수를 표현할수있지만 유효자리비트로 표현할수 있는 한계를 넘어가게되면 근사치를 취하게된다는 단점이있다.
따라서 float와 int의 표현 가능한 수의 범위가 다른 이유는 int와 float의 지수비트의 유무차이라고 답변할수 있을것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[심화과정4일차]]></title>
            <link>https://velog.io/@pht_974/%EC%8B%AC%ED%99%94%EA%B3%BC%EC%A0%954%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%8B%AC%ED%99%94%EA%B3%BC%EC%A0%954%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Thu, 29 Feb 2024 12:58:30 GMT</pubDate>
            <description><![CDATA[<h2 id="팀과제">팀과제</h2>
<p>랜덤맵에대해 세세한 조정과 버그찾기등 여러가지를 진행하였다.
주말동안 남은작업을 진행할 예정인데
남은작업은</p>
<ol>
<li>맵 기믹추가</li>
<li>안가본지역 안개생성</li>
<li>움직임 알려주기</li>
<li>엔딩씬
이렇게이다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[심화과정3일차]]></title>
            <link>https://velog.io/@pht_974/%EC%8B%AC%ED%99%94%EA%B3%BC%EC%A0%953%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%8B%AC%ED%99%94%EA%B3%BC%EC%A0%953%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Wed, 28 Feb 2024 11:29:37 GMT</pubDate>
            <description><![CDATA[<h2 id="팀과제">팀과제</h2>
<p>어제 랜덤맵생성과정이 완료되어 세부적인 조절을 진행하였다. 저번 팀과제에서 랜덤으로 맵을 생성하려고 도전하셨던 팀원분의 코드를 공부하며 내가작성한 코드에 적용하려고 했다. 그러나 코드를 보면서 제작을해보니 내가제작한코드와 그분의 코드가 방향성이 다르다는것을 깨달았다. 나의코드는 플레이어가 계단에 도착하고 다음층으로 이동하기를 누르면 새로운맵이 그려지는 형식이지만 그분의 코드는 미리 모든맵이 생성및 로드가 되어있고 문을통해 다음맵으로 넘어가는 형식이었다. 따라서 그대로 제작을 하면 맵이 겹쳐서 나오는 문제가 발생해 결국 맵을 클리어한 숫자를 확인하여 일정숫자때 중간보스 및 최종보스, 엔딩이 나올수 있도록 제작하는 방향으로 바꾸었다.</p>
<p>그리고 오늘 제작을 하다보니 버그가 여러개 발견되어 수정하는 작업을 가졌었다. 먼저 플레이어가 맵을 뚫고 다니는 현상이 있었는데 이것은 플레이어를 작업하신분이 충돌을 체크해제해둔상태였기 때문에 금방 해결되었다. 
다음으론 플레이어가 타일위에서 움직이는것이 아닌 타일이 겹쳐지는 + 십자가의 꼭짓점에서 움직이는 현상이 있었다. 이것은 맵의 정중앙에 플레이어가 스폰되기때문에 일어나는 현상이었다.
그래서 맵전체를 x,y 0.5씩 이동하는 방법으로 정상적으로 작동하게 만들었다.
마지막으론 플레이어가 계단에 부딪히는순간 맵을 새로그리게하였는데 가끔 플레이어가 타일중앙이아닌 약간 이상한위치에서 스폰이되는 문제가 있었다. 이것은 플레이어가 움직이는 도중 맵이 로드되면서 플레이어의 위치좌표와 맵의 중심좌표가 묘하게 뒤틀리는현상일 것이라 추측하였다. 따라서 플레이어가 계단에 부딪히는순간 맵이 로드되는것이아닌 팝업이 출력되고 해당맵을 계속 탐험할지 새로운층으로 이동할지 결정하게 하였다. 플레이어가 선택을위해 고민하는사이 캐릭터는 정상적으로 이동을 마친다음 선택을 기다리게되고 좌표가 뒤틀리는 현상없이 새롭게 맵이 그려지게 해결하였다.</p>
<p>마지막으로 아직 해결되지않은 오류가 있었다. 현재 플레이어가 계단에서 선택을할때 게임을 멈추게하였는데 만약 이상태에서 플레이어의 움직임이 입력된 상태로 해당맵을 계속탐험하게되면 입력된만큼 캐릭터가 움직인상태로 게임이 지속된다. 이것은 내가 플레이어input을 담당한것이 아니기때문에 담당하신 조원분께 공유한 다음 해결을 할 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[심화과정 팀프로젝트 2일차]]></title>
            <link>https://velog.io/@pht_974/%EC%8B%AC%ED%99%94%EA%B3%BC%EC%A0%95-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-2%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@pht_974/%EC%8B%AC%ED%99%94%EA%B3%BC%EC%A0%95-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-2%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Tue, 27 Feb 2024 11:25:08 GMT</pubDate>
            <description><![CDATA[<h2 id="알고리즘">알고리즘</h2>
<p>오늘의 알고리즘은 35번 부족한금액 계산하기 를 풀었다.</p>
<pre><code>using System;

class Solution
{
    public long solution(int price, int money, int count)
    {
        long sum = 0;    
        long answer = 0;

        for(int i = 1; i &lt;= count; i ++)
        {
            sum += price * i;
        }

        if(sum &gt;= money)
        {
            answer = sum - money;
        }
        else
        {
            answer = 0;
        }
        return answer;
    }
}</code></pre><p>생각보다 어려운 문제는 아니었다. 입력받은 price, money, count값과 자체적으로 계산할 sum, answer값을 선언한다음 반복문을 통해 price와 count를 곱하고 sum에 더해주었다. 그리고 돈이부족하면 sum과 money를 뺀값을 리턴해주고 부족하지 않다면 0을 리턴해주는 방법으로 코드를 작성하였다. 그런데 제출후 채점하기를하니 몇몇예제에서 실패가 나와 무슨문제인지 몰랐는데 질문하기에서 확인해보니 범위를 벗어난값이 나오는 오버플로우가 발생한다는 답이있었다. 그래서 int를 long으로 변경하니 문제없이 정상적으로 작동을 하였다.</p>
<h2 id="팀과제">팀과제</h2>
<p>어제 참고하면서 제작하던 BSP알고리즘과 블로그의 코드를 계속 보다보니 도저히 기한내에 제작이 불가능하다! 라는 결론이 나왔다. 그래서 노선을 유튜브로 돌려 Tilemap으로 랜덤맵 생성하는 영상이있는지 검색을 하였고 다행히 관련영상이 존재해 영상을보고 제작을 이어갔다.
코드중에서 HashSet이란 함수가 나왔는데 이것은 고유한 요소 집합을 저장하는 컬렉션, 즉 중복값을 허용하지 않는다. 맵을 생성할때 방의 위치가 중복으로 나오면 안되기때문에 이 함수를 사용하여 제작하였다.
처음 값을 넣을때는 UnionWith을 이용해 넣으면되고 해당값을 사용한다음 삭제해야할땐 ExcepWith를 사용해 값을 제거했다.</p>
<p>다행히 참고할영상이있어 랜덤한 맵을 계속생성하는것은 무사히 작성이되었다. 이제 중간보스, 최종보스의 방을 설정하는것과 맵 카운트를 추가하는 작업을 진행할것이다.</p>
]]></description>
        </item>
    </channel>
</rss>