[2025_10_13]TextRpg 개발 회고

2025. 10. 13. 14:47TIL

C# 콘솔 RPG 게임 개발 회고 (1주 프로젝트)

프로젝트 개요

1주일 동안 C# 콘솔 기반의 텍스트 RPG 게임을 개발했습니다. 플레이어가 던전을 탐험하고, 아이템을 구매/판매하며, 장비를 관리하는 시스템을 구현했습니다.

사용 기술 스택

  • 언어: C#
  • 핵심 기술: LINQ, Tuple, Dictionary, List, JSON 직렬화/역직렬화, Enum, TryParse를 활용한 입력 검증
  • 디자인 패턴: 상속 구조, Static 활용

핵심 구조 설계

1. 데이터 구조

Enum을 활용한 아이템 타입 정의

 
csharp
// 아이템 타입을 Enum으로 관리
// 처음엔 Weapon, Potion 등으로 선언하려 했으나
// 아이템 이름을 통해 정보를 받아오는 방식으로 구현

아쉬운 점: 아이템 타입을 Weapon, Potion 같은 일반적인 형태가 아닌 아이템 이름 기반으로 구현한 부분이 개선의 여지가 있습니다.

ItemInfo 구조체

아이템의 모든 정보를 담는 구조체를 설계했습니다.

  • 이름
  • 타입
  • 능력치 보너스
  • 설명
  • 가격

생성자를 통해 초기화하도록 구현했습니다.

 

자주 사용하거나 밸런스 조정이 필요한 값들은 상수(const)로 선언해 관리했습니다.

2. 클래스 설계

Character 클래스 (베이스 클래스)

몬스터와 플레이어가 공유하는 공통 속성을 정의했습니다.

 
csharp
// 공통 속성
- 이름
- 레벨
- HP
- 공격력
- 방어력

Player 클래스 (상속)

Character 클래스를 상속받아 플레이어만의 고유 속성을 추가했습니다

 
csharp
// 플레이어 전용 속성
- 직업
- 골드
- 스태미나
- 경험치

// 이니셜라이저를 통해 base(Character) 속성 초기화

주요 시스템 구현

1. 아이템 관리 시스템

데이터 구조

 
csharp
// Dictionary를 활용한 아이템 데이터 관리
Dictionary<Item, ItemInfo> itemData;

// List를 활용한 인벤토리 시스템
static List<Item> playerInventory = new List<Item>();
static List<Item> equipItem = new List<Item>();
static List<Item> shopItem = new List<Item>();

 

ItemInit 메서드

 
csharp
// 반환형: Dictionary<Item, ItemInfo>
// 역할: 게임 시작 시 모든 아이템 데이터 초기화

2. 인벤토리 & 장비 시스템

Inven 클래스

  • 인벤토리 화면 표시
  • 장비창으로 이동 기능
  • 한글 정렬 문제 해결: Utility.PaddingKorean 메서드를 사용해 글자 수 정렬 구현

EquipManager 클래스

장비 장착/해제를 관리하는 핵심 시스템입니다.

장착 여부 체크

 
csharp
bool isEquip; // 장착 여부 플래그

// IsEquipIndex(i) 메서드로 체크
// 현재 장착 중인 아이템이 플레이어 인벤토리에 포함되어 있는지 확인
// true → [E] 표시
// false → - 표시

EquipToggle 메서드

  • 아이템 번호 입력 시 장착/해제
  • 이미 장착 중이면 → 해제
  • 장착 중이 아니면 → 장착
  • HP 포션은 → 사용 후 제거
  • 같은 타입의 아이템 중복 방지: 기존 아이템 자동 해제 후 새 아이템 장착

3. 상점 시스템

Shop 메서드

 
csharp
// LINQ의 OrderBy를 활용한 가격순 정렬
shopItem.OrderBy(item => itemData[item].Price);

ShopBuy 메서드 (구매)

  • 이미 구매한 아이템 체크
  • 포션은 중복 구매 가능하도록 별도 처리

ShopSell 메서드 (판매)

  • 플레이어 인벤토리에서 아이템 선택
  • 판매 시 인벤토리와 장착 리스트에서 모두 제거

4. 탐험 & 던전 시스템

TownPatrol 메서드

 
csharp
// Tuple(var)을 사용한 이벤트 관리
// break를 통한 누적값 계산 처리
// → break 없이 foreach 계속 실행 시 조건에 맞는 모든 값이 중복 계산되는 문제 방지

Dungeon 메서드

던전 입장을 관리하는 핵심 메서드입니다.

기능:

  • 던전 이름과 보상 초기화
  • 방어력과 공격력에 따른 성공/실패 판정
  • 결과 출력

CalcDamage 메서드

 
csharp
// 던전에서 플레이어가 받는 데미지 계산
// 매개변수: 던전 인덱스 (어떤 던전인지)
// 제시된 공식에 따라 계산

CalcReward 메서드

 
csharp
// 플레이어 공격력에 따른 보상 계산
// 매개변수: 던전 인덱스, 보상(골드, 경험치)
// 제시된 공식에 따라 계산

DungeonResult 메서드

던전 결과를 콘솔에 표시하는 메서드입니다.

매개변수:

  • 던전 이름
  • 성공 여부
  • 받은 데미지
  • 던전 인덱스
  • 보상

처리 로직:

  1. 성공 시 → CalcReward 호출
  2. 경험치 획득 → CheckLevelUp 실행
  3. 성공/실패 결과 출력

5. 레벨 시스템

CheckLevelUp 메서드

플레이어의 레벨업을 담당하는 메서드입니다.

기능:

  • 레벨업 시 요구 경험치 증가
  • 능력치 자동 상승
  • 최대 레벨 도달 시 레벨업 중지
  • 다중 레벨업 지원: While문을 사용해 한 번에 2레벨 이상 오를 만큼 경험치를 획득해도 처리 가능

저장/불러오기 시스템

SaveLoad 메서드

저장 슬롯: 총 3개

기능:

  • 저장 데이터 유무에 따라 다른 출력
  • 기존 데이터가 있는 슬롯 선택 시 → "덮어쓰기" 또는 "불러오기" 선택
  • GameManager.cs의 GameSaveManager 클래스를 static으로 선언해 GameSave, GameLoad 메서드 호출

로드 처리:

  1. SaveData 클래스에서 슬롯 정보 읽기
  2. 새로운 플레이어 객체 생성
  3. Start 메서드에 로드된 플레이어 객체를 매개변수로 전달

GameManager.cs

SaveData 클래스

세이브 데이터에 저장될 변수들을 선언한 클래스입니다.

생성자 2개 구현 이유:

  • 빈 생성자: 역직렬화(로드)를 위해 필요
  • 매개변수 생성자: 직렬화(저장)를 위해 필요

GameSaveManager 클래스

JSON 한글 저장 문제 해결

 
csharp
var options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), // 한글 포함 모든 유니코드 출력
    WriteIndented = true  // 줄바꿈과 들여쓰기 적용
};

// WriteIndented 옵션 비교
// false: 한 줄로 압축, 파일 크기 작음, 가독성 낮음 → 네트워크 전송/대용량 데이터
// true: 줄바꿈과 들여쓰기, 파일 크기 큼, 가독성 높음 → 디버깅/세이브 파일

 

GameSave 메서드

 

csharp
// 매개변수: 현재 플레이어 정보, 인벤토리, 장착 아이템
// 1. 새로운 SaveData 객체 생성
// 2. JsonSerializer.Serialize로 직렬화
// 3. File.WriteAllText로 파일 저장

 

GameLoad 메서드

 
csharp
// 반환형: SaveData
// 매개변수: 슬롯 번호
// 1. 파일에서 JSON 읽기
// 2. JsonSerializer.Deserialize로 역직렬화
// 3. SaveData 객체 반환

유틸리티 시스템

Util.cs (Utility 클래스)

편의 기능 메서드를 모아둔 static 클래스입니다.

주요 메서드:

  1. PaddingKorean: 한글 글자 수 정렬
  2. IntInput: TryParse를 활용한 숫자 입력 검증
    • 숫자만 입력 허용
    • 문자 입력 시 "숫자만 입력해주세요!" 출력

메인 진입점

Main 메서드

 
csharp
// 콘솔 제목 설정
// 플레이어 객체 생성
// 커서 숨기기
// Init() 호출
// Start() 호출

간결하게 두 개의 메서드만 호출하도록 설계했습니다.

Init 메서드

 
csharp
// 1. ItemInit 메서드로 itemData 초기화
// 2. foreach문으로 상점에 아이템 추가

Start 메서드

가장 긴 메서드입니다. 이유는 시작 화면에서 이동 가능한 뷰가 많기 때문입니다.

기능:

  • 사용자 입력 받기
  • 각 화면으로 이동 처리
  • 문자열 입력 버그 방지 → Utility.IntInput 사용

프로젝트를 통해 학습한 기술

1. LINQ (Language Integrated Query)

  • OrderBy를 활용한 데이터 정렬

2. Tuple

  • 여러 값을 묶어서 반환
  • 이벤트 관리에 활용

3. Dictionary & List

  • Dictionary로 키-값 쌍 관리
  • List로 동적 컬렉션 관리

4. JSON 직렬화/역직렬화

  • 게임 데이터 저장/불러오기
  • 한글 인코딩 문제 해결

5. Static 활용

  • 외부 C# 파일에서 유틸리티 메서드 바로 호출
  • 코드 재사용성 향상

6. Enum (열거형)

  • 상수 그룹 관리
  • 타입 안정성 확보

7. 상속 구조 설계

  • Character 베이스 클래스
  • Player 파생 클래스
  • 코드 중복 최소화

8. TryParse 활용

  • 안전한 자료형 변환
  • 예외 처리 없이 유효성 검증

개선이 필요한 부분

  1. 아이템 타입 관리: Enum을 더 효과적으로 활용할 수 있었음
  2. 코드 모듈화: 일부 메서드가 너무 길어져 분리 필요
  3. 에러 처리: 예외 상황에 대한 더 견고한 처리 필요

마치며

1주일이라는 짧은 시간 동안 C#의 다양한 기능을 활용해 콘솔 RPG 게임을 완성했습니다. 특히 JSON 직렬화를 통한 저장 시스템과 LINQ를 활용한 데이터 처리, 그리고 상속 구조 설계를 실제로 구현해보면서 많은 것을 배울 수 있었습니다.

다음 프로젝트에서는 이번에 아쉬웠던 부분들을 개선하고, 더 나은 설계 패턴을 적용해보려고 합니다!