[240104]TIL

응징·2024년 1월 4일
0

TIL

목록 보기
10/36
post-thumbnail

강의

알고리즘 기초

Big O 표기법

Big O 표기법은 알고리즘의 효율성을 나타내는 표기법

  • O(1): 상수 시간. 입력의 크기에 상관없이 항상 일정한 시간이 걸립니다.
  • O(n): 선형 시간. 입력의 크기에 비례하여 시간이 걸립니다.
  • O(n^2): 이차 시간. 입력의 크기의 제곱에 비례하여 시간이 걸립니다.
  • O(log n): 로그 시간. 입력의 크기의 로그에 비례하여 시간이 걸립니다.

시간 복잡도 (Time Complexity)

알고리즘이 문제를 해결하는데 걸리는 시간을 나타내는 척도

ex)

int Sum(int n)
{
    int sum = 0;
    for (int i = 0; i <= n; i++)
    {
        sum += i;
    }
    return sum;
}

프가 0부터 n까지 순회, 시간 복잡도는 O(n)

ex)

void PrintPairs(int n)
{
    for (int i = 0; i <= n; i++)
    {
        for (int j = 0; j <= n; j++)
        {
            Console.WriteLine(i + ", " + j);
        }
    }
}

두 개의 중첩된 for 루프를 포함, 각 루프는 0부터 n까지 순회하므로, 시간 복잡도는 O(n^2)

공간 복잡도 (Space Complexity)

코드의 메모리 사용량을 실제 메모리 크기(바이트)로 측정하는 것이 아니라, 입력 크기에 따라 필요한 저장 공간의 양을 측정하는 이유를 설명

정렬 알고리즘

선택 정렬 ( Selection Sort )

  • 선택 정렬은 배열에서 최소값(또는 최대값)을 찾아 맨 앞(또는 맨 뒤)와 교환하는 방법
  • 시간 복잡도: 최악의 경우와 평균적인 경우 모두 O(n^2)
  • 공간 복잡도: O(1) (상수 크기의 추가 공간이 필요하지 않음

최악의 경우와 평균적인 경우 둘다 시간 복잡도는 같기 때문에 무난하게 정렬하기 좋은듯

삽입 정렬 ( Insertion Sort )

  • 삽입 정렬은 정렬되지 않은 부분에서 요소를 가져와 정렬된 적절한 위치에 삽입하는 방법
  • 시간 복잡도: 최악의 경우 O(n^2), 하지만 정렬되어 있는 경우에는 O(n)
  • 공간 복잡도: O(1) (상수 크기의 추가 공간이 필요하지 않음)

로직이 조금 복잡하긴 하지만, 선택 정렬보다 어느 방면에서나 데이터로 우수한데 선택 정렬은 장점이 없나?

퀵 정렬 ( Quick Sort )

  • 퀵 정렬은 피벗을 기준으로 작은 요소들은 왼쪽, 큰 요소들은 오른쪽으로 분할하고 이를 재귀적으로 정렬
  • 시간 복잡도: 최악의 경우 O(n^2), 하지만 평균적으로 O(n log n)
  • 공간 복잡도: 평균적으로 O(log n), 최악의 경우 O(n) (재귀 호출에 필요한 스택 공간)

강의에선 피벗을 오른쪽 끝 값은 사용 =3;

3보다 작으면 왼쪽으로 3보다 큰 숫자는 오른쪽으로 다시 왼쪽 오른쪽 둘다 왼쪽 오른쪽으로 또 쪼개기. 피벗은 오른쪽 끝 값을 사용

그런데 이건 어떤 때 쓰는 거냐...? 시간 복잡도와 공간 복잡도가 너무 큰데

개인과제 (TextGame)

저장하기

JSON 파일

특정 변수를 파일로 저장해서 다음 런타임에도 계속 이어서 할 수 있는 방법을 꽤 여러가지가 있다. 파일 입출력 (File I/O) 방법이나, 환경 변수를 사용하는 방법 꽤 다양하게 나왔는데 게임 개발에서 파일 저장은 JSON 파일이 얘기가 많길래 한번 알아보았다. 먼저 JSON 파일을 사용하기 전에 NuGet 패키지에서 Newtonsoft.Json 패키지를 설치 해야한다.

(검색창)

(설치됨)

<JSON 저장하기>

코드 내에서 데이터를 저장하는 방법은 아래와 같다

string filePath = "player.json";
string json = JsonConvert.SerializeObject(player);
File.WriteAllText(filePath, json);

파일명은 player.json이고 JsonConvert.SerializeObject는 해당 자료를 JSON 파일 구조로 직렬화하는 과정이라고 한다. 나 같은 경우 Player 클래스 타입을 저기에 넣었다. 그리고
File.WriteAllText (파일 경로 , JSON 파일타입) 을 넣는데 참고로 파일경로를 지정해 주지 않는다면 해당 작업 디렉토리에 저장된다고 한다.

<JSON 불러오기>

이제 데이터를 불러올 차례이다

static Character Load()
        {
            // 파일에서 JSON 읽기
            string filePath = "player.json";
            if (File.Exists(filePath))
            {
                string json = File.ReadAllText(filePath);
                return JsonConvert.DeserializeObject<Character>(json);
            }
            else
            {
                Rename = true; //이름 새설정
                // 파일이 없으면 기본값으로 새 플레이어 생성
                return new Character { }; //클래스 생성

            }
        }

File.Exists는 해당 파일이 있는지 여부를 보는 메소드이다. 경로를 지정해주지 않으면 해당 작업 디렉토리로 판정한다. 그렇게 해서 만약 이미player.json 파일이 있다면 파일을 읽어온다. File.ReadAllText(filePath)는 해당 파일에서 텍스트를 읽어와서 그 내용을 json 변수에 저장하는 작업이다. 이상태로는 class형으로 읽을수 없기 때문에 JsonConvert.DeserializeObject(json);과정을 거친다.

Rename은 만약 새 플레이어라면 if문으로 이름을 설정하게끔 하는 bool 자료형이다

JSON 저장 시점 구상

static void Main(string[] args)
      {
          Player = Load();

          // 프로세스 종료 이벤트 핸들러 등록
          AppDomain.CurrentDomain.ProcessExit += OnProcessExit;

          CreateItem1(Armors);
          CreateItem2(Weapons);

          //---------------------------------------------

          if(Rename)   //처음인 경우
          {
              Console.WriteLine("당신의 이름을 알려주세요.");
              Player.Name = Console.ReadLine();  //캐릭터 이름까지 설정
          }
          



          Console.Clear(); //이전 내용 지우기
          Console.WriteLine("스파르타 마을에 오신 여러분 환영합니다.");
          Console.WriteLine("이곳에서 던전으로 들어가기전 활동을 할 수 있습니다.");
          StartMap();
          while (true) // 조건 수정
          {
              Console.Clear(); //이전 내용 지우기
              switch (Map)
              {
                  case 0:  //시작마을
                      StartMap();
                      break;

                  case 1: //상태보기
                      State(Player);

                      break;
                  case 2: //인벤토리
                      Inventory();
                      break;
                  case 3: //상점
                      Store();
                      break;
                  case 4: //던전
                      DungeonStart();
                      break;
                  case 5: //휴식하기
                      Rest();
                      break;
                  default:
                      Map = 0;
                      break;
              }
          }
      }

현재 TextGame의 메인 부분이다. while 반복처리를 하고 있기 때문에 처음엔 이 루프 부분에 저장을 넣어 주기적으로 저장해주길 바랬는데 생각보다 함수와 함수사이에서 Console.ReadLine() 치는 중간단계 때문에 루프 부문에 있을 기회는 시작마을에 있을 때 뿐이다. 그래서 혹시나 콘솔이 종료되면 자동적으로 저장될 수 없는지 찾아보았다.

AppDomain.CurrentDomain.ProcessExit

그러다 보니 위의 핸들러를 알게되었다. 콘솔이 종료되면 자동적으로 실행되는 핸들러이다. 여기서 델리게이트로 새로운 함수 기능도 같이 구현해 보기로 했다.

	AppDomain.CurrentDomain.ProcessExit += OnProcessExit;

...생략

static void OnProcessExit(object sender, EventArgs e) //프로세스 종료전 이 함수가 실행 
      {
          Save(Player);
      }

OnProcessExit에 저장하는 로직을 넣고 콘솔이 종료될때 델리게이트로 OnProcessExit함수도 같이 호출했다.

결과적으로 잘 저장되었으며 해당 파일 내부는 아래와 같다.

스레드로 스토리및 디테일 추가

&

4주차 과제 제출은 안했지만 과제 완성본의 구조가 궁금해서 스네이크 게임 완성본 코드를 봤다.
스레드를 중점으로 쓰던데 시간을 관리하는 줄 알았더니, 그냥 스레드는 현 작업과 다른 작업을 동시에 수행하기 위해 사용된다고 한다.

그래도 과제 내에서 쓴 Thread.Sleep() 메소드를 알아보니 스레드를 지정된 시간 동안 일시적으로 중지하는 메서드라더라.

아직까진 5주차가 가장 이해안됨. 나중에 5주차 복습하기

profile
Unity 개발 위주로 정리합니다

0개의 댓글