[Day 6] Status Window with C++

베리투스·2025년 8월 11일

TIL: Today I Learned

목록 보기
14/93

📌 목표

  • 스탯 관리 시스템을 제작
    • HP와 MP를 입력받고, HP나 MP가 하나라도 50 이하의 숫자를 입력받을 경우 다시 입력받습니다.
    • HP와 MP에 값을 입력받은 후 공격력과 방어력을 입력받습니다. 공격력이나 방어력이 하나라도 0 이하의 숫자를 입력받을 경우 다시 입력 받습니다.
      1. HP 회복 2. MP 회복 3. HP 강화 4. MP 강화 5. 공격 스킬 사용 6. 필살기 사용 7. 프로그램 종료
    • 선택지를 출력한 후, int형 정수 하나를 입력받아서 해당 선택지를 실행합니다.

💻 코드

/*
====================================================================
RPG 스탯 관리 게임 시스템
====================================================================
이 프로그램은 간단한 RPG 캐릭터의 스탯을 관리하는 게임입니다.
사용자는 포션을 사용하고, 스탯을 강화하며, 스킬을 사용할 수 있습니다.
====================================================================
*/

// 라이브러리 포함 (다른 사람이 만든 코드 가져오기)
#include <iostream>  // 콘솔 입출력 기능 (cout, cin 등)
#include <limits>    // 입력 버퍼 처리를 위한 기능

// 네임스페이스 사용 선언
// std:: 를 매번 쓰지 않고 cout, cin 등을 바로 사용할 수 있게 해줍니다
using namespace std;

// 함수 선언부 (Function Prototype)
// 컴파일러에게 "이런 함수들이 나중에 나올 예정이야"라고 미리 알려주는 부분
void setPotion(int count, int* p_HPPotion, int* p_MPPotion);  // 포션 개수 설정
void showStatus(int hpPotion, int mpPotion, int status[]);     // 현재 상태 표시
void healHP(int* p_HPPotion, int status[]);                    // HP 회복
void healMP(int* p_MPPotion, int status[]);                    // MP 회복  
void enhanceHP(int status[]);                                  // HP 강화
void enhanceMP(int status[]);                                  // MP 강화
void useAttackSkill(int status[]);                             // 공격 스킬 사용
void useUltimateSkill(int status[]);                           // 필살기 사용
int getValidInput();                                           // 안전한 입력받기

// 안전한 숫자 입력을 위한 함수
// 사용자가 문자를 입력했을 때 프로그램이 멈추지 않도록 보호해주는 함수
int getValidInput() {
    int value;  // 입력받을 숫자를 저장할 변수
    
    // 올바른 숫자가 입력될 때까지 반복
    while (!(cin >> value)) {  // cin >> value가 실패하면 (문자가 입력되면)
        cout << "유효하지 않은 입력입니다. 숫자를 입력해주세요: ";
        cin.clear();  // 에러 상태를 초기화
        cin.ignore(numeric_limits<streamsize>::max(), '\n');  // 입력 버퍼를 비움
    }
    return value;  // 제대로 입력받은 숫자를 돌려줌
}

// 메인 함수 - 프로그램이 시작되는 곳
int main() {
    /*
    =======================================
    게임 데이터 초기화
    =======================================
    */
    
    // 캐릭터의 스탯을 저장하는 배열 (크기 4, 모두 0으로 시작)
    int status[4] = {0, 0, 0, 0}; 
    // status[0] = HP (체력)
    // status[1] = MP (마나)  
    // status[2] = 공격력
    // status[3] = 방어력
    
    // 포션 개수를 저장하는 변수들
    int HPPotion = 0;  // HP 포션 개수
    int MPPotion = 0;  // MP 포션 개수
    
    // 게임 시작 시 포션 5개씩 무료 지급! 
    // 여기서 &를 붙이는 이유: 포인터(주소)를 넘겨주어야 함수에서 값을 바꿀 수 있음
    setPotion(5, &HPPotion, &MPPotion);
    
    /*
    =======================================
    캐릭터 스탯 입력받기
    =======================================
    */
    
    // HP와 MP 입력받기 (50보다 커야 함!)
    // do-while 루프: 조건에 맞을 때까지 계속 반복
    do {
        cout << "HP를 입력하세요 (50보다 큰 값): ";
        status[0] = getValidInput();  // 안전하게 HP 입력받기
        cout << "MP를 입력하세요 (50보다 큰 값): ";
        status[1] = getValidInput();  // 안전하게 MP 입력받기
        
        // 만약 HP나 MP 중 하나라도 50 이하라면?
        if (status[0] <= 50 || status[1] <= 50) {
            cout << "HP와 MP는 모두 50보다 커야 합니다. 다시 입력해주세요." << endl;
        }
    } while (status[0] <= 50 || status[1] <= 50);  // 조건: 둘 다 50보다 클 때까지 반복
    
    // 공격력과 방어력 입력받기 (0보다 커야 함!)
    do {
        cout << "공격력을 입력하세요 (0보다 큰 값): ";
        status[2] = getValidInput();  // 안전하게 공격력 입력받기
        cout << "방어력을 입력하세요 (0보다 큰 값): ";
        status[3] = getValidInput();  // 안전하게 방어력 입력받기
        
        // 만약 공격력이나 방어력 중 하나라도 0 이하라면?
        if (status[2] <= 0 || status[3] <= 0) {
            cout << "공격력과 방어력은 모두 0보다 커야 합니다. 다시 입력해주세요." << endl;
        }
    } while (status[2] <= 0 || status[3] <= 0);  // 조건: 둘 다 0보다 클 때까지 반복
    
    // 게임 시작 인사말
    cout << "\n*** 스탯 관리 시스템을 시작합니다! ***" << endl;
    
    /*
    =======================================
    게임 메인 루프 (무한 반복)
    =======================================
    */
    
    // while(true): 사용자가 7번(종료)을 선택할 때까지 계속 반복
    while (true) {
        
        // 현재 캐릭터 상태를 화면에 보여주기
        showStatus(HPPotion, MPPotion, status);
        
        // 게임 메뉴 출력
        cout << "\n=== 스탯 관리 메뉴 ===" << endl;
        cout << "1. HP 회복" << endl;        // HP 포션 사용 → HP +20
        cout << "2. MP 회복" << endl;        // MP 포션 사용 → MP +20
        cout << "3. HP 강화" << endl;        // HP를 2배로 만들기
        cout << "4. MP 강화" << endl;        // MP를 2배로 만들기
        cout << "5. 공격 스킬 사용" << endl;  // MP 50 소모하는 스킬
        cout << "6. 필살기 사용" << endl;    // MP의 50% 소모하는 강력한 스킬
        cout << "7. 프로그램 종료" << endl;   // 게임 끝내기
        cout << "선택: ";
        
        // 사용자의 선택을 안전하게 입력받기
        int choice = getValidInput();
        
        // 선택에 따라 해당하는 기능 실행하기
        switch (choice) {
            case 1:  // HP 회복 선택
                healHP(&HPPotion, status);  // HP 회복 함수 호출
                break;
            case 2:  // MP 회복 선택
                healMP(&MPPotion, status);  // MP 회복 함수 호출
                break;
            case 3:  // HP 강화 선택
                enhanceHP(status);  // HP 강화 함수 호출
                break;
            case 4:  // MP 강화 선택
                enhanceMP(status);  // MP 강화 함수 호출
                break;
            case 5:  // 공격 스킬 사용 선택
                useAttackSkill(status);  // 공격 스킬 함수 호출
                break;
            case 6:  // 필살기 사용 선택
                useUltimateSkill(status);  // 필살기 함수 호출
                break;
            case 7:  // 종료 선택
                cout << "프로그램을 종료합니다." << endl;
                return 0;  // 프로그램 종료
            default:
                cout << "잘못된 선택입니다. 1~7 사이의 숫자를 입력해주세요." << endl;
                break;
        }
    }
    return 0;
}

/*
====================================================================
함수 정의부 (Function Definition)
====================================================================
*/

// 포션 개수를 설정하는 함수
void setPotion(int count, int* p_HPPotion, int* p_MPPotion) {
    *p_HPPotion = count;
    *p_MPPotion = count;
}

// 현재 캐릭터 상태를 출력하는 함수
void showStatus(int hpPotion, int mpPotion, int status[]) {
    cout << "\n--- 현재 캐릭터 상태 ---" << endl;
    cout << "HP: " << status[0] << " (HP 포션: " << hpPotion << "개)" << endl;
    cout << "MP: " << status[1] << " (MP 포션: " << mpPotion << "개)" << endl;  
    cout << "공격력: " << status[2] << endl;
    cout << "방어력: " << status[3] << endl;
    cout << "-------------------------" << endl;
}

// HP 포션을 사용해서 HP를 회복하는 함수
void healHP(int* p_HPPotion, int status[]) {
    if (*p_HPPotion > 0) {
        status[0] += 20;
        (*p_HPPotion)--;
        cout << "HP 포션을 사용했습니다! HP가 20 증가했습니다." << endl;
    } else {
        cout << "HP 포션이 없습니다!" << endl;
    }
}

// MP 포션을 사용해서 MP를 회복하는 함수  
void healMP(int* p_MPPotion, int status[]) {
    if (*p_MPPotion > 0) {
        status[1] += 20;
        (*p_MPPotion)--;
        cout << "MP 포션을 사용했습니다! MP가 20 증가했습니다." << endl;
    } else {
        cout << "MP 포션이 없습니다!" << endl;
    }
}

// HP를 2배로 강화하는 함수
void enhanceHP(int status[]) {
    status[0] *= 2;
    cout << "HP 강화를 실행했습니다! HP가 2배로 증가했습니다." << endl;
}

// MP를 2배로 강화하는 함수
void enhanceMP(int status[]) {
    status[1] *= 2;
    cout << "MP 강화를 실행했습니다! MP가 2배로 증가했습니다." << endl;
}

// 공격 스킬을 사용하는 함수
void useAttackSkill(int status[]) {
    if (status[1] >= 50) {
        status[1] -= 50;
        cout << "공격 스킬을 사용했습니다! MP 50을 소모했습니다." << endl;
    } else {
        cout << "MP가 부족합니다! (필요 MP: 50)" << endl;
    }
}

// 필살기를 사용하는 함수
void useUltimateSkill(int status[]) {
    if (status[1] > 0) {
        int mpCost = status[1] / 2;
        status[1] -= mpCost;
        cout << "필살기를 사용했습니다! MP " << mpCost << "를 소모했습니다." << endl;
    } else {
        cout << "MP가 없어서 필살기를 사용할 수 없습니다!" << endl;
    }
}

📝 결과



✅ 코드 리뷰

어려웠던 점설명
*&의 차이 혼동포인터를 사용할 때 값이 바뀌지 않아 원인을 찾는 데 시간이 걸렸음
주소를 넘겨줘야 하는 이유 이해 지연함수 호출 시 값이 아닌 주소를 넘겨야 하는 이유를 이해하는 데 시간이 걸렸음
cin.clear()cin.ignore() 사용법 생소입력 오류 처리 방법을 처음 접해서 동작 원리를 이해하는 데 어려움이 있었음
입력 버퍼 미처리로 인한 무한 루프버퍼를 비워주지 않아 프로그램이 무한 반복되는 문제를 경험했음
profile
Shin Ji Yong // Unreal Engine 5 공부중입니다~

0개의 댓글