강께르의 개발일지
[C++] 상점 기능 구현 본문
1. 이것은 무엇인가?
- 플레이어의 인벤토리와 상점 간의 상호작용을 구현해보았다. 일반적으로 상점에서 할 수있는 매매 기능과 인벤토리에서 물건을 확인하고 원하는 장비로 착용할 수 있게 하는 기능을 구현한 것이다.
2. 요구 사항
- 상점에서 사고 팔기가 가능하도록 기능을 구현
- 사고 파는 과정에서 플레이어의 돈의 증감이 있도록 한다.
- 갯수는 무한정으로 설정하는 것이 아닌 한정적인 수량으로 사고 파는 것으로 한다.
- 인벤토리에 물건이 어떤 것이 있는지 볼 수 있도록 한다.
- 장비를 확인하고 원하는 장비를 인벤토리의 물건과 바꿔 착용할 수 있게 한다.
- 이에 대한 기능을 구현할 때, vector로 이용해 데이터를 관리하도록 한다.
3. 클래스 구성
- 클래스는 기본적으로 플레이어 클래스, 인벤토리 클래스, 상점 클래스, 아이템 클래스는 있어야 한다.
- 아이템 클래스는 게임에서 아이템 단 하나를 표현하기 위한 클래스이다. 아이템 클래스의 객체는 아이템 하나를 표현할 것이며, 그에 대한 정보는 멤버변수로 표현하여 가질 것이다.
- 인벤토리 클래스는 아이템을 자료형으로 하는 vector를 멤버변수로 가져 그것을 '플레이어의 물건을 넣는 가방'이라고 할 것이다. 착용하고 있는 장비에 해당되는 아이템 클래스 자료형 멤버변수를 갖는다.
- 플레이어 클래스는 돈과 인벤토리 클래스의 객체를 멤버 변수로 갖는다. 상점 클래스의 기능을 통해 돈의 증가와 감소가 결정될 것이다.
- 상점 클래스는 아이템을 자료형으로 하는 vector를 멤버변수로 가져 그것을 '상점에 진열한 아이템들'이라고 할 것이다.
- 이를 클래스들의 상호작용을 관리하고 클래스의 함수를 호출할 또 다른 클래스를 정의할 것이다.
4. 새로 알게 된 점
- 배열이 아닌 vector를 이용해 데이터를 저장한다는 것을 익히는 시간이었다. vector가 제공하는 기능이 유용하다는 것을 느꼈다. vector의 크기를 신경써가면서 할 필요가 없다. 반복자를 통해서 배열처럼 포인터 연산하여 접근할 수 있다는 거에 배우는 것도 어려움이 없었다.
- 같은 클래스 내에 있는 멤버변수인 객체들의 상호작용을 다루어봤다. 이번 기능 구현을 통해 상점이 갖는 vector와 플레이어의 인벤토리가 갖는 vector와의 데이터가 오고가는 것이 가장 중요한 핵심이었는데 이 객체의 상호작용을 이루기 위해 vector의 멤버함수를 익히기도 했고, Get, Set으로 캡슐화를 이룬 데이터 접근까지 만만치 않았다.
- vector끼리의 상호작용이다보니 인덱스 접근에 유의해야했다. 크기에 대해 신경쓰지 않아도 되는 것이지, 무의미한 인덱스에 접근하는 일은 컴파일러가 여전히 해주지 않는 일이다. 디버깅의 주된 일은 어느 함수에서 어느 인덱스에 잘못 접근했는지 찾는 일이었다. 아무래도 상점 vector와 인벤토리 vector가 가지는 요소는 위치랑 값이 전혀 다르기에 손이 많이 갈 수 밖에 없었다.
5. 코드
- 이번에는 코드 안에 주석으로 함수와 변수 설명을 첨언했으니 그것을 참고하면 되겠다.
5-1. Header.h
#pragma once
#include<iostream>
#include<Windows.h>
#include<string>
#include<vector>
using std::vector;
using std::string;
// 플레이어의 위치를 구분할 열거자
enum class LOCATION
{
LOCATION_TOWN,
LOCATION_SHOP,
LOCATION_INVENTORY
};
// 상점에서의 행동을 구분할 열거자
enum class SHOP
{
SHOP_TOWN,
SHOP_BUY,
SHOP_SELL
};
// 아이템의 타입을 구분할 열거자
enum class ITEM
{
ITEM_EMPTY,
ITEM_WEAPON,
ITEM_ARMOR,
ITEM_ACCESSORY
};
// 인벤토리에서의 행동을 구분할 열거자
enum class INVENTORY
{
INVENTORY_TOWN,
INVENTORY_SHOWBAG,
INVENTORY_EQUIP,
INVENTORY_SHOWSTAT
};
5-2. MainGame.h
#pragma once
#include"Header.h"
#include"Player.h"
#include"Shop.h"
class MainGame
{
private:
Player* m_player; // 플레이어
Shop* m_shop; // 상점
int m_mainSelectNum; // MainGame 클래스의 함수 내에서 선택을 저장할 변수
public:
MainGame();
~MainGame();
Player* GetPlayer() { return m_player; }
Shop* GetShop() { return m_shop; }
void Update();
void ShowMainPage();
void ShowShopPage();
void ShowInventoryPage();
};
5-3. MainGame.cpp
#pragma once
#include"Header.h"
#include"Player.h"
#include"Shop.h"
class MainGame
{
private:
Player* m_player; // 플레이어
Shop* m_shop; // 상점
int m_mainSelectNum; // MainGame 클래스의 함수 내에서 선택을 저장할 변수
public:
MainGame();
~MainGame();
Player* GetPlayer() { return m_player; }
Shop* GetShop() { return m_shop; }
void Update();
void ShowMainPage();
void ShowShopPage();
void ShowInventoryPage();
};
5-4. Shop.h
#pragma once
#include"Header.h"
#include"Player.h"
#include"Item.h"
class Shop
{
private:
vector<Item> m_vItem; // 상점에 진열된 아이템을 저장할 vector
vector<Item>::iterator m_viItem; // 위 vector의 반복자
int m_itemCount; // 진열된 아이템의 갯수를 저장할 변수
int m_shopSelectNum; // 상점 클래스의 함수 내에서 선택을 저장할 변수
public:
Shop();
void ShowShopItem();
void ShopBuyItemPage(Player*);
void ShopSellItemPage(Player*);
void BuyItem(int, Player*);
void SellItem(int, Player*);
int IsItemExist(const string);
};
5-5. Shop.cpp
#include "Shop.h"
// 생성자로 인한 초기화, 상점의 아이템이 될 item 객체를 동적으로 생성해
// 멤버변수 m_vItem에 요소를 하나씩 할당한다.
Shop::Shop() : m_itemCount(0), m_shopSelectNum((int)SHOP::SHOP_TOWN)
{
Item inputItem1(ITEM::ITEM_WEAPON, "평범한 철제 장검", 10, 5,
"어느 상점에서나 살 수 있는 장검", 10);
Item inputItem2(ITEM::ITEM_WEAPON, "바스타드 소드", 30, 20,
"황무지에서 경험을 쌓은 호인들의 무기", 5);
Item inputItem3(ITEM::ITEM_WEAPON, "엑스칼리버", 100, 50,
"선택 받은 자만이 뽑을 수 있다던 그 검", 1);
Item inputItem4(ITEM::ITEM_ARMOR, "가죽 갑옷", 10, 10,
"탄탄한 가죽으로 만든 갑옷", 10);
Item inputItem5(ITEM::ITEM_ACCESSORY, "마법 진주 목걸이", 25, 15,
"특별한 진주로 세공한 목걸이", 8);
m_vItem.push_back(inputItem1);
m_vItem.push_back(inputItem2);
m_vItem.push_back(inputItem3);
m_vItem.push_back(inputItem4);
m_vItem.push_back(inputItem5);
}
// 멤버변수 m_vItem의 요소를 하나씩 참조해 Item의 ShowItemInfo()를 출력
void Shop::ShowShopItem()
{
m_itemCount = 0;
m_viItem = m_vItem.begin();
for (m_viItem; m_viItem != m_vItem.end(); ++m_viItem)
{
std::cout << "=================================================" << std::endl;
std::cout << ++m_itemCount << "번째 아이템" << std::endl;
m_viItem->ShowItemInfo();
Sleep(500);
}
std::cout << "=================================================" << std::endl;
}
// 물건 사기에 대한 출력문에 해당하는 함수
// 예외처리를 통과한 선택지만이 BuyItem 함수의 매개변수가 될 수 있다
void Shop::ShopBuyItemPage(Player* player)
{
while (true)
{
system("cls");
std::cout << "=================================================" << std::endl;
std::cout << "물건 사기" << std::endl;
ShowShopItem();
if (m_itemCount == 0)
{
std::cout << "상점 주인 : 아! 미안해요... 물건이 이젠 없어..." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "상점 메뉴로 돌아갑니다." << std::endl;
std::cout << "=================================================" << std::endl;
Sleep(1000);
return;
}
std::cout << "상점 주인 : 저희는 쓸만한 것만 들여놓습니다!" << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "플레이어의 소지금 : " << player->GetMoney() << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "어느 물건을 사시겠습니까?" << std::endl;
std::cout << "상점 메뉴로 돌아가려면 0을 입력하세요." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_shopSelectNum;
if (m_shopSelectNum != 0)
{
bool WrongSelect = ((0 > m_shopSelectNum) || (m_shopSelectNum > m_itemCount));
while (WrongSelect)
{
system("cls");
std::cout << "=================================================" << std::endl;
std::cout << "물건 사기" << std::endl;
ShowShopItem();
std::cout << "플레이어의 소지금 : " << player->GetMoney() << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "상점 주인 : 뭘 달라고 하시는 거죠? 거기엔 아무것도 없습니다!" << std::endl;
std::cout << "다시 입력하세요." << std::endl;
std::cout << "상점 메뉴로 돌아가려면 0을 입력하세요." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_shopSelectNum;
WrongSelect = ((0 > m_shopSelectNum) || (m_shopSelectNum > m_itemCount));
}
bool NotEnoughMoney = m_vItem[m_shopSelectNum - 1].GetPrice() > player->GetMoney();
if (NotEnoughMoney)
{
std::cout << "=================================================" << std::endl;
std::cout << "상점 주인 : 그냥 드릴 수는 없죠! 돈이 부족하시네요." << std::endl;
std::cout << "=================================================" << std::endl;
Sleep(1000);
}
else
BuyItem(m_shopSelectNum - 1, player);
}
else if(m_shopSelectNum == 0)
{
std::cout << "=================================================" << std::endl;
std::cout << "상점 메뉴로 돌아갑니다." << std::endl;
std::cout << "=================================================" << std::endl;
Sleep(500);
return;
}
}
}
// 물건 팔기에 대한 출력문에 해당하는 함수
// 예외처리를 통과한 선택지만이 SellItem 함수의 매개변수가 될 수 있다
void Shop::ShopSellItemPage(Player* player)
{
while (true)
{
system("cls");
std::cout << "=================================================" << std::endl;
std::cout << "물건 팔기" << std::endl;
player->GetInventory()->ShowPlayerBag();
if (player->GetInventory()->GetBagItemCount() == 0)
{
std::cout << "상점 주인 : 자네는 내가 살 물건을 가지고 오는게 좋겠어." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "상점 메뉴로 돌아갑니다." << std::endl;
std::cout << "=================================================" << std::endl;
Sleep(1000);
return;
}
std::cout << "상점 주인 : 어떤 물건을 파실 건가요!" << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "플레이어의 소지금 : " << player->GetMoney() << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "어느 물건을 파시겠습니까?" << std::endl;
std::cout << "상점 메뉴로 돌아가려면 0을 입력하세요." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_shopSelectNum;
int bagItemCount = player->GetInventory()->GetBagItemCount();
if (m_shopSelectNum != 0)
{
bool WrongSelect = ((0 > m_shopSelectNum) || (m_shopSelectNum > bagItemCount));
while (WrongSelect)
{
system("cls");
std::cout << "=================================================" << std::endl;
std::cout << "물건 팔기" << std::endl;
player->GetInventory()->ShowPlayerBag();
std::cout << "플레이어의 소지금 : " << player->GetMoney() << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "그곳엔 아이템이 없습니다." << std::endl;
std::cout << "다시 입력하세요." << std::endl;
std::cout << "상점 메뉴로 돌아가려면 0을 입력하세요." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_shopSelectNum;
WrongSelect = ((0 > m_shopSelectNum) || (m_shopSelectNum > bagItemCount));
}
SellItem(m_shopSelectNum - 1, player);
}
else if (m_shopSelectNum == 0)
{
std::cout << "=================================================" << std::endl;
std::cout << "상점 메뉴로 돌아갑니다." << std::endl;
std::cout << "=================================================" << std::endl;
Sleep(500);
return;
}
}
}
// 실질적인 물건 사기에 대한 기능을 하는 함수
// 사려고 하는 아이템이 인벤토리에 있으면 그에 맞는 갯수를 처리하고
// 플레이어의 돈을 재설정한 후, 상점의 아이템 갯수를 1개 감소시킨다.
// 만약 갯수가 0 이라면 요소를 삭제한다.
void Shop::BuyItem(int itemIdx, Player* player)
{
vector<Item>* playerBag = player->GetInventory()->GetBag();
// 사려고하는 아이템이 인벤토리에 있는가?
int existItem = player->GetInventory()->IsItemExist(m_vItem[itemIdx].GetName());
// 있다면 갯수를 1개 추가해라
if (existItem > -1)
{
playerBag->at(existItem).
SetCount(playerBag->at(existItem).GetCount() + 1);
}
// 없다면 새로 요소를 추가해라
else
{
Item* tempItem = new Item(m_vItem[itemIdx]);
tempItem->SetCount(1);
playerBag->push_back(*tempItem);
}
player->SetMoney(player->GetMoney() - m_vItem[itemIdx].GetPrice());
m_vItem[itemIdx].SetCount(m_vItem[itemIdx].GetCount() - 1);
if (m_vItem[itemIdx].GetCount() == 0)
{
m_vItem.erase(m_vItem.begin() + itemIdx);
}
}
// 실질적인 물건 팔기에 대한 기능을 하는 함수
// 팔려고 하는 아이템이 상점에 있으면 그에 맞는 갯수를 처리하고
// 플레이어의 돈을 재설정한 후, 인벤토리의 아이템 갯수를 1개 감소시킨다.
// 만약 갯수가 0 이라면 요소를 삭제한다.
void Shop::SellItem(int itemIdx, Player* player)
{
vector<Item>* playerBag = player->GetInventory()->GetBag();
int existItem = IsItemExist(playerBag->at(itemIdx).GetName());
if (existItem > -1)
{
m_vItem[existItem].SetCount(m_vItem[existItem].GetCount() + 1);
}
else
{
Item* tempItem = new Item(playerBag->at(itemIdx));
tempItem->SetCount(1);
m_vItem.push_back(*tempItem);
}
player->SetMoney(player->GetMoney() + m_vItem[itemIdx].GetPrice());
playerBag->at(itemIdx).SetCount(playerBag->at(itemIdx).GetCount() - 1);
if (playerBag->at(itemIdx).GetCount() == 0)
{
playerBag->erase(playerBag->begin() + itemIdx);
}
}
// 해당 이름을 가지는 아이템이 상점 내에 있는지 확인하는 함수
int Shop::IsItemExist(const string itemName)
{
int result = -1;
int itemCount = 0;
m_viItem = m_vItem.begin();
for (m_viItem; m_viItem != m_vItem.end(); ++m_viItem)
{
++itemCount;
if (m_viItem->GetName() == itemName)
{
result = itemCount - 1;
break;
}
}
return result;
}
5-6. Item.h
#pragma once
#include"Header.h"
class Item
{
private:
// 아이템의 정보에 대한 변수들
// 변수 이름으로 뜻을 알 수 있도록 한다.
ITEM m_itemType;
string m_name;
int m_price;
int m_ability;
string m_description;
int m_count;
public:
Item(ITEM, string, int, int, string, int);
ITEM GetType() { return m_itemType; }
void SetType(const ITEM itemType) { m_itemType = itemType; }
string GetName() { return m_name; }
void SetName(const string name) { m_name = name; }
int GetPrice() { return m_price; }
void SetPrice(const int price) { m_price = price; }
int GetAbility() { return m_ability; }
void SetAbility(const int ability) { m_ability = ability; }
string GetDescription() { return m_description; }
void SetDescription(const string description) { m_description = description; }
int GetCount() { return m_count; }
void SetCount(const int count) { m_count = count; }
void ShowItemInfo();
};
5-7. Item.cpp
#include "Item.h"
Item::Item(ITEM type, string name, int price,
int ability, string description, int count)
: m_itemType(type), m_name(name), m_price(price),
m_ability(ability), m_description(description),
m_count(count) { }
void Item::ShowItemInfo()
{
std::cout << "이름 : " << m_name << std::endl;
std::cout << "가격 : " << m_price << std::endl;
std::cout << "능력치 : " << m_ability << std::endl;
std::cout << "설명 : " << m_description << std::endl;
std::cout << "보유 갯수 : " << m_count << std::endl;
}
5-8. Player.h
#pragma once
#include"Header.h"
#include"Inventory.h"
class Player
{
private:
Inventory* m_inventory; // 인벤토리
int m_money; // 돈
int m_atk; // 플레이어의 공격력
int m_def; // 플레이어의 방어력
public:
Player();
~Player();
Inventory* GetInventory() { return m_inventory; }
int GetMoney() { return m_money; }
void SetMoney(int money) { m_money = money; }
int GetAtk() { return m_atk; }
void SetAtk(int atk) { m_atk = atk; }
int GetDef() { return m_def; }
void SetDef(int def) { m_def = def; }
void ShowStat();
};
5-9. Player.cpp
#include "Player.h"
Player::Player() : m_inventory(new Inventory()),
m_money(100), m_atk(10), m_def(5)
{ }
Player::~Player()
{
delete m_inventory;
}
void Player::ShowStat()
{
system("cls");
std::cout << "=================================================" << std::endl;
std::cout << "플레이어의 공격력 : " << m_atk << " + " << m_inventory->GetWeapon()->GetAbility() << std::endl;
std::cout << "플레이어의 방어력 : " << m_def
<< " + " << m_inventory->GetArmor()->GetAbility()
<< " + " << m_inventory->GetAccessory()->GetAbility() << std::endl;
std::cout << "=================================================" << std::endl;
}
5-10. Inventory.h
#pragma once
#include"Header.h"
#include"Item.h"
class Inventory
{
private:
vector<Item> m_vBag; // 인벤토리의 물건을 저장할 vector
vector<Item>::iterator m_viBag; // 위 vector의 반복자
// 포인터로 선언한 이유는 훗날 있을
// Item을 상속으로 구현하여 타입을 구분할 때,
// 다형성을 구현할 목적으로 미리 이렇게 만듦
Item* m_equipWeapon; // 무기를 저장할 Item 포인터
Item* m_equipArmor; // 갑옷을 저장할 Item 포인터
Item* m_equipAccessory; // 장신구를 저장할 Item 포인터
int m_bagItemCount; // 인벤토리 안의 물건의 갯수를 표현할 변수
int m_inventorySelectNum; // 인벤토리 클래스 함수 내에서의 플레이어의 선택을 저장할 변수
public:
Inventory();
~Inventory();
vector<Item>* GetBag() { return &m_vBag; }
Item* GetWeapon() { return m_equipWeapon; }
Item* GetArmor() { return m_equipArmor; }
Item* GetAccessory() { return m_equipAccessory; }
int GetBagItemCount() { return m_bagItemCount; }
void ShowPlayerBag();
void ShowPlayerEquip();
void ShowEquipText();
void ChangePlayerEquip(int);
int IsItemExist(const string);
};
5-11. Inventory.cpp
#include "Inventory.h"
// 생성자로 인한 초기화, 인벤토리의 아이템이 될 item 객체를 동적으로 생성해
// 멤버변수 m_vBag에 요소를 하나씩 할당한다. 그리고 장비에 관련된 세 변수의 객체 동적으로 생성
Inventory::Inventory() : m_bagItemCount(0), m_inventorySelectNum(0)
{
/*"맨손", 0, 0,
"사람은 죽어서 이 손으로 돌아갈거야.", 1*/
m_equipWeapon = new Item(ITEM::ITEM_WEAPON, "평범한 철제 장검", 10, 5,
"어느 상점에서나 살 수 있는 장검", 1);
m_equipArmor = new Item(ITEM::ITEM_ARMOR, "더러운 옷", 0, 0,
"처음 공장에서 만들어졌을 때는 깨끗했을거야.", 1);
m_equipAccessory = new Item(ITEM::ITEM_WEAPON, "로켓", 0, 0,
"어머니의 사진이 들어 있는 로켓", 1);
Item inputItem1(ITEM::ITEM_WEAPON, "평범한 철제 장검", 10, 5,
"어느 상점에서나 살 수 있는 장검", 1);
Item inputItem2(ITEM::ITEM_ARMOR, "가죽 갑옷", 10, 10,
"탄탄한 가죽으로 만든 갑옷", 100);
Item inputItem3(ITEM::ITEM_ACCESSORY, "마법 진주 목걸이", 25, 15,
"특별한 진주로 세공한 목걸이", 1);
Item inputItem4(ITEM::ITEM_WEAPON, "펜", 5, 1,
"칼은 펜보다 강하다.", 1);
Item inputItem5(ITEM::ITEM_ARMOR, "플레이트 아머", 100, 30,
"금속제 중 최고의 갑옷", 1);
m_vBag.push_back(inputItem1);
m_vBag.push_back(inputItem2);
m_vBag.push_back(inputItem3);
m_vBag.push_back(inputItem4);
m_vBag.push_back(inputItem5);
}
// 소멸자
Inventory::~Inventory()
{
delete m_equipWeapon;
delete m_equipArmor;
delete m_equipAccessory;
}
// 플레이어의 인벤토리 전부 보여주기
// m_vBag에 있는 요소 다 출력한다.
void Inventory::ShowPlayerBag()
{
m_bagItemCount = 0;
m_viBag = m_vBag.begin();
for (m_viBag; m_viBag != m_vBag.end(); ++m_viBag)
{
std::cout << "=================================================" << std::endl;
std::cout << ++m_bagItemCount << "번째 아이템" << std::endl;
m_viBag->ShowItemInfo();
Sleep(500);
}
std::cout << "=================================================" << std::endl;
}
// 장비 확인하기 및 장비 교체에 관련한 출력문과 함수가 들어있는 함수
void Inventory::ShowPlayerEquip()
{
ShowEquipText();
std::cout << "=================================================" << std::endl;
std::cout << "플레이어의 장비 확인하기를 선택하셨습니다." << std::endl;
std::cout << "1~3을 입력해 원하는 장비를 교체합니다." << std::endl;
std::cout << "0을 누르면 이전으로 돌아갑니다." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_inventorySelectNum;
bool WrongSelect = ((0 > m_inventorySelectNum) || (m_inventorySelectNum > 3));
while (WrongSelect)
{
ShowEquipText();
std::cout << "=================================================" << std::endl;
std::cout << "그곳엔 아이템이 없습니다. 다시 입력하세요." << std::endl;
std::cout << "이전으로 돌아가려면 0을 입력하세요." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_inventorySelectNum;
WrongSelect = ((0 > m_inventorySelectNum) || (m_inventorySelectNum > 3));
}
if (m_inventorySelectNum == 0) return;
ITEM selectItemType = (ITEM)m_inventorySelectNum;
system("cls");
ShowPlayerBag();
std::cout << "원하는 아이템을 선택하세요." << std::endl;
std::cout << "이전으로 돌아가려면 0을 입력하세요." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_inventorySelectNum;
if (m_inventorySelectNum != 0)
{
WrongSelect = ((0 > m_inventorySelectNum) || (m_inventorySelectNum > m_bagItemCount));
while (WrongSelect)
{
system("cls");
ShowPlayerBag();
std::cout << "그곳엔 아이템이 없거나 올바르지 않은 장비 타입입니다." << std::endl;
std::cout << "다시 입력하세요." << std::endl;
std::cout << "이전으로 돌아가려면 0을 입력하세요." << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "입력 : ";
std::cin >> m_inventorySelectNum;
WrongSelect = ((0 > m_inventorySelectNum) || (m_inventorySelectNum > m_bagItemCount));
}
bool WrongType = selectItemType != m_vBag[m_inventorySelectNum - 1].GetType();
if (WrongType)
{
std::cout << "=================================================" << std::endl;
std::cout << "아이템 타입이 맞지 않습니다." << std::endl;
std::cout << "=================================================" << std::endl;
Sleep(1000);
}
else
ChangePlayerEquip(m_inventorySelectNum - 1);
}
else if (m_inventorySelectNum == 0)
{
std::cout << "=================================================" << std::endl;
std::cout << "상점 메뉴로 돌아갑니다." << std::endl;
std::cout << "=================================================" << std::endl;
Sleep(500);
return;
}
}
// 반복적으로 호출하는 플레이어의 장비 출력 함수
void Inventory::ShowEquipText()
{
system("cls");
std::cout << "=================================================" << std::endl;
std::cout << "플레이어의 장비" << std::endl;
std::cout << "=================================================" << std::endl;
std::cout << "1.무 기" << std::endl;
m_equipWeapon->ShowItemInfo();
Sleep(500);
std::cout << "=================================================" << std::endl;
std::cout << "2.방 어 구" << std::endl;
m_equipArmor->ShowItemInfo();
Sleep(500);
std::cout << "=================================================" << std::endl;
std::cout << "3.장 신 구" << std::endl;
m_equipAccessory->ShowItemInfo();
Sleep(500);
}
// 특정 vector 인덱스를 매개변수로 하여 그 인덱스의
// 장비와 현재 장비를 바꾸는 함수
// 현재 장비와 똑같은 장비가 인벤토리에 있으면 갯수를 추가시키고
// 그 다음 장비 데이터를 대입하고 나서
// 인벤토리에 있던 장비를 갯수를 감소시킨다.
// 만약 갯수가 0이면 요소를 삭제한다.
void Inventory::ChangePlayerEquip(int itemIdx)
{
int existItem;
if (m_vBag[itemIdx].GetType() == ITEM::ITEM_WEAPON)
{
existItem = IsItemExist(m_equipWeapon->GetName());
if (existItem > -1)
m_vBag[existItem].SetCount(m_vBag[existItem].GetCount() + 1);
else
m_vBag.push_back(*m_equipWeapon);
m_equipWeapon = new Item(m_vBag[itemIdx]);
m_vBag[itemIdx].SetCount(m_vBag[itemIdx].GetCount() - 1);
if (m_vBag[itemIdx].GetCount() == 0)
{
m_vBag.erase(m_vBag.begin() + itemIdx);
}
}
else if(m_vBag[itemIdx].GetType() == ITEM::ITEM_ARMOR)
{
existItem = IsItemExist(m_equipArmor->GetName());
if (existItem > -1)
m_vBag[existItem].SetCount(m_vBag[existItem].GetCount() + 1);
else
m_vBag.push_back(*m_equipArmor);
m_equipArmor = new Item(m_vBag[itemIdx]);
m_vBag[itemIdx].SetCount(m_vBag[itemIdx].GetCount() - 1);
if (m_vBag[itemIdx].GetCount() == 0)
{
m_vBag.erase(m_vBag.begin() + itemIdx);
}
}
else if(m_vBag[itemIdx].GetType() == ITEM::ITEM_ACCESSORY)
{
existItem = IsItemExist(m_equipAccessory->GetName());
if (existItem > -1)
m_vBag[existItem].SetCount(m_vBag[existItem].GetCount() + 1);
else
m_vBag.push_back(*m_equipAccessory);
m_equipAccessory = new Item(m_vBag[itemIdx]);
m_vBag[itemIdx].SetCount(m_vBag[itemIdx].GetCount() - 1);
if (m_vBag[itemIdx].GetCount() == 0)
{
m_vBag.erase(m_vBag.begin() + itemIdx);
}
}
}
// 해당 이름을 가진 아이템이 인벤토리에 있는지 확인하는 함수
int Inventory::IsItemExist(const string itemName)
{
int result = -1;
int itemCount = 0;
m_viBag = m_vBag.begin();
for (m_viBag; m_viBag != m_vBag.end(); ++m_viBag)
{
++itemCount;
if (m_viBag->GetName() == itemName)
{
result = itemCount - 1;
break;
}
}
return result;
}
5-12. Main.cpp
#include"MainGame.h"
int main(void)
{
MainGame mainGame;
mainGame.Update();
}
6. 결과
'연습' 카테고리의 다른 글
[C++] 스택 구현 (0) | 2021.06.22 |
---|---|
[C++] 단방향 리스트 구현 (0) | 2021.06.22 |
[C++] 월남뽕 게임 (0) | 2021.06.16 |
[C++] 몬스터와 1대3 턴제 전투 게임 (0) | 2021.06.14 |
[C++] 슬라이드 퍼즐 게임 (0) | 2021.06.14 |