2024-04-25
개인 프로젝트의 마감일이다.
마지막 기능인 "데이터 저장하기" 라는 큰 벽을 만나게 되었다.
json 을 활용하여 게임을 종료해도 이전에 플레이 한 데이터가 남도록 만들어보자.
최소 하루 한 번, 영타를 연습하면 좋을 것 같아 하루 루틴에 추가하였다.
객체를 다른 형식으로 변환하여 데이터를 저장하거나 전송하는 과정이다.
(C# 의 경우, 주로 데이터를 텍스트의 형식으로 변환하여 데이터를 전송, 특히 Json 형태로)
건담 프라모델(클래스)을 분해하여(직렬화) 내용물과 조립설명서로 택배 (json)를 보냄
데이터 저장 : 객체의 현재 상태를 저장, 저장된 데이터를 다시 읽어와서 사용
데이터 전송 : 네트워크를 통해서 다른 시스템으로 전송하거나 통신
복원 및 복구 : 프로그램이 중단됐을 때, 객체의 이전 상태를 복원하거나 복구
닷넷에서 JSON 을 사용하기 위한 오픈 소스 중 하나이다.
아래의 이미지를 따라 Newtonsoft.Json 패키지를 설치하고, 코드에 using Newtonsoft.Json 을 추가한다.
JsonConvert 를 입력하고 빨간줄에 마우스를 올려 다음과 같이 진행한다.
진행한 게임 정보를 저장하기 위해서 Serialize 를 수행하여
Player 클래스 정보를 Json 형식으로 전환하는 것이 목표이다.
먼저 사용되는 함수를 알아보자.
지정된 시스템 특수 폴더의 경로를 가져온다.
public static string GetFolderPath(Environment.SpeicalFolder folder);
매개 변수 : folder - Environment.SpeicalFolder (시스템 관련 폴더를 식별하는 열거형 값 중 하나)
반환 값 : String
해당 폴더가 실제 컴퓨터에 존재하면, 지정한 시스템 특수 폴더의 경로가 String 형태로 저장
존재하지 않는다면, 빈 문자열("")을 저장
두 문자열을 한 경로로 결합한다.
public static string Combine(string path1, string path2);
매개 변수 : path 1,2 (결합할 경로들)
반환 값 : String
결합된 경로. 만약 지정된 경로 중 하나의 길이가 0인 문자열이면, 다른 경로를 반환
path2 에 절대 경로가 포함되어 있으면 path2 를 반환
.NET 객체로부터 JSON 문자열을 만들기 위해 사용한다.
위의 함수들과는 다르게 패키지를 추가하여 사용한 메서드이기 때문에
함수를 클릭하고 F12 버튼을 눌러 정의를 확인할 수 있었다.
매개 변수 : value (Json 으로 변환시킬 객체) , converters(직렬화 되는 동안 사용되는 변환기 모음)
반환 값 : String
새 파일을 만들고 지정된 문자열을 파일에 쓴 다음 파일을 닫는다.
파일이 이미 존재하면, 덮어쓴다.
public static void WriteAllText(string path, string? contents);
매개 변수 : path (쓸 파일) , contents (파일에 쓸 문자열)
static void SaveData()
{
// 저장할 json 파일의 이름 지정
string playerDataName = "playerStatData.json";
string itemDataName = "itemData.json";
// 데이터 경로 저장 (C드라이브 - Documents)
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
// 여러 문자열을 한 경로로 결합하는 Path.Combine(str1, str2)
string playerDataPath = Path.Combine(path, playerDataName);
string itemDataPath = Path.Combine(path, itemDataName);
// Class 를 Json 으로 Serialize (직렬화)
string playerJson = JsonConvert.SerializeObject(player, Formatting.Indented);
string itemJson = JsonConvert.SerializeObject(player.myItems, Formatting.Indented);
// 새 파일을 만들고 파일에 내용을 쓴 다음 닫는다. 대상 파일이 이미 존재하는 경우 덮어쓴다.
File.WriteAllText(playerDataPath, playerJson);
File.WriteAllText(itemDataPath, itemJson);
}
직렬화의 반대 과정.
직렬화된 데이터를 원래 데이터 구조로 복원하는 작업
택배 (json) 를 받아 내용물과 조립설명서를 통해 조립하여 건담 (클래스)을 복구
string noviceArmor = "수련자 갑옷";
string info = "수련에 도움을 주는 갑옷입니다.";
int price = 1000;
Console.WriteLine("{0} | {1} | {2} G", noviceArmor ,info, price};
// 결과 : 수련자 갑옷 | 수련에 도움을 주는 갑옷입니다. | 1000 G
저장한 Json 형식을 불러와 객체 정보로 전환하는 것이 목표이다.
직렬화에 사용되는 함수와 유사하다.
지정된 파일이 있는지 확인한다.
public static bool Exists(string? path);
매개 변수 : path (확인할 파일)
반환 값 : Boolean
파일의 이름이 존재하고, 호출자에게 필요한 권한이 있으면 true , 그렇지 않으면 false
path 가 잘못된 경로이거나 빈 문자열이면 false
호출자에게 지정된 파일을 읽을 권한이 없는 경우 false
텍스트 파일을 열고 파일의 모든 텍스트를 읽은 다음 파일을 닫는다.
public static string ReadAllText(string path);
매개 변수 : path (읽어올 파일의 경로)
반환 값 : String
파일의 모든 텍스트를 포함하는 문자열
JSON 문자열로부터 .NET 객체를 만들기 위해 사용한다.
위의 함수들과는 다르게 패키지를 추가하여 사용한 메서드이기 때문에
함수를 클릭하고 F12 버튼을 눌러 정의를 확인할 수 있었다.
매개 변수 : value (객체로 변환시킬 Json 문자열)
반환 값 : T (클래스)
static void LoadData()
{
// 불러올 json 파일의 이름 지정
string playerDataName = "playerStatData.json";
string itemDataName = "itemData.json";
// 데이터 경로 지정 (C 드라이브 - Documents)
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string playerDataPath = Path.Combine(path, playerDataName);
if(File.Exists(playerDataPath)) // json 파일이 존재
{
string playerJson = File.ReadAllText(playerDataPath);
player = JsonConvert.DeserializeObject<Player>(playerJson);
Console.WriteLine("플레이어 데이터를 불러왔습니다.");
}
else // json 파일이 존재하지 않음
{
Console.WriteLine("저장된 플레이어 데이터가 없습니다.");
}
}
"동물의 숲" 게임의 경우, 하루를 마무리하고 침대에 누워 휴식을 취할 때, 게임 정보가 저장된다.
이를 떠올려, [휴식하기] 를 통해 데이터의 정보를 저장하도록 설정하였고,
게임이 시작될 때, 저장된 정보가 있는지 확인하여 불러오도록 했다.
| 저장 |
|---|
![]() |
| 불러오기(파일X) | 불러오기(파일O) |
|---|---|
![]() | ![]() |
어제 계획한 대로, 모든 기능 구현을 마쳤다.
마감 기한까지 시간도 넉넉하여
미처 발견하지 못한 예외 케이스나 버그
(골드가 부족할 때, 메시지를 출력하자마자 바로 화면이 전환되는 경우 -> 발견 후 수정)
조금 더 최적화할 수 있는 코드는 없는지
(3중 if문을 && 와 || 연산자를 적절히 사용해서 줄이기)
찾아보는 시간을 가지며
첫번째 개인 과제 프로젝트를 마칠 수 있었다.