학습일지/C와 C++

C++ 콘솔 RPG 프로젝트 Main 흐름 정리

Tsukino Ren 2026. 3. 31. 20:57

Main 흐름 정리

개요

이번에는 Main.cpp를 중심으로 정리했다. Main.cpp는 개별 기능을 구현하는 파일보다는

게임의 전체 흐름을 제어하고 각 시스템을 연결하는 역할을 담당한다.

 

플레이어 생성, 게임 시작, 메인 메뉴 출력, 전투 진입, 상점 입장, 인벤토리 확인, 아이템 사용, 게임종료 등

전체 진행 흐름이 이 파일로 관리한다.

 

이번 파일은 게임의 시작점이자 제어 역할을 하는 구조라고 볼 수 있다.


포함된 헤더

#include <iostream>
#include <ctime>
#include <cstdlib>

#include "Player.h"
#include "Inventory.h"
#include "Store.h"
#include "BattleSystem.h"
#include "GameLog.h"

라이브러리

  • iostream : 입.출력을 처리 헤더
  • ctime, cstdlib : 난수 시드 설정을 위한 헤더 ( time, srand 사용 )

사용자 정의 헤더

  • Player : 플레이어의 데이터를 관리한다
  • Inventory : 인벤토리 및 아이템을 처리를 담당한다
  • Store : 상점 기능을 담당한다
  • BattleSystem : 전투 기능을 담당한다
  • GameLog : 화면 출력 및 UI를 담당한다

입력 대기 함수 분리

void Next()
{
    std::cin.ignore(20, '\n');
    std::cin.get();
}

반복사용되는 "엔더키를 눌러 다음으로 넘어가는 처리" 를 함수로 분리하여 사용했다.

 

메뉴마다 아래 코드가 반복되면 코드가 중복되어 많아지기에 함수처리를 하여 정리하는 방향으로 정했다.

Next() 함수로 묶어두게 되면

  • 코드 중복이 감소한다
  • 이후 입력 대기 방식 수정 하게되면 함수만 수정해 주면 된다
  • 출력문도 함수처리 하고싶으면 추가 하면 된다

이러한 장점이있다


Srand()

int main(void)
{
 std::srand(static_cast<unsigned int>(std::time(nullptr)));
 
 return 0;
 )

난수 시드를 Time 즉 현재 시간 기준으로 설정하게 했다.

 

이유

전투, 몬스터 생성, 아이템 드롭 등 랜덤 요소가 있는곳에서

프로그램 실행마다 새로운 패턴을 사용하게끔 하기 위해서 사용했다.


주요 객체 생성

   GameLog log;
   Player player("Player");
   Inventory inventory;
   Store store;

이번 main() 에서 필요한 핵심 객체들을 생성한다.

각 객체의 역할

  • GameLog log;
    • 화면 출력 및 UI 표시를 담당한다
  • Player player("Player");
    • 플레이어 상태값을 보관한다
  • Inventory inventory;
    • 아이템 저장 및 사용을 담당한다
  • Store store;
    • 상점 진입 및 구매 처리를 담당한다

중요한 점은 main.cpp가 직접 세부 기능을 구현하지 않고

필요한 객체를 생성하고 호출만 한다는 점이 있다.

 

main()은 로직 처리의 중심보다는 전체 흐름을 조립, 관리하는 역할에 가깝다


시작 메뉴 처리

  int startChoice = log.ShowMainMenu();
  if (startChoice != 1)
  {
      std::cout << "게임을 종료합니다.\n";
      return 0;
  }

게임 시작 전에 메인 화면을 보여주고 시작 선택이 아니면 바로 프로그램을 종료한다

장점

  • 게임 진입 전 분기 처리가 명확하다
  • 이후 시작 메뉴에서 다른 기능 확장이 쉽다

캐릭터 설정

 log.SetupCharacter(&player);

게임 시작 후 플레이어 초기 설정을 진행한다.

 

여기서는 GameLog를 통해 캐릭터 생성 관련 UI와 입력을 담당하며, 실제 대상은 player 객체가 되겠다.


메인 시스템 루프

 while (true)
 {
     if (!player.IsAlive())
     {
         log.DrawGameOver();
         break;
     }
    ~~~~ 
 }

게임은 메인 루프를 통해 계속 반복되게 한다.

 

루프의 가장 앞부분에서 플레이어의 생존 여부를 검사하고 사망 상태라면 게임 오버 화면을 출력한 뒤 종료한다.

 

장점

  • 게임 종료 조건이 루프 상단에 있으니 흐름 파악이 쉽다
  • 가장 앞에 있으니 이후 다른 종료 조건들도 같은 위치에 추가하기 편하다

메인 메뉴 출력

  std::cout << "==================================================\n";
  std::cout << "                    메인 메뉴\n";
  std::cout << "==================================================\n";
  std::cout << "1. 상태 보기\n";
  std::cout << "2. 전투 시작\n";
  std::cout << "3. 상점 입장\n";
  std::cout << "4. 인벤토리 확인\n";
  std::cout << "5. 아이템 사용\n";
  std::cout << "6. 토벌 현황 확인\n";
  std::cout << "0. 게임 종료\n";
  std::cout << "선택 >> ";

  int menu;
  std::cin >> menu;

메인 메뉴 출력은 main() 내부에 직접 작성되어 있으며 메뉴 흐름을 한눈에 보기 쉽다

다만

출력 코드가 길어질수록 main()에 부담이 가게된다.

개인 생각으론 Log 파트로 옮기는게 메인도 깔끔해지고 좋지 않을까 싶다.


메뉴 입력 예외 처리

if (std::cin.fail())
{
    std::cin.clear();
    std::cin.ignore(100, '\n');
    std::cout << "잘못된 입력입니다.\n";
    continue;
}

숫자가 아닌 값을 입력했을 때를 대비해 예외 처리용으로 넣었다

해당 코드들의 역할

  • std::cin.fail()
    • 입력 실패 여부를 확인한다
  • std::cin.clear()
    • 실패 상태를 해제한다
  • std::cin.ignore()
    • 잘못 입력된 버퍼를 제거한다
  • continue
    • 이번 루프를 중한다고 복귀한다.

의미

콘솔 프로그램에서는 입력 오류 처리가 매우 중요하므로 이 처리가 없으면 잘못된 입력 이후 프로그렘이 계속 꼬일 수 있다.