Big O 표기법은 알고리즘의 효율성을 나타내는 표기법
알고리즘이 문제를 해결하는데 걸리는 시간을 나타내는 척도
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)
코드의 메모리 사용량을 실제 메모리 크기(바이트)로 측정하는 것이 아니라, 입력 크기에 따라 필요한 저장 공간의 양을 측정하는 이유를 설명
- 선택 정렬은 배열에서 최소값(또는 최대값)을 찾아 맨 앞(또는 맨 뒤)와 교환하는 방법
- 시간 복잡도: 최악의 경우와 평균적인 경우 모두 O(n^2)
- 공간 복잡도: O(1) (상수 크기의 추가 공간이 필요하지 않음
최악의 경우와 평균적인 경우 둘다 시간 복잡도는 같기 때문에 무난하게 정렬하기 좋은듯
- 삽입 정렬은 정렬되지 않은 부분에서 요소를 가져와 정렬된 적절한 위치에 삽입하는 방법
- 시간 복잡도: 최악의 경우 O(n^2), 하지만 정렬되어 있는 경우에는 O(n)
- 공간 복잡도: O(1) (상수 크기의 추가 공간이 필요하지 않음)
로직이 조금 복잡하긴 하지만, 선택 정렬보다 어느 방면에서나 데이터로 우수한데 선택 정렬은 장점이 없나?
강의에선 피벗을 오른쪽 끝 값은 사용 =3;
3보다 작으면 왼쪽으로 3보다 큰 숫자는 오른쪽으로 다시 왼쪽 오른쪽 둘다 왼쪽 오른쪽으로 또 쪼개기. 피벗은 오른쪽 끝 값을 사용
그런데 이건 어떤 때 쓰는 거냐...? 시간 복잡도와 공간 복잡도가 너무 큰데
특정 변수를 파일로 저장해서 다음 런타임에도 계속 이어서 할 수 있는 방법을 꽤 여러가지가 있다. 파일 입출력 (File I/O) 방법이나, 환경 변수를 사용하는 방법 꽤 다양하게 나왔는데 게임 개발에서 파일 저장은 JSON 파일이 얘기가 많길래 한번 알아보았다. 먼저 JSON 파일을 사용하기 전에 NuGet 패키지에서 Newtonsoft.Json 패키지를 설치 해야한다.
(검색창)
(설치됨)
코드 내에서 데이터를 저장하는 방법은 아래와 같다
string filePath = "player.json";
string json = JsonConvert.SerializeObject(player);
File.WriteAllText(filePath, json);
파일명은 player.json이고 JsonConvert.SerializeObject는 해당 자료를 JSON 파일 구조로 직렬화하는 과정이라고 한다. 나 같은 경우 Player 클래스 타입을 저기에 넣었다. 그리고
File.WriteAllText (파일 경로 , 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 자료형이다
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주차 복습하기