STIKA

Unity 캠프 20일차 TIL < C# 문법 4 / 알고리즘 > 본문

프로그래밍/Unity + C#

Unity 캠프 20일차 TIL < C# 문법 4 / 알고리즘 >

STIKA 2024. 1. 19. 00:56

24.01.19 Fri

 

❤️ TIL

Today I Learned

❤️하루에 1%씩만 나아가도 4개월 동안 쌓이면 꽤 덩치가 커진답니다 :)


📌 오늘의 계획

  • 알고리즘 코드카타
  • C# 4주차 강의 듣기
  • C# 5주차 강의 듣기
  • C# 3주차 과제 풀기

✏️ 작업 내용

✔️ C# 문법 4주차

다중상속의 시작

애초에 우리가 만드는 모든 것들은 코드의 재사용을 위해 만드는 것

 

인터페이스 ( Interface )

특징

  • 클래스가 구현해야 하는 멤버들을 정의해놓은 것
  • 클래스에 대한 제약 조건을 명시하는 것
  • 클래스가 아님
  • 사용할 때 모든 인터페이스 멤버를 구현해야 사용가능
  • 다중 상속을 지원

 

인터페이스는 만들 때 맨앞에 I를 붙여야함

interface IMyInterface
{
    void Method1();
    int Method2(string str);
}

구현안하고 그냥 실행하면 에러남

class MyClass : IMyInterface
{
    public void Method1()
    {
        // 구현
    }

    public int Method2(string str)
    {
        // 구현
        return 0;
    }
}

인터페이스 vs 추상클래스

 

인터페이스

  • 정의 O 구현 X
  • 다중 상속이 가능, 여러 클래스가 동일한 인터페이스를 구현할 수 있다
  • 클래스들 간의 결합도를 낮추고, 유연한 상호작용을 가능하게 한다
  • 모든 동작을 구현해야 한다는 의무를 가지기 때문에 작업량이 증가할 수 있다

추상 클래스

  • 일부 동작의 구현을 가지며, 추상 메서드를 포함할 수 있다
  • 단일 상속만 가능, 상속 계층 구조 형성가능
  • 공통된 동작을 추상화하여 코드의 중복을 방지하고, 확장성을 제공
  • 동작 구현이 가능해서 하위 클래스에서 재정의하지 않아도 될 경우 유용
  • 다중 상속이 불가능하고, 상속을 통해 밀접하게 결합된 클래스들을 형성하므로 유연성이 제한

 

인터페이스 다중상속

// 인터페이스 1
public interface IItemPickable
{
    void PickUp();
}

// 인터페이스 2
public interface IDroppable
{
    void Drop();
}

// 아이템 클래스
public class Item : IItemPickable, IDroppable
{
    public string Name { get; set; }

    public void PickUp()
    {
        Console.WriteLine("아이템 {0}을 주웠습니다.", Name);
    }

    public void Drop()
    {
        Console.WriteLine("아이템 {0}을 버렸습니다.", Name);
    }
}

// 플레이어 클래스
public class Player
{
    public void InteractWithItem(IItemPickable item)
    {
        item.PickUp();
    }

    public void DropItem(IDroppable item)
    {
        item.Drop();
    }
}

// 게임 실행
static void Main()
{
    Player player = new Player();
    Item item = new Item { Name = "Sword" };

    // 아이템 주울 수 있음
    player.InteractWithItem(item);

    // 아이템 버릴 수 있음
    player.DropItem(item);
}

 


 

열거형

switch(enumValue)
{
    case MyEnum.Value1:
        // Value1에 대한 처리
        break;
    case MyEnum.Value2:
        // Value2에 대한 처리
        break;
    case MyEnum.Value3:
        // Value3에 대한 처리
        break;
    default:
        // 기본 처리
        break;
}

 

// 처리하는 함수
static void ProcessMonth(int month)
{
    if (month >= (int)Month.January && month <= (int)Month.December)
    {
        Month selectedMonth = (Month)month;
        Console.WriteLine("선택한 월은 {0}입니다.", selectedMonth);
        // 월에 따른 처리 로직 추가
    }

 

게임사용사례

// 게임 상태
enum GameState
{
    MainMenu,
    Playing,
    Paused,
    GameOver
}

// 방향
enum Direction
{
    Up,
    Down,
    Left,
    Right
}

// 아이템 등급
enum ItemRarity
{
    Common,
    Uncommon,
    Rare,
    Epic
}

 


 

예외처리

try
{
    // 예외가 발생할 수 있는 코드
}
catch (ExceptionType1 ex)
{
    // ExceptionType1에 해당하는 예외 처리
}
catch (ExceptionType2 ex)
{
    // ExceptionType2에 해당하는 예외 처리
}
finally
{
    // 예외 발생 여부와 상관없이 항상 실행되는 코드
}

예시

// 플레이어 이동
try
{
    // 플레이어 이동 코드
    if (IsPlayerCollidingWithWall())
    {
        throw new CollisionException("플레이어가 벽에 충돌했습니다!");
    }
}
catch (CollisionException ex)
{
    // 충돌 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}


// 리소스 로딩
try
{
    // 리소스 로딩 코드
    LoadResource("image.png");
}
catch (ResourceNotFoundException ex)
{
    // 리소스가 없는 경우 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}
catch (ResourceLoadException ex)
{
    // 리소스 로딩 중 오류가 발생한 경우 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}


// 게임 상태 전이
try
{
    // 상태 전이 코드
    if (currentGameState != GameState.Playing)
    {
        throw new InvalidStateException("게임이 실행 중이 아닙니다!");
    }
    // 게임 상태 전이 실행
}
catch (InvalidStateException ex)
{
    // 상태 예외 처리
    Debug.Log(ex.Message);
    // 예외에 대한 추가 처리
}

값형 참조형

값형 = struct

class MyClass
{
    public int Value;
}

MyClass obj1 = new MyClass();
obj1.Value = 10;

MyClass obj2 = obj1; // obj2는 obj1과 동일한 객체를 참조

obj2.Value = 20;

Console.WriteLine(obj1.Value); // 출력 결과: 20​

new키워드의 차이?


 

박싱 언박싱

→ 값형과 참조형 사이의 변환을 의미

1) 박싱(Boxing)

  • 박싱은 값형을 참조형으로 변환하는 과정을 말합니다.
  • 값형 변수의 값을 메모리의 힙 영역에 할당된 객체로 래핑합니다.
  • 박싱을 통해 값형이 참조형의 특징을 갖게 되며, 참조형 변수로 다뤄질 수 있습니다.
  • 박싱된 값형은 참조로 전달되므로 메모리 오버헤드가 발생할 수 있습니다.

 

2) 언박싱(Unboxing)

  • 언박싱은 박싱된 객체를 다시 값형으로 변환하는 과정을 말합니다.
  • 박싱된 객체에서 값을 추출하여 값형 변수에 할당합니다.
  • 언박싱은 명시적으로 타입 캐스팅을 해야 하며, 런타임에서 타입 검사가 이루어집니다.
  • 잘못된 형식으로 언박싱하면 런타임 에러가 발생할 수 있습니다.

 

3) 박싱과 언박싱의 주요 특징

  • 박싱과 언박싱은 값형과 참조형 사이의 변환 작업이므로 성능에 영향을 미칠 수 있습니다. 반복적인 박싱과 언박싱은 성능 저하를 초래할 수 있으므로 주의해야 합니다.
  • 박싱된 객체는 힙 영역에 할당되므로 가비지 컬렉션의 대상이 될 수 있습니다. 따라서 메모리 관리에 유의해야 합니다.
  • 박싱된 객체와 원래의 값형은 서로 독립적이므로 값을 수정하더라도 상호간에 영향을 주지 않습니다.

 

4) 사용예제

  • object는 .NET Common Type System (CTS)의 일부이며, 모든 클래스의 직간접적인 상위 클래스입니다. 모든 클래스는 object에서 상속되며, object는 모든 형식을 참조할 수 있는 포괄적인 타입입니다.
using System;

class Program
{
    static void Main()
    {
        // 값형
        int x = 10;
        int y = x;
        y = 20;
        Console.WriteLine("x: " + x); // 출력 결과: 10
        Console.WriteLine("y: " + y); // 출력 결과: 20

        // 참조형
        int[] arr1 = new int[] { 1, 2, 3 };
        int[] arr2 = arr1;
        arr2[0] = 4;
        Console.WriteLine("arr1[0]: " + arr1[0]); // 출력 결과: 4
        Console.WriteLine("arr2[0]: " + arr2[0]); // 출력 결과: 4

        // 박싱과 언박싱
        int num1 = 10;
        object obj = num1; // 박싱
        int num2 = (int)obj; // 언박싱
        Console.WriteLine("num1: " + num1); // 출력 결과: 10
        Console.WriteLine("num2: " + num2); // 출력 결과: 10
    }
}

리스트 활용 예제

List<object> myList = new List<object>();

// 박싱: 값 형식을 참조 형식으로 변환하여 리스트에 추가
int intValue = 10;
myList.Add(intValue); // int를 object로 박싱하여 추가

float floatValue = 3.14f;
myList.Add(floatValue); // float를 object로 박싱하여 추가

// 언박싱: 참조 형식을 값 형식으로 변환하여 사용
int value1 = (int)myList[0]; // object를 int로 언박싱
float value2 = (float)myList[1]; // object를 float로 언박싱

 

델리게이트

  • 델리게이트(delegate)는 메서드를 참조하는 타입입니다.
  • 다른 프로그래밍 언어에서는 함수 포인터라는 용어를 사용하기도 합니다.
  • 델리게이트를 이용하면 메서드를 매개변수로 전달하거나 변수에 할당할 수 있습니다.
delegate void MyDelegate(string message);

static void Method1(string message)
{
    Console.WriteLine("Method1: " + message);
}

static void Method2(string message)
{
    Console.WriteLine("Method2: " + message);
}

class Program
{
    static void Main()
    {
        // 델리게이트 인스턴스 생성 및 메서드 등록
        MyDelegate myDelegate = Method1;
        myDelegate += Method2;

        // 델리게이트 호출
        myDelegate("Hello!");

        Console.ReadKey();
    }
}

하나 이상의 메서드 등록

 

사용 예제

공격 콜백 받기

  • 다음 예제에서는 event 를 붙여서 사용했다
  • event는 할당연산자( = )를 사용할 수 없으며, 클래스 외부에서는 직접 이벤트를 호출할 수 없다.
// 델리게이트 선언
public delegate void EnemyAttackHandler(float damage);

// 적 클래스
public class Enemy
{
    // 공격 이벤트
    public event EnemyAttackHandler OnAttack;

    // 적의 공격 메서드
    public void Attack(float damage)
    {
        // 이벤트 호출
        OnAttack?.Invoke(damage);
				// null 조건부 연산자
				// null 참조가 아닌 경우에만 멤버에 접근하거나 메서드를 호출
    }
}

// 플레이어 클래스
public class Player
{
    // 플레이어가 받은 데미지 처리 메서드
    public void HandleDamage(float damage)
    {
        // 플레이어의 체력 감소 등의 처리 로직
        Console.WriteLine("플레이어가 {0}의 데미지를 입었습니다.", damage);
    }
}

// 게임 실행
static void Main()
{
    // 적 객체 생성
    Enemy enemy = new Enemy();

    // 플레이어 객체 생성
    Player player = new Player();

    // 플레이어의 데미지 처리 메서드를 적의 공격 이벤트에 추가
    enemy.OnAttack += player.HandleDamage;

    // 적의 공격
    enemy.Attack(10.0f);
}

 

 

람다

  • 람다(lambda)는 익명 메서드를 만드는 방법입니다.
  • 람다를 사용하면 메서드의 이름 없이 메서드를 만들 수 있습니다.
  • 람다는 델리게이트를 사용하여 변수에 할당하거나, 메서드의 매개변수로 전달할 수 있습니다.
(parameter_list) => expression

Calculate calc = (x, y) => 
{	
		return x + y;
};

Calculate calc = (x, y) => x + y;

using System;

// 델리게이트 선언
delegate void MyDelegate(string message);

class Program
{
    static void Main()
    {
        // 델리게이트 인스턴스 생성 및 람다식 할당
        MyDelegate myDelegate = (message) =>
        {
            Console.WriteLine("람다식을 통해 전달된 메시지: " + message);
        };

        // 델리게이트 호출
        myDelegate("안녕하세요!");

        Console.ReadKey();
    }
}

 

게임분기의 시작을알리기

// 델리게이트 선언
public delegate void GameEvent();

// 이벤트 매니저 클래스
public class EventManager
{
    // 게임 시작 이벤트
    public event GameEvent OnGameStart;

    // 게임 종료 이벤트
    public event GameEvent OnGameEnd;

    // 게임 실행
    public void RunGame()
    {
        // 게임 시작 이벤트 호출
        OnGameStart?.Invoke();

        // 게임 실행 로직

        // 게임 종료 이벤트 호출
        OnGameEnd?.Invoke();
    }
}

// 게임 메시지 클래스
public class GameMessage
{
    public void ShowMessage(string message)
    {
        Console.WriteLine(message);
    }
}

// 게임 실행
static void Main()
{
    // 이벤트 매니저 객체 생성
    EventManager eventManager = new EventManager();

    // 게임 메시지 객체 생성
    GameMessage gameMessage = new GameMessage();

    // 게임 시작 이벤트에 람다 식으로 메시지 출력 동작 등록
    eventManager.OnGameStart += () => gameMessage.ShowMessage("게임이 시작됩니다.");

    // 게임 종료 이벤트에 람다 식으로 메시지 출력 동작 등록
    eventManager.OnGameEnd += () => gameMessage.ShowMessage("게임이 종료됩니다.");

    // 게임 실행
    eventManager.RunGame();
}

 

Func, Action

  • **Func**과 **Action**은 델리게이트를 대체하는 미리 정의된 제네릭 형식입니다.
  • **Func**는 값을 반환하는 메서드를 나타내는 델리게이트입니다. 마지막 제네릭 형식 매개변수는 반환 타입을 나타냅니다. 예를 들어, **Func<int, string>**는 **int**를 입력으로 받아 **string**을 반환하는 메서드를 나타냅니다.
  • **Action**은 값을 반환하지 않는 메서드를 나타내는 델리게이트입니다. **Action**은 매개변수를 받아들이지만, 반환 타입이 없습니다. 예를 들어, **Action<int, string>**은 **int**와 **string**을 입력으로 받고, 아무런 값을 반환하지 않는 메서드를 나타냅니다.
  • Func 및 **Action**은 제네릭 형식으로 미리 정의되어 있어 매개변수와 반환 타입을 간결하게 표현할 수 있습니다.

func

// Func를 사용하여 두 개의 정수를 더하는 메서드
int Add(int x, int y)
{
    return x + y;
}

// Func를 이용한 메서드 호출
Func<int, int, int> addFunc = Add;
int result = addFunc(3, 5);
Console.WriteLine("결과: " + result);

 

action

// Action을 사용하여 문자열을 출력하는 메서드
void PrintMessage(string message)
{
    Console.WriteLine(message);
}

// Action을 이용한 메서드 호출
Action<string> printAction = PrintMessage;
printAction("Hello, World!");

 

예제

// 게임 캐릭터 클래스
class GameCharacter
{
    private Action<float> healthChangedCallback;

    private float health;

    public float Health
    {
        get { return health; }
        set
        {
            health = value;
            healthChangedCallback?.Invoke(health);
        }
    }

    public void SetHealthChangedCallback(Action<float> callback)
    {
        healthChangedCallback = callback;
    }
}

// 게임 캐릭터 생성 및 상태 변경 감지
GameCharacter character = new GameCharacter();
character.SetHealthChangedCallback(health =>
{
    if (health <= 0)
    {
        Console.WriteLine("캐릭터 사망!");
    }
});

// 캐릭터의 체력 변경
character.Health = 0;

 

 

 

LINQ(Language Integrated Query)

  • .NET 프레임워크에서 제공되는 쿼리 언어 확장
  • 데이터 소스(예: 컬렉션, 데이터베이스, XML 문서 등)에서 데이터를 쿼리하고 조작하는데 사용됩니다.
  • 데이터베이스 쿼리와 유사한 방식으로 데이터를 필터링, 정렬, 그룹화, 조인 등 다양한 작업을 수행할 수 있습니다.
  • LINQ는 객체, 데이터베이스, XML 문서 등 다양한 데이터 소스를 지원합니다.

구조

var result = from 변수 in 데이터소스
             [where 조건식]
             [orderby 정렬식 [, 정렬식...]]
             [select 식];

 

  • var 키워드는 결과 값의 자료형을 자동으로 추론합니다.
  • from 절에서는 데이터 소스를 지정합니다.
  • where 절은 선택적으로 사용하며, 조건식을 지정하여 데이터를 필터링합니다.
  • orderby 절은 선택적으로 사용하며, 정렬 방식을 지정합니다.
  • select 절은 선택적으로 사용하며, 조회할 데이터를 지정합니다.
// 데이터 소스 정의 (컬렉션)
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

// 쿼리 작성 (선언적인 구문)
var evenNumbers = from num in numbers
                  where num % 2 == 0
                  select num;

// 쿼리 실행 및 결과 처리
foreach (var num in evenNumbers)
{
    Console.WriteLine(num);
}

 


✔️ C# 문법 5주차

탐색 알고리즘

 

선형 탐색 ( Linear Search )

  • 선형 탐색은 가장 단순한 탐색 알고리즘입니다. 배열의 각 요소를 하나씩 차례대로 검사하여 원하는 항목을 찾습니다.
  • 시간 복잡도: 최악의 경우 O(n)

 

구현 예제

  • 배열의 처음부터 끝까지 하나씩 비교하여 검색하는 알고리즘
  • 배열이 정렬되어 있지 않을 경우 사용

 

 

int SequentialSearch(int[] arr, int target)
{
    for (int i = 0; i < arr.Length; i++)
    {
        if (arr[i] == target)
        {
            return i;
        }
    }

    return -1;
}

 

이진 탐색 ( Binary Search )

  • 이진 탐색은 정렬된 배열에서 빠르게 원하는 항목을 찾는 방법입니다. 중간 요소와 찾고자 하는 항목을 비교하여 대상이 중간 요소보다 작으면 왼쪽을, 크면 오른쪽을 탐색합니다.
  • 시간 복잡도: 최악의 경우 O(log n)

구현 예제

  • 배열이 정렬되어 있을 경우 사용하는 알고리즘
  • 중앙값과 비교하여 탐색 범위를 반으로 줄이는 방법으로 빠른 검색이 가능
int BinarySearch(int[] arr, int target)
{
    int left = 0;
    int right = arr.Length - 1;

    while (left <= right)
    {
        int mid = (left + right) / 2;

        if (arr[mid] == target)
        {
            return mid;
        }
        else if (arr[mid] < target)
        {
            left = mid + 1;
        }
        else
        {
            right = mid - 1;
        }
    }

    return -1;
}

 

 

그래프

  • 정점(Vertex)과 간선(Edge)으로 이루어진 자료 구조
  • 방향 그래프(Directed Graph)와 무방향 그래프(Undirected Graph)로 나뉨
  • 가중치 그래프(Weighted Graph)는 간선에 가중치가 있음
  • https://visualgo.net/en/dfsbfs

 

탐색방법

 

깊이 우선 탐색 (Depth-First Search, DFS)

  • DFS는 트리나 그래프를 탐색하는 알고리즘 중 하나로, 루트에서 시작하여 가능한 한 깊이 들어가서 노드를 탐색하고, 더 이상 방문할 노드가 없으면 이전 노드로 돌아가는 방식입니다.
  • 시간 복잡도: 최악의 경우 O(V+E) (V는 노드 수, E는 간선 수)

너비 우선 탐색 (Breadth-First Search, BFS)

  • BFS는 트리나 그래프를 탐색하는 알고리즘 중 하나로, 루트에서 시작하여 가까운 노드부터 방문하고, 그 다음 레벨의 노드를 방문하는 방식입니다.
  • 시간 복잡도: 최악의 경우 O(V+E) (V는 노드 수, E는 간선 수)

 

활용 예제

using System;
using System.Collections.Generic;

public class Graph
{
    private int V; // 그래프의 정점 개수
    private List<int>[] adj; // 인접 리스트

    public Graph(int v)
    {
        V = v;
        adj = new List<int>[V];
        for (int i = 0; i < V; i++)
        {
            adj[i] = new List<int>();
        }
    }

    public void AddEdge(int v, int w)
    {
        adj[v].Add(w);
    }

    public void DFS(int v)
    {
        bool[] visited = new bool[V];
        DFSUtil(v, visited);
    }

    private void DFSUtil(int v, bool[] visited)
    {
        visited[v] = true;
        Console.Write($"{v} ");

        foreach (int n in adj[v])
        {
            if (!visited[n])
            {
                DFSUtil(n, visited);
            }
        }
    }

    public void BFS(int v)
    {
        bool[] visited = new bool[V];
        Queue<int> queue = new Queue<int>();

        visited[v] = true;
        queue.Enqueue(v);

        while (queue.Count > 0)
        {
            int n = queue.Dequeue();
            Console.Write($"{n} ");

            foreach (int m in adj[n])
            {
                if (!visited[m])
                {
                    visited[m] = true;
                    queue.Enqueue(m);
                }
            }
        }
    }
}

public class Program
{
    public static void Main()
    {
        Graph graph = new Graph(6);

        graph.AddEdge(0, 1);
        graph.AddEdge(0, 2);
        graph.AddEdge(1, 3);
        graph.AddEdge(2, 3);
        graph.AddEdge(2, 4);
        graph.AddEdge(3, 4);
        graph.AddEdge(3, 5);
        graph.AddEdge(4, 5);

        Console.WriteLine("DFS traversal:");
        graph.DFS(0);
        Console.WriteLine();

        Console.WriteLine("BFS traversal:");
        graph.BFS(0);
        Console.WriteLine();
    }
}

 

 

최단 경로 알고리즘

 

다익스트라 알고리즘(Dijkstra Algorithm)

하나의 시작 정점에서 다른 모든 정점까지의 최단 경로를 찾는 알고리즘입니다.

음의 가중치를 갖는 간선이 없는 경우에 사용됩니다.

 

벨만-포드 알고리즘(Bellman-Ford Algorithm)

음의 가중치를 갖는 간선이 있는 그래프에서도 사용할 수 있는 최단 경로 알고리즘입니다.

음수 사이클이 있는 경우에도 탐지할 수 있습니다.

 

A 알고리즘 (A-star Algorithm)

특정 목적지까지의 최단 경로를 찾는 알고리즘입니다.

휴리스틱 함수를 사용하여 각 정점까지의 예상 비용을 계산하고, 가장 낮은 예상 비용을 가진 정점을 선택하여 탐색합니다

 

다익스트라 알고리즘 예제

using System;

class DijkstraExample
{
    static int V = 6; // 정점의 수

    // 주어진 그래프의 최단 경로를 찾는 다익스트라 알고리즘
    static void Dijkstra(int[,] graph, int start)
    {
        int[] distance = new int[V]; // 시작 정점으로부터의 거리 배열
        bool[] visited = new bool[V]; // 방문 여부 배열

        // 거리 배열 초기화
        for (int i = 0; i < V; i++)
        {
            distance[i] = int.MaxValue;
        }

        distance[start] = 0; // 시작 정점의 거리는 0

        // 모든 정점을 방문할 때까지 반복
        for (int count = 0; count < V - 1; count++)
        {
            // 현재 방문하지 않은 정점들 중에서 최소 거리를 가진 정점을 찾음
            int minDistance = int.MaxValue;
            int minIndex = -1;

            for (int v = 0; v < V; v++)
            {
                if (!visited[v] && distance[v] <= minDistance)
                {
                    minDistance = distance[v];
                    minIndex = v;
                }
            }

            // 최소 거리를 가진 정점을 방문 처리
            visited[minIndex] = true;

            // 최소 거리를 가진 정점과 인접한 정점들의 거리 업데이트
            for (int v = 0; v < V; v++)
            {
                if (!visited[v] && graph[minIndex, v] != 0 && distance[minIndex] != int.MaxValue && distance[minIndex] + graph[minIndex, v] < distance[v])
                {
                    distance[v] = distance[minIndex] + graph[minIndex, v];
                }
            }
        }

        // 최단 경로 출력
        Console.WriteLine("정점\t거리");
        for (int i = 0; i < V; i++)
        {
            Console.WriteLine($"{i}\t{distance[i]}");
        }
    }

    static void Main(string[] args)
    {
        int[,] graph = {
            { 0, 4, 0, 0, 0, 0 },
            { 4, 0, 8, 0, 0, 0 },
            { 0, 8, 0, 7, 0, 4 },
            { 0, 0, 7, 0, 9, 14 },
            { 0, 0, 0, 9, 0, 10 },
            { 0, 0, 4, 14, 10, 0 }
        };

        int start = 0; // 시작 정점

        Dijkstra(graph, start);
    }
}

 


 

3주차 Snake_Game 만들기 과제

 

Console.SetCursorPosition(x, y); 활용하기

Console.SetCursorPosition(x, y);는 콘솔 커서를 x, y 위치로 이동시켜주는 코드이다.

ctrl + k + d 자동정렬

 

foreach→컬렉션이나 배열의 각 요소를 반복하여 처리하는데 사용

foreach(타입 변수명 in 컬렉션)
{
	반복되는 코드
}

string[] fruits = { "apple", "orange", "banana" };

foreach(string fruit in fruits)
{
	Console.Write(fruit);
}

 

console.readkey()

키입력을 받고 입력된 키의 정보를 반환

true를 넣어주면 화면상 출력 사라짐

값 안넣거나 false를 넣으면 화면상 내가 누른값 출력

-> keyinfo = console.readkey(true)

keyinfo를 반환함

readkey.key = 특정키의 눌림여부를 확인

readkey.modifiers 수정자 키 ctrl, alt, shift 사용여부확인

 

console.keyavailable

현재 입력버퍼에 키입력이 있는지 확인

눌리면true 안눌리면 false

 

console.readkey().key != consolekey.enter

 

consolekeyinfo keychar 누른 키의 유니코드 문자를 가져옴

 

 


📝 오늘의 마무리

유니티가 시작하면서 빡집중해서 남은 강의를 다 들었다.

근데 조금 아니 많이 어렵다.

이걸 내가 실제 코드에 적용할수있을까

 

그 어려운 와중에도 몇가지들은

이걸 진작에 보고 만들었으면 팀 프로젝트를 할 때 조금 더 활용성이 좋고

깔끔한 코드를 만들 수 있지 않았을까 싶다

근데 또 구상하고 구현하는데에 시간을 다 쓴거라 별반 차이없었을꺼같기도 하고..

아직은 음 사용하는게 어색해서

편한 코드를 만들고 정리를 하지 않았을까

 

예전에 미로찾기에서 최단거리 찾는 알고리즘을 생으로 들이박아 만들려고 한적이 있는데

그때는 처참하게 실패했다

그러다가 탐색 알고리즘이 있어서 주의 깊게 봤는데

와 오늘은 그냥 멘붕의 연속이다...

왜이렇게 어려운지

 

개인과제 TextRPG를 만들기 위해

3~5주차 과제는 넘기라고 했었는데

3주차의 과제는 만들어보기로 했다.

(4주차는 TextRPG, 5주차는 알고리즘 문제풀기)


 

✏️ 스스로 어제보다 한 발 더 나아갔다는 것을 자각하기

✏️ TIL을 쓰기 위해서라도, 오늘 반드시 단 하나라도 배우기

✏️ 꾸준히 기록을 남기는 습관 가지기

 

📕 오늘의 학습 키워드

📕  공부한 내용 본인의 언어로 정리하기

📕  오늘의 회고

📕  12시간 중 얼마나 몰입했는지

📕  더 나은 미래를 위해 내일 어떤 공부를 진행할 것인지