C++/C++입문

[C++] 3. TextPRG 상점 제작

나는야 개발자 2025. 4. 1. 07:01
반응형

TextRPG 전투

- 링크

 

[C++] 2. TextRPG 전투

▶  인벤토리 추가struct _tagInventory{ int iGold;};struct _tagPlayer{ char strName[NAME_SIZE]; char strJobNAME[NAME_SIZE]; JOB eJob; int iAttackMin; int iAttackMax; int iArmorMin; int iArmorMax; int iHp; int iHpMax; int iMP; int iMPMax; int iExp; i

lhy-info.tistory.com

 

 

상점, 아이템 타입 추가

enum ITEM_TPYE
{
	IT_NONE,
	IT_WEAPON,
	IT_ARMOR,
	IT_BACK
};

enum STORE_MENU
{
	SM_NONE,
	SM_WEAPON,
	SM_ARMOR,
	SM_BACK
};

 

▶ 유저 인벤토리에 아이템 구조체 추가

#define ITEM_DESC_LENGTH 32
#define INVENTORY_MAX 20
#define STORE_WEAPON_MAX 3
#define STORE_ARMOR_MAX 3

struct _tagItem
{
	char strName[NAME_SIZE];
	char strTypeName[NAME_SIZE];
	ITEM_TPYE eType;
	int iMin;
	int iMax;
	int iPrice;
	int iSell;
	char strDesc[ITEM_DESC_LENGTH];
};

struct _tagInventory
{
	_tagItem titem[INVENTORY_MAX];
	int iItemCount;
	int iGold;
};

 

판매할 아이템 목록 추가

//상점에 판매할 아이템 목록 생성
_tagItem tStoreWeapon[STORE_WEAPON_MAX] = {};
_tagItem tStoreArmor[STORE_WEAPON_MAX] = {};

//각 아이템 정보 설정
tStoreWeapon[0].eType = IT_WEAPON;
strcpy_s(tStoreWeapon[0].strTypeName, "무기");
strcpy_s(tStoreWeapon[0].strName, "목검");
strcpy_s(tStoreWeapon[0].strDesc, "나무로 만든 검");
tStoreWeapon[0].iMin = 5;
tStoreWeapon[0].iMax = 10;
tStoreWeapon[0].iPrice = 1000;
tStoreWeapon[0].iSell = 500;

tStoreWeapon[1].eType = IT_WEAPON;
strcpy_s(tStoreWeapon[1].strTypeName, "무기");
strcpy_s(tStoreWeapon[1].strName, "철검");
strcpy_s(tStoreWeapon[1].strDesc, "철로 만든 검");
tStoreWeapon[1].iMin = 20;
tStoreWeapon[1].iMax = 30;
tStoreWeapon[1].iPrice = 5000;
tStoreWeapon[1].iSell = 4000;

tStoreWeapon[2].eType = IT_WEAPON;
strcpy_s(tStoreWeapon[2].strTypeName, "무기");
strcpy_s(tStoreWeapon[2].strName, "황금검");
strcpy_s(tStoreWeapon[2].strDesc, "황금으로 만든 검");
tStoreWeapon[2].iMin = 50;
tStoreWeapon[2].iMax = 100;
tStoreWeapon[2].iPrice = 15000;
tStoreWeapon[2].iSell = 10000;

//방어구
tStoreArmor[0].eType = IT_ARMOR;
strcpy_s(tStoreArmor[0].strTypeName, "방어구");
strcpy_s(tStoreArmor[0].strName, "나무 갑옷");
strcpy_s(tStoreArmor[0].strDesc, "나무로 만든 갑옷");
tStoreArmor[0].iMin = 5;
tStoreArmor[0].iMax = 10;
tStoreArmor[0].iPrice = 1000;
tStoreArmor[0].iSell = 500;

tStoreArmor[1].eType = IT_ARMOR;
strcpy_s(tStoreArmor[1].strTypeName, "방어구");
strcpy_s(tStoreArmor[1].strName, "철 갑옷");
strcpy_s(tStoreArmor[1].strDesc, "철로 만든 갑옷");
tStoreArmor[1].iMin = 20;
tStoreArmor[1].iMax = 30;
tStoreArmor[1].iPrice = 5000;
tStoreArmor[1].iSell = 4000;

tStoreArmor[2].eType = IT_ARMOR;
strcpy_s(tStoreArmor[2].strTypeName, "방어구");
strcpy_s(tStoreArmor[2].strName, "황금 갑옷");
strcpy_s(tStoreArmor[2].strDesc, "황금으로 만든 갑옷");
tStoreArmor[2].iMin = 50;
tStoreArmor[2].iMax = 100;
tStoreArmor[2].iPrice = 15000;
tStoreArmor[2].iSell = 10000;

 

유저가 무기 상점에 들어왔을 경우

case SM_WEAPON:
while (true)
{
    system("cls");
    cout << "****** 무기 상점 ******" << endl;

    for (size_t i = 0; i < STORE_WEAPON_MAX; i++)
    {
        cout << i + 1 << ". 이름 : " << tStoreWeapon[i].strName << "\t 종류 : " << tStoreWeapon[i].strTypeName << endl;
        cout << "공격력 : " << tStoreWeapon[i].iMin << " - " << tStoreWeapon[i].iMax << endl;
        cout << "판매가격 : " << tStoreWeapon[i].iPrice << "\t구매가격 : " << tStoreWeapon[i].iSell << endl;
        cout << "설명 : " << tStoreWeapon[i].strDesc << endl << endl;
    }

    cout << STORE_WEAPON_MAX + 1 << ". 뒤로가기" << endl;
    cout << "보유금액 : " << tPlayer.tInventory.iGold << " GOLD" << endl;
    cout << "남은 공간 : " << INVENTORY_MAX - tPlayer.tInventory.iItemCount << endl;
    cout << "구입할 아이템을 선택하세요 : ";
    cin >> imenu;

    if (cin.fail())
    {
        cin.clear();
        cin.ignore(1024, '\n');
        continue;
    }
    else if (imenu == STORE_WEAPON_MAX + 1)
    {
        break;
    }
    else if (imenu < 1 || imenu > STORE_WEAPON_MAX + 1)
    {
        cout << "잘못 선택하였습니다." << endl;
        system("pause");
        continue;
    }

    //상점 판매목록 배열의 인덱스를 구해준다
    int iWeaponIndex = imenu - 1;

    //인벤토리가 꽉 찼는지 검사
    if (tPlayer.tInventory.iItemCount == INVENTORY_MAX)
    {
        cout << "가방이 꽉 찼습니다." << endl;
        system("pause");
        continue;
    }

    //돈이 부족할 경우
    else if (tPlayer.tInventory.iGold < tStoreWeapon[iWeaponIndex].iPrice)
    {
        cout << "보유 금액이 부족합니다." << endl;
        system("pause");
        continue;
    }

    // 처음에 iItemCount는 하나도 추가되어 있지 않기 때문에 0으로 초기화 되어 있으므로 0번 인덱스에 구매한 아이템을 추가하게 된다. 그리고 카운트가 1이 된다.
    //다음번에 추가할때는 1번 인덱스에 추가하게 된다.
    tPlayer.tInventory.titem[tPlayer.tInventory.iItemCount] = tStoreWeapon[iWeaponIndex];
    ++tPlayer.tInventory.iItemCount;

    //골드 차감
    tPlayer.tInventory.iGold -= tStoreWeapon[iWeaponIndex].iPrice;

    cout << tStoreWeapon[iWeaponIndex].strName << " 아이템을 구매하였습니다." << endl;
    system("pause");
}
break;

 

 유저가 방어구 상점에 들어왔을 경우

case SM_ARMOR:
while (true)
{
    system("cls");
    cout << "****** 방어구 상점 ******" << endl;

    for (size_t i = 0; i < STORE_ARMOR_MAX; i++)
    {
        cout << i + 1 << ". 이름 : " << tStoreArmor[i].strName << "\t 종류 : " << tStoreArmor[i].strTypeName << endl;
        cout << "공격력 : " << tStoreArmor[i].iMin << " - " << tStoreArmor[i].iMax << endl;
        cout << "판매가격 : " << tStoreArmor[i].iPrice << "\t구매가격 : " << tStoreArmor[i].iSell << endl;
        cout << "설명 : " << tStoreArmor[i].strDesc << endl << endl;
    }

    cout << STORE_ARMOR_MAX + 1 << ". 뒤로가기" << endl;
    cout << "보유금액 : " << tPlayer.tInventory.iGold << " GOLD" << endl;
    cout << "남은 공간 : " << INVENTORY_MAX - tPlayer.tInventory.iItemCount << endl;
    cout << "구입할 아이템을 선택하세요 : ";
    cin >> imenu;

    if (cin.fail())
    {
        cin.clear();
        cin.ignore(1024, '\n');
        continue;
    }
    else if (imenu == STORE_ARMOR_MAX + 1)
    {
        break;
    }
    else if (imenu < 1 || imenu > STORE_ARMOR_MAX + 1)
    {
        cout << "잘못 선택하였습니다." << endl;
        system("pause");
        continue;
    }

    //상점 판매목록 배열의 인덱스를 구해준다
    int iarmorindex = imenu - 1;

    //인벤토리가 꽉 찼는지 검사
    if (tPlayer.tInventory.iItemCount == INVENTORY_MAX)
    {
        cout << "가방이 꽉 찼습니다." << endl;
        system("pause");
        continue;
    }

    //돈이 부족할 경우
    else if (tPlayer.tInventory.iGold < tStoreArmor[iarmorindex].iPrice)
    {
        cout << "보유 금액이 부족합니다." << endl;
        system("pause");
        continue;
    }

    // 처음에 iItemCount는 하나도 추가되어 있지 않기 때문에 0으로 초기화 되어 있으므로 0번 인덱스에 구매한 아이템을 추가하게 된다. 그리고 카운트가 1이 된다.
    //다음번에 추가할때는 1번 인덱스에 추가하게 된다.
    tPlayer.tInventory.titem[tPlayer.tInventory.iItemCount] = tStoreArmor[iarmorindex];
    ++tPlayer.tInventory.iItemCount;

    //골드 차감
    tPlayer.tInventory.iGold -= tStoreArmor[iarmorindex].iPrice;

    cout << tStoreArmor[iarmorindex].strName << " 아이템을 구매하였습니다." << endl;
    system("pause");
}
break;

 

 

인벤토리에서 유저가 구매한 상품의 정보 보여주기

case MM_INVENTORY:
system("cls");
cout << "****** 정보 ******" << endl;
cout << "이름 : " << tPlayer.strName << "\t직업 : " << tPlayer.strJobNAME << endl;
cout << "레벨 : " << tPlayer.iLevel << "\t경험치 : " << tPlayer.iExp << endl;
cout << "공격력 : " << tPlayer.iAttackMax << " /  " << tPlayer.iAttackMax << endl;
cout << "방어력 : " << tPlayer.iArmorMax << " / " << tPlayer.iArmorMax << endl;
cout << "체력 : " << tPlayer.iHp << " / " << tPlayer.iHpMax << endl;
cout << "마나 : " << tPlayer.iMP << " / " << tPlayer.iMPMax << endl;
cout << "보유 골드 : " << tPlayer.tInventory.iGold << endl;

cout << "****** 가방 ******" << endl;
for (int i = 0; i < tPlayer.tInventory.iItemCount; i++)
{
    cout << i + 1 << ". 이름 : " << tPlayer.tInventory.titem[i].strName << "\t 종류 : " << tPlayer.tInventory.titem[i].strTypeName << endl;
    cout << "공격력 : " << tPlayer.tInventory.titem[i].iMin << " - " << tPlayer.tInventory.titem[i].iMax << endl;
    cout << "판매가격 : " << tPlayer.tInventory.titem[i].iPrice << "\t구매가격 : " << tPlayer.tInventory.titem[i].iSell << endl;
    cout << "설명 : " << tPlayer.tInventory.titem[i].strDesc << endl << endl;
}
system("pause");
break;

 

 전체코드

#include <iostream>
#include <time.h>

using namespace std;

enum MAIN_MENU
{
	MM_NONE,
	MM_MAP,
	MM_STORE,
	MM_INVENTORY,
	MM_EXIT
};

enum MM_TYPE
{
	MT_NONE,
	MT_EASY,
	MT_NORMAL,
	MT_HARD,
	MT_BACK
};

enum JOB
{
	JOB_NONE,
	JOB_KNIGHT,
	JOB_ARCHER,
	JOB_WIZARD,
	JOB_END
};

#define NAME_SIZE 32
#define ITEM_DESC_LENGTH 32
#define INVENTORY_MAX 20
#define STORE_WEAPON_MAX 3
#define STORE_ARMOR_MAX 3

enum ITEM_TPYE
{
	IT_NONE,
	IT_WEAPON,
	IT_ARMOR,
	IT_BACK
};

enum STORE_MENU
{
	SM_NONE,
	SM_WEAPON,
	SM_ARMOR,
	SM_BACK
};
struct _tagItem
{
	char strName[NAME_SIZE];
	char strTypeName[NAME_SIZE];
	ITEM_TPYE eType;
	int iMin;
	int iMax;
	int iPrice;
	int iSell;
	char strDesc[ITEM_DESC_LENGTH];
};

struct _tagInventory
{
	_tagItem titem[INVENTORY_MAX];
	int iItemCount;
	int iGold;
};

struct _tagPlayer
{
	char strName[NAME_SIZE];
	char strJobNAME[NAME_SIZE];
	JOB eJob;
	int iAttackMin;
	int iAttackMax;
	int iArmorMin;
	int iArmorMax;
	int iHp;
	int iHpMax;
	int iMP;
	int iMPMax;
	int iExp;
	int iLevel;
	_tagInventory tInventory;
};

struct _tagMonster
{
	char strName[NAME_SIZE];
	int iAttackMin;
	int iAttackMax;
	int iArmorMin;
	int iArmorMax;
	int iHp;
	int iHpMax;
	int iMP;
	int iMPMax;
	int iExp;
	int iLevel;
	int iGoleMin;
	int iGoleMax;
};

enum BATTLE
{
	BATTLE_NONE,
	BATTLE_ATTACK,
	BATTLE_BACK,
};

int main()
{
	srand((unsigned int)time(0));
	//게임 시작할때 플레이어 정보 설정

	_tagPlayer tPlayer = {};

	//이름 설정
	cout << "이름 : ";
	//끝까지 문자열을 다 채워버리면 null을 인식 못하기 때문
	cin.getline(tPlayer.strName, NAME_SIZE - 1);


	//직업 설정 
	int iJob = JOB_NONE;
	while (iJob == JOB_NONE)
	{
		system("cls");
		cout << "1. 기사" << endl;
		cout << "2. 궁수" << endl;
		cout << "3. 마법사" << endl;
		cout << "직업을 선택하세요 : ";
		cin >> iJob;

		if (cin.fail())
		{
			cin.clear();
			cin.ignore(1024, '\n');
			continue;
		}
		else if (iJob <= JOB_NONE || iJob >= JOB_END)
		{
			iJob = JOB_NONE;
		}

		//직업 이름
		tPlayer.eJob = (JOB)iJob;
		tPlayer.iLevel = 1;
		tPlayer.iExp = 0;
		tPlayer.tInventory.iGold = 10000;


		switch (tPlayer.eJob)
		{
		case JOB_KNIGHT:
			strcpy_s(tPlayer.strJobNAME, "기사");
			tPlayer.iAttackMin = 5;
			tPlayer.iAttackMax = 10;
			tPlayer.iArmorMin = 15;
			tPlayer.iArmorMin = 20;
			tPlayer.iHpMax = 500;
			tPlayer.iHp = 500;
			tPlayer.iMP = 100;
			tPlayer.iMPMax = 100;
			break;
		case JOB_ARCHER:
			strcpy_s(tPlayer.strJobNAME, "궁수");
			tPlayer.iAttackMin = 10;
			tPlayer.iAttackMax = 15;
			tPlayer.iArmorMin = 10;
			tPlayer.iArmorMin = 15;
			tPlayer.iHpMax = 400;
			tPlayer.iHp = 400;
			tPlayer.iMP = 200;
			tPlayer.iMPMax = 200;
			break;
		case JOB_WIZARD:
			strcpy_s(tPlayer.strJobNAME, "마법사");
			tPlayer.iAttackMin = 15;
			tPlayer.iAttackMax = 20;
			tPlayer.iArmorMin = 5;
			tPlayer.iArmorMin = 10;
			tPlayer.iHpMax = 300;
			tPlayer.iHp = 300;
			tPlayer.iMP = 300;
			tPlayer.iMPMax = 300;
			break;
		}
	}

	//몬스터 생성
	_tagMonster tMonsterArr[MT_BACK - 1] = {};

	//고블린 생성
	strcpy_s(tMonsterArr[0].strName, "고블린");
	tMonsterArr[0].iAttackMin = 20;
	tMonsterArr[0].iAttackMax = 30;
	tMonsterArr[0].iArmorMin = 2;
	tMonsterArr[0].iArmorMax = 5;
	tMonsterArr[0].iHp = 100;
	tMonsterArr[0].iHpMax = 100;
	tMonsterArr[0].iMP = 10;
	tMonsterArr[0].iMPMax = 10;
	tMonsterArr[0].iLevel = 1;
	tMonsterArr[0].iExp = 1000;
	tMonsterArr[0].iGoleMin = 500;
	tMonsterArr[0].iGoleMax = 1500;

	//트롤 생성
	strcpy_s(tMonsterArr[1].strName, "트롤");
	tMonsterArr[1].iAttackMin = 80;
	tMonsterArr[1].iAttackMax = 130;
	tMonsterArr[1].iArmorMin = 60;
	tMonsterArr[1].iArmorMax = 90;
	tMonsterArr[1].iHp = 2000;
	tMonsterArr[1].iHpMax = 2000;
	tMonsterArr[1].iMP = 100;
	tMonsterArr[1].iMPMax = 100;
	tMonsterArr[1].iLevel = 5;
	tMonsterArr[1].iExp = 7000;
	tMonsterArr[1].iGoleMin = 6000;
	tMonsterArr[1].iGoleMax = 8000;

	//드래곤 생성
	strcpy_s(tMonsterArr[2].strName, "드래곤");
	tMonsterArr[2].iAttackMin = 250;
	tMonsterArr[2].iAttackMax = 500;
	tMonsterArr[2].iArmorMin = 200;
	tMonsterArr[2].iArmorMax = 400;
	tMonsterArr[2].iHp = 30000;
	tMonsterArr[2].iHpMax = 30000;
	tMonsterArr[2].iMP = 20000;
	tMonsterArr[2].iMPMax = 20000;
	tMonsterArr[2].iLevel = 10;
	tMonsterArr[2].iExp = 30000;
	tMonsterArr[2].iGoleMin = 20000;
	tMonsterArr[2].iGoleMax = 50000;

	//상점에 판매할 아이템 목록 생성
	_tagItem tStoreWeapon[STORE_WEAPON_MAX] = {};
	_tagItem tStoreArmor[STORE_WEAPON_MAX] = {};

	//각 아이템 정보 설정
	tStoreWeapon[0].eType = IT_WEAPON;
	strcpy_s(tStoreWeapon[0].strTypeName, "무기");
	strcpy_s(tStoreWeapon[0].strName, "목검");
	strcpy_s(tStoreWeapon[0].strDesc, "나무로 만든 검");
	tStoreWeapon[0].iMin = 5;
	tStoreWeapon[0].iMax = 10;
	tStoreWeapon[0].iPrice = 1000;
	tStoreWeapon[0].iSell = 500;

	tStoreWeapon[1].eType = IT_WEAPON;
	strcpy_s(tStoreWeapon[1].strTypeName, "무기");
	strcpy_s(tStoreWeapon[1].strName, "철검");
	strcpy_s(tStoreWeapon[1].strDesc, "철로 만든 검");
	tStoreWeapon[1].iMin = 20;
	tStoreWeapon[1].iMax = 30;
	tStoreWeapon[1].iPrice = 5000;
	tStoreWeapon[1].iSell = 4000;

	tStoreWeapon[2].eType = IT_WEAPON;
	strcpy_s(tStoreWeapon[2].strTypeName, "무기");
	strcpy_s(tStoreWeapon[2].strName, "황금검");
	strcpy_s(tStoreWeapon[2].strDesc, "황금으로 만든 검");
	tStoreWeapon[2].iMin = 50;
	tStoreWeapon[2].iMax = 100;
	tStoreWeapon[2].iPrice = 15000;
	tStoreWeapon[2].iSell = 10000;

	//방어구
	tStoreArmor[0].eType = IT_ARMOR;
	strcpy_s(tStoreArmor[0].strTypeName, "방어구");
	strcpy_s(tStoreArmor[0].strName, "나무 갑옷");
	strcpy_s(tStoreArmor[0].strDesc, "나무로 만든 갑옷");
	tStoreArmor[0].iMin = 5;
	tStoreArmor[0].iMax = 10;
	tStoreArmor[0].iPrice = 1000;
	tStoreArmor[0].iSell = 500;

	tStoreArmor[1].eType = IT_ARMOR;
	strcpy_s(tStoreArmor[1].strTypeName, "방어구");
	strcpy_s(tStoreArmor[1].strName, "철 갑옷");
	strcpy_s(tStoreArmor[1].strDesc, "철로 만든 갑옷");
	tStoreArmor[1].iMin = 20;
	tStoreArmor[1].iMax = 30;
	tStoreArmor[1].iPrice = 5000;
	tStoreArmor[1].iSell = 4000;

	tStoreArmor[2].eType = IT_ARMOR;
	strcpy_s(tStoreArmor[2].strTypeName, "방어구");
	strcpy_s(tStoreArmor[2].strName, "황금 갑옷");
	strcpy_s(tStoreArmor[2].strDesc, "황금으로 만든 갑옷");
	tStoreArmor[2].iMin = 50;
	tStoreArmor[2].iMax = 100;
	tStoreArmor[2].iPrice = 15000;
	tStoreArmor[2].iSell = 10000;


	while (true)
	{
		//로비 구성
		system("cls");
		cout << "******로비******" << endl;
		cout << "1. 맵" << endl;
		cout << "2. 상점" << endl;
		cout << "3. 가방" << endl;
		cout << "4. 종료" << endl;

		cout << "메뉴를 선택하세요! : ";
		int imenu;
		cin >> imenu;

		if (cin.fail())
		{
			cin.clear();
			cin.ignore(1024, '\n');
			continue;
		}

		if (imenu == MM_EXIT)
		{
			break;
		}

		//메뉴에 따른 처리 
		switch (imenu)
		{
			//맵 선택
		case MM_MAP:
			while (true)
			{
				system("cls");
				cout << "******맵******" << endl;
				cout << "1. 쉬움" << endl;
				cout << "2. 보통" << endl;
				cout << "3. 어려움" << endl;
				cout << "4. 뒤로가기" << endl;

				cout << "난이도를 선택해 주세요 : ";
				cin >> imenu;
				if (cin.fail())
				{
					cin.clear();
					cin.ignore(1024, '\n');
					continue;
				}
				//이 if문은 맵 메뉴를 돌려주기 위한 while에 속해 있으므로 이 while문을 빠져나감
				else if (imenu == MT_BACK)
				{
					break;
				}

				//선택한 메뉴 1을 빼주면 몬스터 배열의 인덱스가 된다
				//그렇게 해서 해당 맵의 몬스터 생성
				_tagMonster tMonster = tMonsterArr[imenu - 1];


				//전투 시작
				while (true)
				{
					switch (imenu)
					{
					case MT_EASY:
						cout << "********* 쉬움 *********" << endl;
						break;
					case MT_NORMAL:
						cout << "********* 보통 *********" << endl;
						break;
					case MT_HARD:
						cout << "********* 어려움 *********" << endl;
						break;
					}

					//플레이어 정보
					cout << "********* Player *********" << endl;
					cout << "이름 : " << tPlayer.strName << "\t직업 : " << tPlayer.strJobNAME << endl;
					cout << "레벨 : " << tPlayer.iLevel << "\t경험치 : " << tPlayer.iExp << endl;
					cout << "공격력 : " << tPlayer.iAttackMax << " /  " << tPlayer.iAttackMax << endl;
					cout << "방어력 : " << tPlayer.iArmorMax << " / " << tPlayer.iArmorMax << endl;
					cout << "체력 : " << tPlayer.iHp << " / " << tPlayer.iHpMax << endl;
					cout << "마나 : " << tPlayer.iMP << " / " << tPlayer.iMPMax << endl;
					cout << "보유 골드 : " << tPlayer.tInventory.iGold << endl;

					//몬스터 정보 출력
					cout << "********* Monster *********" << endl;
					cout << "이름 : " << tMonster.strName << endl;
					cout << "레벨 : " << tMonster.iLevel << "\t획득 경험치 : " << tMonster.iExp << endl;
					cout << "공격력 : " << tMonster.iAttackMax << " /  " << tMonster.iAttackMax << endl;
					cout << "방어력 : " << tMonster.iArmorMax << " / " << tMonster.iArmorMax << endl;
					cout << "체력 : " << tMonster.iHp << " / " << tMonster.iHpMax << endl;
					cout << "마나 : " << tMonster.iMP << " / " << tMonster.iMPMax << endl;
					cout << "보유 골드 : " << tMonster.iGoleMin << " / " << tMonster.iGoleMax << endl;

					cout << "1. 공격" << endl;
					cout << "2. 도망가기" << endl;
					cout << "메뉴를 선택해 주세요 : ";
					cin >> imenu;
					system("cls");
					if (cin.fail())
					{
						cin.clear();
						cin.ignore(1024, '\n');
						continue;
					}
					else if (imenu == BATTLE_BACK)
					{
						break;
					}
					switch (imenu)
					{
					case BATTLE_ATTACK:

						//플레이어가 공격
						// 예를들어 min 5 Max15 일 경우
						// 15 - 5 + 1을하면 11이 됨
						// 11로 나눈 나머지는 0~10이 되고 여기에 min값인 5를 더하게 되면 5~15사이로 값이 나오게 됨
						int iattack = rand() % ((tPlayer.iAttackMax - tPlayer.iAttackMin + 1) + tPlayer.iAttackMin);
						int iarmor = rand() % ((tMonster.iArmorMax - tMonster.iArmorMin + 1) + tMonster.iArmorMin);
						int idamage = iattack - iarmor;

						//삼항연산자 : 조건식 ? true일때값 : flase일때 값
						idamage = idamage < 1 ? 1 : idamage;

						//몬스터 hp를 감소시킨다
						tMonster.iHp -= idamage;

						cout << tPlayer.strName << " 가 " << tMonster.strName << " 에게 " << idamage << " 피해를 입혔습니다. " << endl;

						//몬스터가 죽었을 경우
						if (tMonster.iHp <= 0)
						{
							cout << tMonster.strName << " 몬스터가 사망하였습니다." << endl;
							tPlayer.iExp += tMonster.iExp;
							int igold = rand() % ((tMonster.iGoleMax - tMonster.iGoleMin + 1) + tMonster.iGoleMin);
							tPlayer.tInventory.iGold += igold;

							//몬스터 다시 부활
							tMonster.iHp = tMonster.iHpMax;
							tMonster.iMP = tMonster.iMPMax;

							cout << tMonster.iExp << " 경험치를 획득하였습니다. " << endl;
							cout << igold << " 골드를 획득하였습니다." << endl;
							system("pause");
							break;
						}

						//몬스터가 살아있다면 몬스터가 공격
						iattack = rand() % ((tMonster.iAttackMax - tMonster.iAttackMin + 1) + tMonster.iAttackMin);
						iarmor = rand() % ((tPlayer.iArmorMax - tPlayer.iArmorMin + 1) + tPlayer.iArmorMin);
						idamage = iattack - iarmor;

						//플레이어 데미지 받음
						tPlayer.iHp -= idamage;

						cout << tMonster.strName << " 가 " << tPlayer.strName << " 에게 " << idamage << " 피해를 입혔습니다. " << endl;

						//몬스터가 죽었을 경우
						if (tPlayer.iHp <= 0)
						{
							cout << tPlayer.strName << " 플레이어가 사망하였습니다." << endl;
							int iexp = tPlayer.iExp * 0.1f;
							int igold = tPlayer.tInventory.iGold * 0.1f;
							tPlayer.iExp -= iexp;
							tPlayer.tInventory.iGold -= igold;

							cout << iexp << " 경험치를 잃었습니다. " << endl;
							cout << igold << " 골드를 잃었습니다." << endl;

							//플레이어의 hp와 mp를 회복한다
							tPlayer.iHp = tPlayer.iHpMax;
							tPlayer.iMP = tPlayer.iMPMax;
						}
						break;
					}
				}
			}
			break;
		case MM_STORE:
			while (true)
			{
				system("cls");
				cout << "******맵******" << endl;
				cout << "1. 무기 상점" << endl;
				cout << "2. 방어구 상점" << endl;
				cout << "3. 뒤로가기" << endl;
				cout << "상점을 선택하세요 : ";
				int imenu;
				cin >> imenu;
				system("cls");
				if (cin.fail())
				{
					cin.clear();
					cin.ignore(1024, '\n');
					continue;
				}
				else if (imenu == SM_BACK)
				{
					break;
				}

				switch (imenu)
				{
				case SM_WEAPON:
					while (true)
					{
						system("cls");
						cout << "****** 무기 상점 ******" << endl;

						for (size_t i = 0; i < STORE_WEAPON_MAX; i++)
						{
							cout << i + 1 << ". 이름 : " << tStoreWeapon[i].strName << "\t 종류 : " << tStoreWeapon[i].strTypeName << endl;
							cout << "공격력 : " << tStoreWeapon[i].iMin << " - " << tStoreWeapon[i].iMax << endl;
							cout << "판매가격 : " << tStoreWeapon[i].iPrice << "\t구매가격 : " << tStoreWeapon[i].iSell << endl;
							cout << "설명 : " << tStoreWeapon[i].strDesc << endl << endl;
						}

						cout << STORE_WEAPON_MAX + 1 << ". 뒤로가기" << endl;
						cout << "보유금액 : " << tPlayer.tInventory.iGold << " GOLD" << endl;
						cout << "남은 공간 : " << INVENTORY_MAX - tPlayer.tInventory.iItemCount << endl;
						cout << "구입할 아이템을 선택하세요 : ";
						cin >> imenu;

						if (cin.fail())
						{
							cin.clear();
							cin.ignore(1024, '\n');
							continue;
						}
						else if (imenu == STORE_WEAPON_MAX + 1)
						{
							break;
						}
						else if (imenu < 1 || imenu > STORE_WEAPON_MAX + 1)
						{
							cout << "잘못 선택하였습니다." << endl;
							system("pause");
							continue;
						}

						//상점 판매목록 배열의 인덱스를 구해준다
						int iWeaponIndex = imenu - 1;

						//인벤토리가 꽉 찼는지 검사
						if (tPlayer.tInventory.iItemCount == INVENTORY_MAX)
						{
							cout << "가방이 꽉 찼습니다." << endl;
							system("pause");
							continue;
						}

						//돈이 부족할 경우
						else if (tPlayer.tInventory.iGold < tStoreWeapon[iWeaponIndex].iPrice)
						{
							cout << "보유 금액이 부족합니다." << endl;
							system("pause");
							continue;
						}

						// 처음에 iItemCount는 하나도 추가되어 있지 않기 때문에 0으로 초기화 되어 있으므로 0번 인덱스에 구매한 아이템을 추가하게 된다. 그리고 카운트가 1이 된다.
						//다음번에 추가할때는 1번 인덱스에 추가하게 된다.
						tPlayer.tInventory.titem[tPlayer.tInventory.iItemCount] = tStoreWeapon[iWeaponIndex];
						++tPlayer.tInventory.iItemCount;

						//골드 차감
						tPlayer.tInventory.iGold -= tStoreWeapon[iWeaponIndex].iPrice;

						cout << tStoreWeapon[iWeaponIndex].strName << " 아이템을 구매하였습니다." << endl;
						system("pause");
					}
					break;
				case SM_ARMOR:
					while (true)
					{
						system("cls");
						cout << "****** 방어구 상점 ******" << endl;

						for (size_t i = 0; i < STORE_ARMOR_MAX; i++)
						{
							cout << i + 1 << ". 이름 : " << tStoreArmor[i].strName << "\t 종류 : " << tStoreArmor[i].strTypeName << endl;
							cout << "공격력 : " << tStoreArmor[i].iMin << " - " << tStoreArmor[i].iMax << endl;
							cout << "판매가격 : " << tStoreArmor[i].iPrice << "\t구매가격 : " << tStoreArmor[i].iSell << endl;
							cout << "설명 : " << tStoreArmor[i].strDesc << endl << endl;
						}

						cout << STORE_ARMOR_MAX + 1 << ". 뒤로가기" << endl;
						cout << "보유금액 : " << tPlayer.tInventory.iGold << " GOLD" << endl;
						cout << "남은 공간 : " << INVENTORY_MAX - tPlayer.tInventory.iItemCount << endl;
						cout << "구입할 아이템을 선택하세요 : ";
						cin >> imenu;

						if (cin.fail())
						{
							cin.clear();
							cin.ignore(1024, '\n');
							continue;
						}
						else if (imenu == STORE_ARMOR_MAX + 1)
						{
							break;
						}
						else if (imenu < 1 || imenu > STORE_ARMOR_MAX + 1)
						{
							cout << "잘못 선택하였습니다." << endl;
							system("pause");
							continue;
						}

						//상점 판매목록 배열의 인덱스를 구해준다
						int iarmorindex = imenu - 1;

						//인벤토리가 꽉 찼는지 검사
						if (tPlayer.tInventory.iItemCount == INVENTORY_MAX)
						{
							cout << "가방이 꽉 찼습니다." << endl;
							system("pause");
							continue;
						}

						//돈이 부족할 경우
						else if (tPlayer.tInventory.iGold < tStoreArmor[iarmorindex].iPrice)
						{
							cout << "보유 금액이 부족합니다." << endl;
							system("pause");
							continue;
						}

						// 처음에 iItemCount는 하나도 추가되어 있지 않기 때문에 0으로 초기화 되어 있으므로 0번 인덱스에 구매한 아이템을 추가하게 된다. 그리고 카운트가 1이 된다.
						//다음번에 추가할때는 1번 인덱스에 추가하게 된다.
						tPlayer.tInventory.titem[tPlayer.tInventory.iItemCount] = tStoreArmor[iarmorindex];
						++tPlayer.tInventory.iItemCount;

						//골드 차감
						tPlayer.tInventory.iGold -= tStoreArmor[iarmorindex].iPrice;

						cout << tStoreArmor[iarmorindex].strName << " 아이템을 구매하였습니다." << endl;
						system("pause");
					}
					break;
				}
			}
			break;
		case MM_INVENTORY:
			system("cls");
			cout << "****** 정보 ******" << endl;
			cout << "이름 : " << tPlayer.strName << "\t직업 : " << tPlayer.strJobNAME << endl;
			cout << "레벨 : " << tPlayer.iLevel << "\t경험치 : " << tPlayer.iExp << endl;
			cout << "공격력 : " << tPlayer.iAttackMax << " /  " << tPlayer.iAttackMax << endl;
			cout << "방어력 : " << tPlayer.iArmorMax << " / " << tPlayer.iArmorMax << endl;
			cout << "체력 : " << tPlayer.iHp << " / " << tPlayer.iHpMax << endl;
			cout << "마나 : " << tPlayer.iMP << " / " << tPlayer.iMPMax << endl;
			cout << "보유 골드 : " << tPlayer.tInventory.iGold << endl;

			cout << "****** 가방 ******" << endl;
			for (int i = 0; i < tPlayer.tInventory.iItemCount; i++)
			{
				cout << i + 1 << ". 이름 : " << tPlayer.tInventory.titem[i].strName << "\t 종류 : " << tPlayer.tInventory.titem[i].strTypeName << endl;
				cout << "공격력 : " << tPlayer.tInventory.titem[i].iMin << " - " << tPlayer.tInventory.titem[i].iMax << endl;
				cout << "판매가격 : " << tPlayer.tInventory.titem[i].iPrice << "\t구매가격 : " << tPlayer.tInventory.titem[i].iSell << endl;
				cout << "설명 : " << tPlayer.tInventory.titem[i].strDesc << endl << endl;
			}
			system("pause");
			break;
		default:
			break;
		}
	}
	return 0;
}
반응형

'C++ > C++입문' 카테고리의 다른 글

[C++] 5. TextRPG 아이템 능력치 적용  (0) 2025.04.04
[C++] 4. TextRPG 아이템 장착  (0) 2025.04.03
[C++] 2. TextRPG 전투  (0) 2025.03.30
[C++] 1. TextRPG  (0) 2025.03.28
[C++] 구조체와 문자열  (0) 2025.03.28