상점 시스템 설계 및 구현
개요
콘솔 기반 RPG에서 사용할 수 있는 상점 시스템을 구현했다.
플레이어와 인벤토리를 연동하여 다음 기능을 제공한다.
- 아이템 구매
- 아이템 판매
- 인벤토리 확인
단순 기능 구현이 아닌, UI / 로직 / 데이터의 역할 분리를 목표로 설계했다.
기존 접근 방식과 문제점
초기에는 하나의 함수에서 모든 처리를 수행하는 방식으로 접근했으나 다음과 같은 문제가 발생했다.
- UI와 로직이 혼합되어 가독성이 낮음
- 기능 추가 시 코드 수정 범위 증가
- 재사용이 어려움
이러한 문제를 해결하기 위해 구조를 분리하는 방향으로 설계를 진행했다.
전체 구조 설계
클래스 구성
Store
├── Player (외부 의존)
└── Inventory (외부 의존)
{
std::string name;
int price;
};
핵심 설계 의도
- Store는 상점의 흐름만 담당
- Player는 상태 관리
- Inventory는 아이템 관리
즉, 각 객체가 하나의 책임만 가지도록 구성했다.
상태 기반 흐름 설계
while (isOpen_)
{
PrintMainMenu(player);
int choice;
std::cin >> choice;
switch (choice)
{
case 1: BuyItem(player, inventory); break;
case 2: SellItem(player, inventory); break;
case 3: /* 인벤토리 출력 */ break;
case 0: Close(); break;
}
}
설계 포인트
- 상점은 "열림과 닫힘 상태"를 가진다
- 입력에 따라 기능이 분기된다
- 하나의 루프 안에서 모든 흐름을 제어한다
UI와 로직 분리
출력 관련 기능을 별도의 함수로 분리했다
void PrintTitle(const std::string& title) const;
void PrintBorder() const;
void PrintPlayerInfo(const Player& player) const;
의도
- 출력 형식을 한 곳에서 관리
- 동일 UI 재사용 가능
- 로직 코드와 분리하여 가독성 확보
예를 들어 타이틀 출력은 다음과 같이 통일된다
PrintTitle("마녀의 물약 상점");
아이템 구매 로직
if (player.GetGold() < item.price)
{
// 구매 실패
}
player.loseGold(item.price);
inventory.AddItem(item.name, item.price);
처리 흐름
- 골드 확인
- 골드 차감
- 인벤토리에 아이템 추가
설계 포인트
- 조건 검증 → 상태 변경 → 결과 처리 순서 유지
- 실패 케이스를 먼저 처리하여 흐름 단순화
아이템 판매 로직
int sellPrice = item.price * 60 / 100;
inventory.RemoveItem(index);
player.gainGold(sellPrice);
설계 포인트
- 판매가는 원가의 60%로 설정
- 처리 순서를 명확히 정의
순서:
- 인벤토리에서 제거
- 골드 지급
이 순서를 지키지 않으면 문제가 발생할 수 있다
입력 예외 처리
if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(10000, '\n');
}
문제 상황
- 잘못된 입력 시 cin이 실패 상태 유지
- 이후 입력이 모두 무시되는 문제 발생
해결
- clear()로 상태 초기화
- ignore()로 입력 버퍼 제거
출력 정렬 처리
std::setw(2)
std::left
std::right
역할
- 출력 정렬
- UI 가독성 개선
개선해야 할 사항
1. 입력 대기 코드 중복
int temp;
std::cin >> temp;
현재 입력을 받는 코드가 여러 위치에서 반복되고 있다
- 입력 처리 로직이 중복되면 유지보수 시 수정 범위가 증가
- 입력 검증(예외 처리) 추가 시 모든 코드에 동일하게 반영해야 하는 문제 발생
입력 처리 로직을 별도의 함수로 분리하여 재사용성을 높일 필요가 있어보인다
2.ClearScreen 방식
std::cout << std::string(30, '\n');
현재 화면을 초기화하기 위해 개행을 출력하는 방식을 사용하고 있다
- 실제 화면이 지워지는 것이 아니라 단순히 밀어내는 방식
- 콘솔 환경에 따라 출력 결과가 일관되지 않을 수 있음
추후 찾아보고 변경사항 추가
3.ShopItem 확장
현재 ShopItem은 다음과 같은 구조로 구성되어 있다.
- name
- price
이 구조는 기본적인 상점 기능에는 충분하나
- 아이템 타입 ( 소모품, 장비 등)
- 효과 ( 회복량, 버프, 디버프 등)
- 설명 (UI 표시용 텍스트)
와 같은 요소를 추가하기 어려운 구조
기능 확장을 고려하여 구조를 확장 가능한 형태로 개선해야 한다
마무리
이번 구현을 통해 다음과 같은 점을 확인할 수 있엇다.
게임 시스템은 상태 흐름을 기반으로 설계되어야 하며,
UI와 로직을 분리함으로써 유지보수성과 확장성을 확보할 수 있다.
또한 객체 간 역할을 명확히 나누는 것이 전체 구조의 안정성과 코드 관리 측면에서 중요하다는 것을 이해하게 되었다.
특히 팀 프로젝트를 통해
각 기능이 독립적으로 동작할 수 있도록 설계하는 것이 협업에서 필수적이며,
단순 구현을 넘어서 구조를 고려한 개발의 중요성을 경험할 수 있엇다.
'학습일지 > C와 C++' 카테고리의 다른 글
| C++ 팀 프로젝트 TextConsoleRPG (0) | 2026.04.01 |
|---|---|
| C++ 콘솔 RPG 프로젝트 Main 흐름 정리 (0) | 2026.03.31 |
| C++ 보스 몬스터 설계와 패턴 (0) | 2026.03.27 |
| C++ 첫 번째 협업 체험 팀 프로젝트 (0) | 2026.03.26 |
| C++ 연금술 공방 관리 시스템 구현 과제 (0) | 2026.03.24 |