오늘의 할일
1. 코드카타 정리
2. 과제
3. 궁금증 해결
4. 다음 학습 예습
개념 요약
메모리 이중 해제를 막기 위해 생긴 게 Rule of Three
-> 어떤 클래스가 3가지 법칙 중 단 하나라도 직접 구현해야 한다면 무조건 나머지 2개도 함께 직접 구현해야 한다는 법칙
1. 소멸자 (Destructor): ~Inventory()
2. 복사 생성자 (Copy Constructor): Inventory(const Inventory& other)
3. 복사 대입 연산자 (Copy Assignment Operator): operator=(const Inventory& other)
복사 생성자 vs 복사 대입 연산자
Inventory inv2 = inv1;
Inventory inv2(inv1);
Inventory inv1;
Inventory inv2;
inv2 = inv1; //나중에 대입💡
시간 복잡도(Big-O 표기법) : 데이터의 개수가 늘어날 때 연산 횟수가 얼마나 기하급수적으로 늘어나는지를 수학적으로 표현한 것
큐 : 선입선출(FIFO) 자료구조
-> 스택은 정반대로 후입선출
2개의 위치 포인터
4대 핵심 연산 (모두 속도는 O(1) - 즉시 실행)
임의의 양의 정수 n에 대해, n이 어떤 양의 정수 x의 제곱인지 아닌지 판단하고
n이 양의 정수 x의 제곱이라면 x+1의 제곱을 리턴하고, n이 양의 정수 x의 제곱이 아니라면 -1을 리턴하는 함수
#include <string>
#include <vector>
using namespace std;
long long solution(long long n) {
long long answer = 0;
for (long long i = 1; i * i <= n; i++)
{
if (i * i == n) {
answer = (i + 1) * (i + 1);
}
}
answer = -1;
return answer;
}
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Monster;
class Player {
protected:
string name;
string job;
int hp;
int mp;
int power;
int defence;
int level;
int exp;
int maxExp;
int maxHp; //추가
int maxMp; //추가
public:
Player(string name, string job, int hp, int mp, int power, int defence);
virtual ~Player() {}
virtual void attack(Monster* monster) = 0;
void gainExp(int rewardExp);
void printPlayerStatus() const;
string getName() { return name; }
string getJob() { return job; }
int getLevel() { return level; }
int getHp() { return hp; }
int getMp() { return mp; }
int getPower() { return power; }
int getDefence() { return defence; }
int getMaxHp() { return maxHp; } //추가
int getMaxMp() { return maxMp; } //추가
void setName(string name) { this->name = name; }
void setJob(string job) { this->job = job; }
void setLevel(int level) { this->level = level; }
void setHp(int hp) { this->hp = hp; }
void setMp(int mp) { this->mp = mp; }
void setPower(int power) { this->power = power; }
void setDefence(int defence) { this->defence = defence; }
};
#include "Player.h"
Player::Player(string name, string job, int hp, int mp, int power, int defence) : name(name), job(job), hp(hp), mp(mp), maxHp(hp), maxMp(mp), power(power), defence(defence), level(1), exp(0), maxExp(100) {}
//최대체력, 최대마나 추가
void Player::gainExp(int rewardExp) {
exp += rewardExp;
cout << " -> +" << rewardExp << " EXP! (EXP: " << exp << "/" << maxExp << ")" << endl;
while (exp >= maxExp) {
cout << endl;
cout << " -> Level up! Lv." << level << " -> Lv." << (level + 1) << endl;
level++;
hp += 10;
maxHp += 10; //추가
mp += 5;
power += 5;
cout << " -> HP +10, MP +5, Attack +5" << endl;
exp -= maxExp;
maxExp += 50;
cout << " -> (Current EXP: " << exp << "/" << maxExp << ")" << endl;
}
}
void Player::printPlayerStatus() const {
cout << "===========================================" << endl;
cout << " [ " << name << " (" << job << ") - Lv." << level << " ]" << endl;
cout << "===========================================" << endl;
cout << " EXP : " << exp << " / " << maxExp << endl;
cout << " HP : " << hp << " MP : " << mp << endl;
cout << " Att : " << power << " Defense : " << defence << endl;
cout << "===========================================" << endl << endl;
}
#include <iostream>
#include <string>
#include <vector>
#include <algorithm> //추가 (min 함수)
#include "Player.h"
#include "Warrior.h"
#include "Mage.h"
#include "Rogue.h"
#include "Archer.h"
#include "Monster.h"
using namespace std;
string name;
const int SIZE = 4;
int playerstat[SIZE] = { 0 };
// {HP, MP, 공격력, 방어력}
int PotionHP = 0;
int PotionMP = 0;
int choice;
bool isGameStart = false;
struct Item {
string name;
int price = 0;
void PrintItem() const {
cout << name << " (" << price << "G)" << endl;
}
};
vector<Item> inventory;
struct PotionRecipe {
string potionName;
string ingredient1;
string ingredient2;
void PrintRecipe() const {
cout << "-> " << potionName << " : " << ingredient1 << " x1, " << ingredient2 << " x1" << endl;
}
};
vector<PotionRecipe> recipes = {
{"HPPotion", "Herb", "Clear Water"},
{"MPPotion", "Slime Jelly", "Clear Water"},
{"StaminaPotioin", "Herb", "Berry"}
};
void printTitle()
{
cout << "===========================================" << endl;
cout << " [ Dungeon Escape Text RPG ]" << endl;
cout << "===========================================" << endl;
}
void statsMenu()
{
cout << "===========================================" << endl;
cout << " " << name << "'s Stats" << endl;
cout << "===========================================" << endl;
cout << "HP: " << playerstat[0] << " MP: " << playerstat[1] << endl;
cout << "Attack: " << playerstat[2] << " Defense: " << playerstat[3] << endl;
cout << endl;
}
Player* createCharacter(string name, int playerstat[]) {
cout << "< Job Selection >" << endl;
cout << name << ", choose your job!" << endl;
cout << "1. Warrior 2. Mage 3. Rogue 4. Archer" << endl;
cout << "Choose: ";
int jobChoice;
cin >> jobChoice;
Player* player = nullptr;
switch (jobChoice) {
case 1:
cout << endl;
player = new Warrior(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
case 2:
cout << endl;
player = new Mage(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
case 3:
cout << endl;
player = new Rogue(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
case 4:
cout << endl;
player = new Archer(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
default:
cout << endl;
player = new Warrior(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
}
return player;
}
Player* statsCustom()
{
Player* player = nullptr;
while (!isGameStart) {
cout << "===========================================" << endl;
cout << " < Character Upgrade >" << endl;
cout << "1. HP UP 2. MP UP 3. Attack x2" << endl;
cout << "4. Defense x2 5. Show Stats 0. Jop Select & Start Game" << endl;
cout << "===========================================" << endl;
cout << "Choose : ";
cin >> choice;
cout << endl;
switch (choice) {
case 0:
system("cls");
printTitle();
cout << endl;
player = createCharacter(name, playerstat);
cout << endl;
cout << "Starting the game!" << endl;
cout << endl;
cout << " /| ________________" << endl;
cout << " O|===|* >________________>" << endl;
cout << " ||" << endl;
cout << endl << endl;
isGameStart = true;
break;
case 1:
if (PotionHP == 0)
{
cout << "No potions left!" << endl;
cout << endl;
break;
}
cout << "* HP increased by 20. (HP Potion used: " << PotionHP - 1 << " left)" << endl;
PotionHP -= 1;
playerstat[0] += 20;
cout << endl;
break;
case 2:
if (PotionMP == 0)
{
cout << "No potions left!" << endl;
cout << endl;
break;
}
cout << "* MP increased by 20. (MP Potion used: " << PotionMP - 1 << " left)" << endl;
PotionMP -= 1;
playerstat[1] += 20;
cout << endl;
break;
case 3:
cout << "* Attack multiplied by 2." << endl;
playerstat[2] *= 2;
cout << endl;
break;
case 4:
cout << "* Defense multiplied by 2." << endl;
playerstat[3] *= 2;
cout << endl;
break;
case 5:
system("cls");
printTitle();
cout << endl;
statsMenu();
break;
default:
cout << "Please choose another number." << endl;
cout << endl;
break;
}
}
return player;
}
void enterStats()
{
while (true)
{
cout << "Enter HP and MP: ";
cin >> playerstat[0];
cin >> playerstat[1];
if (playerstat[0] < 50 || playerstat[1] < 50)
{
cout << "HP or MP is too low. Try again." << endl;
}
else {
break;
}
}
while (true)
{
cout << "Enter Attack and Defense: ";
cin >> playerstat[2];
cin >> playerstat[3];
if (playerstat[2] < 50 || playerstat[3] < 50)
{
cout << "Attack or Defense is too low. Try again." << endl;
}
else {
break;
}
}
}
// 수정
void startBattle(Player* player, Monster& monster) {
cout << endl;
cout << " [ Battle Start! ] " << player->getName() << "(" << player->getJob() << ") vs " << monster.getName() << endl;
cout << endl;
while (player->getHp() > 0 && monster.getHp() > 0) {
cout << "--- Player Turn ---" << endl;
cout << "1. Attack" << endl;
cout << "2. Use Item" << endl;
cout << "Choose: ";
int turnChoice;
cin >> turnChoice;
cout << endl;
if (turnChoice == 2) {
cout << "[ Inventory ]" << endl;
if (inventory.empty()) {
cout << "The inventory is empty!" << endl << endl;
}
else {
for (int i = 0; i < inventory.size(); i++) {
cout << (i+1) << ". " << inventory[i].name << " (" << inventory[i].price << "G)" << endl;
}
cout << "0. Cancel" << endl;
cout << "Choose item: ";
int itemChoice;
cin >> itemChoice;
cout << endl;
if (itemChoice > 0 && itemChoice <= inventory.size()) {
int idx = itemChoice - 1;
string itemName = inventory[idx].name;
if (itemName == "HPPotion" || itemName == "HP Potion") {
int oldHp = player->getHp();
player->setHp(min(oldHp + 50, player->getMaxHp()));
cout << "* " << itemName << " used! HP restored by 50 (" << oldHp << " -> " << player->getHp() << ")" << endl << endl;
inventory.erase(inventory.begin() + idx);
}
else if (itemName == "MPPotion" || itemName == "MP Potion") {
int oldMp = player->getMp();
player->setMp(min(oldMp + 50, player->getMaxMp()));
cout << "* " << itemName << " used! MP restored by 50 (" << oldMp << " -> " << player->getMp() << ")" << endl << endl;
inventory.erase(inventory.begin() + idx);
}
else {
cout << "You cannot use this item in battle." << endl << endl;
}
}
else if (itemChoice == 0) {
cout << "Canceled item use." << endl << endl;
continue;
}
else {
cout << "Invalid item number!" << endl << endl;
}
}
}
else {
player->attack(&monster);
}
if (monster.getHp() <= 0) {
cout << " (Dead) ";
cout << endl << endl;
cout << "★ Victory!" << endl;
player->gainExp(monster.getExpReward());
cout << endl;
cout << " -> Got: " << monster.getDropItemName() << "!" << endl;
cout << " -> Saved to inventory." << endl << endl;
Item droppedItem;
droppedItem.name = monster.getDropItemName();
droppedItem.price = monster.getDropItemPrice();
inventory.push_back(droppedItem);
break;
}
cout << endl << endl;
cout << "--- Monster Turn ---" << endl;
monster.attack(player);
int monsterDamage = monster.getPower() - player->getDefence();
if (monsterDamage <= 0) {
monsterDamage = 1;
}
int playerOldHp = player->getHp();
player->setHp(playerOldHp - monsterDamage);
cout << monsterDamage << " damage to " << player->getName() << "!" << endl;
cout << player->getName() << " HP : " << playerOldHp << " -> " << player->getHp();
cout << endl << endl;
if (player->getHp() <= 0) {
cout << " (Dead) " << endl;
cout << endl;
cout << " Game Over..." << endl;
break;
}
}
}
void AlchemyWorkshop() {
int ChoiceShop;
while (true) {
cout << "=== Potion Shop ===" << endl;
cout << "1. Show all recipes" << endl;
cout << "2. Search by potion name" << endl;
cout << "3. Search by ingredient" << endl;
cout << "0. Go back" << endl;
cout << endl;
cout << "Choose : ";
cin >> ChoiceShop;
cout << endl;
switch (ChoiceShop) {
case 0:
system("cls");
printTitle();
return;
case 1:
for (const PotionRecipe& PR : recipes) {
PR.PrintRecipe();
}
cout << endl;
break;
case 2:
{
string searchName;
cout << "Search potion name: ";
cin.ignore();
getline(cin, searchName);
bool isFound = false;
for (const PotionRecipe& PR : recipes) {
if (PR.potionName == searchName) {
PR.PrintRecipe();
isFound = true;
break;
}
}
if (!isFound) {
cout << "It cannot be found." << endl;
}
cout << endl;
break;
}
case 3: {
string searchIngredient;
cout << "Search ingredient: ";
cin.ignore();
getline(cin, searchIngredient);
int count = 0;
for (const PotionRecipe& PR : recipes) {
if (PR.ingredient1 == searchIngredient || PR.ingredient2 == searchIngredient)
{
PR.PrintRecipe();
count++;
}
}
if (count == 0) {
cout << "It cannot be found." << endl;
}
else {
cout << "Found " << count << " recipes." << endl;
}
cout << endl;
break;
}
default:
cout << "Please choose another number." << endl << endl;
break;
}
}
}
void mainMenu(Player* player)
{
int choiceMenu;
while (true) {
cout << "=== Main Menu ===" << endl;
cout << "1. Enter Dungeon" << endl;
cout << "2. Check Inventory" << endl;
cout << "3. Potion Shop" << endl;
cout << "0. Quit" << endl;
cout << endl;
cout << "Choose : ";
cin >> choiceMenu;
cout << endl;
switch (choiceMenu) {
case 0:
system("cls");
printTitle();
cout << "Exit Game.." << endl;
return;
case 1:
{
Monster slime("Slime", 30, 20, 10, "Slime Jelly", 30, 30);
Monster professor("Professor", 40, 30, 10, "paper", 30, 70);
startBattle(player, slime);
startBattle(player, professor);
if (player->getHp() <= 0) {
return;
}
break;
}
case 2:
system("cls");
printTitle();
cout << "[ Inventory (" << inventory.size() << "/10) ]" << endl;
if (inventory.empty()) {
cout << "The inventory is empty." << endl;
}
else {
int number = 1;
for (const Item& item : inventory) {
cout << number << ". ";
item.PrintItem();
number++;
}
}
cout << endl;
break;
case 3:
system("cls");
printTitle();
AlchemyWorkshop();
break;
default:
cout << "Please choose another number." << endl << endl;
break;
}
}
}
void setPotion(int count, int* p_HPPotion, int* p_MPPotion) {
*p_HPPotion = count;
*p_MPPotion = count;
}
int main() {
printTitle();
cout << "Enter your hero's name: ";
cin >> name;
cout << endl;
enterStats();
system("cls");
printTitle();
statsMenu();
setPotion(5, &PotionHP, &PotionMP);
cout << "* You received " << PotionHP << " HP Potions and " << PotionMP << " MP Potions." << endl;
Player* player = statsCustom();
player->printPlayerStatus();
mainMenu(player);
delete player;
return 0;
}
Inventory<T> 직접 구현 (template, 동적 메모리)
#pragma once
#include <iostream>
#include <string>
using namespace std;
template<typename T>
class Inventory {
private:
T* pItems_;
int capacity_;
int size_;
public:
Inventory(int capacity = 10) : capacity_(capacity), size_(0) {
pItems_ = new T[capacity_];
}
~Inventory() {
delete[] pItems_;
}
Inventory(const Inventory<T>& other) : capacity_(other.capacity_), size_(other.size_) {
pItems_ = new T[capacity_];
for (int i = 0; i < size_; i++) {
pItems_[i] = other.pItems_[i];
}
}
Inventory<T>& operator=(const Inventory<T>& other) {
if (this == &other) return *this;
delete[] pItems_;
capacity_ = other.capacity_;
size_ = other.size_;
pItems_ = new T[capacity_];
for (int i = 0; i < size_; i++) {
pItems_[i] = other.pItems_[i];
}
return *this;
}
int GetSize() const { return size_; }
int GetCapacity() const { return capacity_; }
bool AddItem(const T& item) {
if (size_ >= capacity_) {
cout << "Inventory is full! (" << size_ << "/" << capacity_ << ")" << endl;
return false;
}
pItems_[size_] = item;
size_++;
return true;
}
void RemoveLastItem() {
if (size_ > 0) {
size_--;
}
else {
cout << "Inventory is already empty!" << endl;
}
}
void RemoveItemAt(int index) {
if (index < 0 || index >= size_) return;
for (int i = index; i < size_ - 1; i++) {
pItems[i] = pItems_[i + 1];
}
size_--;
}
T& operator[](int index) {
return pItems_[index];
}
const T& operator[](int index) const {
return pItems_[index];
}
void PrintAllItems() const {
if (size_ == 0) {
cout << "The inventory is empty." << endl;
return;
}
for (int i = 0; i < size_; i++) {
cout << (i + 1) << ". ";
pItems_[i].PrintItem();
}
}
};
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include "Player.h"
#include "Warrior.h"
#include "Mage.h"
#include "Rogue.h"
#include "Archer.h"
#include "Monster.h"
#include "Inventory.h" //추가
using namespace std;
string name;
const int SIZE = 4;
int playerstat[SIZE] = { 0 };
// {HP, MP, 공격력, 방어력}
int PotionHP = 0;
int PotionMP = 0;
int choice;
bool isGameStart = false;
struct Item {
string name;
int price = 0;
void PrintItem() const {
cout << name << " (" << price << "G)" << endl;
}
};
//수정
Inventory<Item> inventory(10);
struct PotionRecipe {
string potionName;
string ingredient1;
string ingredient2;
void PrintRecipe() const {
cout << "-> " << potionName << " : " << ingredient1 << " x1, " << ingredient2 << " x1" << endl;
}
};
vector<PotionRecipe> recipes = {
{"HPPotion", "Herb", "Clear Water"},
{"MPPotion", "Slime Jelly", "Clear Water"},
{"StaminaPotioin", "Herb", "Berry"}
};
void printTitle()
{
cout << "===========================================" << endl;
cout << " [ Dungeon Escape Text RPG ]" << endl;
cout << "===========================================" << endl;
}
void statsMenu()
{
cout << "===========================================" << endl;
cout << " " << name << "'s Stats" << endl;
cout << "===========================================" << endl;
cout << "HP: " << playerstat[0] << " MP: " << playerstat[1] << endl;
cout << "Attack: " << playerstat[2] << " Defense: " << playerstat[3] << endl;
cout << endl;
}
Player* createCharacter(string name, int playerstat[]) {
cout << "< Job Selection >" << endl;
cout << name << ", choose your job!" << endl;
cout << "1. Warrior 2. Mage 3. Rogue 4. Archer" << endl;
cout << "Choose: ";
int jobChoice;
cin >> jobChoice;
Player* player = nullptr;
switch (jobChoice) {
case 1:
cout << endl;
player = new Warrior(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
case 2:
cout << endl;
player = new Mage(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
case 3:
cout << endl;
player = new Rogue(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
case 4:
cout << endl;
player = new Archer(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
default:
cout << endl;
player = new Warrior(name, playerstat[0], playerstat[1], playerstat[2], playerstat[3]);
break;
}
return player;
}
Player* statsCustom()
{
Player* player = nullptr;
while (!isGameStart) {
cout << "===========================================" << endl;
cout << " < Character Upgrade >" << endl;
cout << "1. HP UP 2. MP UP 3. Attack x2" << endl;
cout << "4. Defense x2 5. Show Stats 0. Jop Select & Start Game" << endl;
cout << "===========================================" << endl;
cout << "Choose : ";
cin >> choice;
cout << endl;
switch (choice) {
case 0:
system("cls");
printTitle();
cout << endl;
player = createCharacter(name, playerstat);
cout << endl;
cout << "Starting the game!" << endl;
cout << endl;
cout << " /| ________________" << endl;
cout << " O|===|* >________________>" << endl;
cout << " ||" << endl;
cout << endl << endl;
isGameStart = true;
break;
case 1:
if (PotionHP == 0)
{
cout << "No potions left!" << endl;
cout << endl;
break;
}
cout << "* HP increased by 20. (HP Potion used: " << PotionHP - 1 << " left)" << endl;
PotionHP -= 1;
playerstat[0] += 20;
cout << endl;
break;
case 2:
if (PotionMP == 0)
{
cout << "No potions left!" << endl;
cout << endl;
break;
}
cout << "* MP increased by 20. (MP Potion used: " << PotionMP - 1 << " left)" << endl;
PotionMP -= 1;
playerstat[1] += 20;
cout << endl;
break;
case 3:
cout << "* Attack multiplied by 2." << endl;
playerstat[2] *= 2;
cout << endl;
break;
case 4:
cout << "* Defense multiplied by 2." << endl;
playerstat[3] *= 2;
cout << endl;
break;
case 5:
system("cls");
printTitle();
cout << endl;
statsMenu();
break;
default:
cout << "Please choose another number." << endl;
cout << endl;
break;
}
}
return player;
}
void enterStats()
{
while (true)
{
cout << "Enter HP and MP: ";
cin >> playerstat[0];
cin >> playerstat[1];
if (playerstat[0] < 50 || playerstat[1] < 50)
{
cout << "HP or MP is too low. Try again." << endl;
}
else {
break;
}
}
while (true)
{
cout << "Enter Attack and Defense: ";
cin >> playerstat[2];
cin >> playerstat[3];
if (playerstat[2] < 50 || playerstat[3] < 50)
{
cout << "Attack or Defense is too low. Try again." << endl;
}
else {
break;
}
}
}
void startBattle(Player* player, Monster& monster) {
cout << endl;
cout << " [ Battle Start! ] " << player->getName() << "(" << player->getJob() << ") vs " << monster.getName() << endl;
cout << endl;
while (player->getHp() > 0 && monster.getHp() > 0) {
cout << "--- Player Turn ---" << endl;
cout << "1. Attack" << endl;
cout << "2. Use Item" << endl;
cout << "Choose: ";
int turnChoice;
cin >> turnChoice;
cout << endl;
//수정
if (turnChoice == 2) {
cout << "[ Inventory ]" << endl;
if (inventory.GetSize() == 0) {
cout << "The inventory is empty!" << endl << endl;
}
else {
for (int i = 0; i < inventory.GetSize(); i++) {
cout << (i+1) << ". " << inventory[i].name << " (" << inventory[i].price << "G)" << endl;
}
cout << "0. Cancel" << endl;
cout << "Choose item: ";
int itemChoice;
cin >> itemChoice;
cout << endl;
if (itemChoice > 0 && itemChoice <= inventory.GetSize()) {
int idx = itemChoice - 1;
string itemName = inventory[idx].name;
if (itemName == "HPPotion" || itemName == "HP Potion") {
int oldHp = player->getHp();
player->setHp(min(oldHp + 50, player->getMaxHp()));
cout << "* " << itemName << " used! HP restored by 50 (" << oldHp << " -> " << player->getHp() << ")" << endl << endl;
inventory.RemoveItemAt(idx);
}
else if (itemName == "MPPotion" || itemName == "MP Potion") {
int oldMp = player->getMp();
player->setMp(min(oldMp + 50, player->getMaxMp()));
cout << "* " << itemName << " used! MP restored by 50 (" << oldMp << " -> " << player->getMp() << ")" << endl << endl;
inventory.RemoveItemAt(idx);
}
else {
cout << "You cannot use this item in battle." << endl << endl;
}
}
else if (itemChoice == 0) {
cout << "Canceled item use." << endl << endl;
continue;
}
else {
cout << "Invalid item number!" << endl << endl;
}
}
}
else {
player->attack(&monster);
}
if (monster.getHp() <= 0) {
cout << " (Dead) ";
cout << endl << endl;
cout << "★ Victory!" << endl;
player->gainExp(monster.getExpReward());
cout << endl;
cout << " -> Got: " << monster.getDropItemName() << "!" << endl;
cout << " -> Saved to inventory." << endl << endl;
Item droppedItem;
droppedItem.name = monster.getDropItemName();
droppedItem.price = monster.getDropItemPrice();
//수정
inventory.AddItem(droppedItem);
break;
}
cout << endl << endl;
cout << "--- Monster Turn ---" << endl;
monster.attack(player);
int monsterDamage = monster.getPower() - player->getDefence();
if (monsterDamage <= 0) {
monsterDamage = 1;
}
int playerOldHp = player->getHp();
player->setHp(playerOldHp - monsterDamage);
cout << monsterDamage << " damage to " << player->getName() << "!" << endl;
cout << player->getName() << " HP : " << playerOldHp << " -> " << player->getHp();
cout << endl << endl;
if (player->getHp() <= 0) {
cout << " (Dead) " << endl;
cout << endl;
cout << " Game Over..." << endl;
break;
}
}
}
void AlchemyWorkshop() {
int ChoiceShop;
while (true) {
cout << "=== Potion Shop ===" << endl;
cout << "1. Show all recipes" << endl;
cout << "2. Search by potion name" << endl;
cout << "3. Search by ingredient" << endl;
cout << "0. Go back" << endl;
cout << endl;
cout << "Choose : ";
cin >> ChoiceShop;
cout << endl;
switch (ChoiceShop) {
case 0:
system("cls");
printTitle();
return;
case 1:
for (const PotionRecipe& PR : recipes) {
PR.PrintRecipe();
}
cout << endl;
break;
case 2:
{
string searchName;
cout << "Search potion name: ";
cin.ignore();
getline(cin, searchName);
bool isFound = false;
for (const PotionRecipe& PR : recipes) {
if (PR.potionName == searchName) {
PR.PrintRecipe();
isFound = true;
break;
}
}
if (!isFound) {
cout << "It cannot be found." << endl;
}
cout << endl;
break;
}
case 3: {
string searchIngredient;
cout << "Search ingredient: ";
cin.ignore();
getline(cin, searchIngredient);
int count = 0;
for (const PotionRecipe& PR : recipes) {
if (PR.ingredient1 == searchIngredient || PR.ingredient2 == searchIngredient)
{
PR.PrintRecipe();
count++;
}
}
if (count == 0) {
cout << "It cannot be found." << endl;
}
else {
cout << "Found " << count << " recipes." << endl;
}
cout << endl;
break;
}
default:
cout << "Please choose another number." << endl << endl;
break;
}
}
}
void mainMenu(Player* player)
{
int choiceMenu;
while (true) {
cout << "=== Main Menu ===" << endl;
cout << "1. Enter Dungeon" << endl;
cout << "2. Check Inventory" << endl;
cout << "3. Potion Shop" << endl;
cout << "0. Quit" << endl;
cout << endl;
cout << "Choose : ";
cin >> choiceMenu;
cout << endl;
switch (choiceMenu) {
case 0:
system("cls");
printTitle();
cout << "Exit Game.." << endl;
return;
case 1:
{
Monster slime("Slime", 30, 20, 10, "Slime Jelly", 30, 30);
Monster professor("Professor", 40, 30, 10, "paper", 30, 70);
startBattle(player, slime);
startBattle(player, professor);
if (player->getHp() <= 0) {
return;
}
break;
}
//수정
case 2:
system("cls");
printTitle();
cout << "[ Inventory (" << inventory.GetSize() << "/10) ]" << endl;
inventory.PrintAllItems();
cout << endl;
break;
case 3:
system("cls");
printTitle();
AlchemyWorkshop();
break;
default:
cout << "Please choose another number." << endl << endl;
break;
}
}
}
void setPotion(int count, int* p_HPPotion, int* p_MPPotion) {
*p_HPPotion = count;
*p_MPPotion = count;
}
int main() {
printTitle();
cout << "Enter your hero's name: ";
cin >> name;
cout << endl;
enterStats();
system("cls");
printTitle();
statsMenu();
setPotion(5, &PotionHP, &PotionMP);
cout << "* You received " << PotionHP << " HP Potions and " << PotionMP << " MP Potions." << endl;
Player* player = statsCustom();
player->printPlayerStatus();
mainMenu(player);
delete player;
return 0;
}
1
Q. 복사 대입 연산자, Rule of Three?
얕은 복사를 하면 메모리 이중 해제 발생 가능
-> 1. inv2 = inv1; 을 했더니, inv1과 inv2가 완전히 똑같은 메모리 방 하나를 동시에 공유하게 됨.
2. 게임이 끝나고 inv2가 소멸하면서 delete[] pItems_;를 해버림 (방이 파괴됨)
3. 직후 inv1도 소멸하면서 "어? 내 주머니에 메모리 주소가 있네? 치워야지!" 하고 이미 파괴된 방을 또 파괴(delete[])하려고 시도함
4. 컴퓨터: "이미 지운 메모리를 또 지워?! 이거 보안 사고야!" ➡️ 프로그램 강제 종료 (Crash)
이 메모리 이중 해제를 막기 위해 생긴 게 Rule of Three
-> 어떤 클래스가 3가지 법칙 중 단 하나라도 직접 구현해야 한다면 무조건 나머지 2개도 함께 직접 구현해야 한다는 법칙
1. 소멸자 (Destructor): ~Inventory()
2. 복사 생성자 (Copy Constructor): Inventory(const Inventory& other)
3. 복사 대입 연산자 (Copy Assignment Operator): operator=(const Inventory& other)
💡소멸자에서 delete로 뭔가를 치워야한다는 건 생성할 때 new로 메모리를 빌렸다는 뜻! -> 복사가 일어날 때도 깊은 복사 2가지 문법을 무조건 직접 짜야함.
복사 생성자 vs 복사 대입 연산자
Inventory inv2 = inv1;
Inventory inv2(inv1);
Inventory inv1;
Inventory inv2;
inv2 = inv1; //나중에 대입💡
Inventory<T>& operator=(const Inventory<T>& other) {
// 1단계: 자기 자신을 대입하는지 검사
if (this == &other) return *this;
// 2단계: 기존에 들고 있던 메모리 청소
delete[] pItems_;
// 3단계: 새로운 메모리 할당 및 데이터 복사 (Deep Copy)
capacity_ = other.capacity_;
size_ = other.size_;
pItems_ = new T[capacity_];
for (int i = 0; i < size_; i++) {
pItems_[i] = other.pItems_[i];
}
// 4단계: 내 자신(*this)을 반환
return *this;
}
2
Q. 시간 복잡도 & Big-O 표기법
시간 복잡도(Big-O 표기법) : 데이터의 개수가 늘어날 때 연산 횟수가 얼마나 기하급수적으로 늘어나는지를 수학적으로 표현한 것
데이터가 10개든 1억 개든 항상 딱 1번의 연산만으로 끝나는 속도.
비유: 배열에서 인덱스로 바로 찾아가기 (inventory[3]), 인벤토리 맨 뒤에 아이템 추가하기.
데이터 개수(N)만큼 연산 횟수가 정직하게 늘어나는 속도. 100개면 100번, 1만 개면 1만 번.
비유: 인벤토리에서 "전설의 검"을 찾으려고 1번 칸부터 끝까지 하나씩 다 열어보는 것.
데이터가 늘어날 때마다 연산 횟수가 제곱수로 폭증! (100개 -> 1만 번, 1만 개 -> 1억 번 연산).
비유: 몬스터 100마리가 서로 각자 다른 몬스터 100마리와 모두 거리를 계산해야 할 때 (for문 안에 for문).
3
Q. 큐?
큐 : 선입선출(FIFO) 자료구조
-> 스택은 정반대로 후입선출
선형 큐
원형 큐 : 배열의 처음과 끝이 이어져 있다고 생각하는 동그란 원형 큐
-> (현재 위치 + 1) % 배열크기
2개의 위치 포인터
4대 핵심 연산 (모두 속도는 O(1) - 즉시 실행)
#include <iostream>
#include <queue> // 💡 큐를 쓰기 위한 필수 헤더
#include <string>
using namespace std;
int main() {
// 💡 문자열을 담는 큐(대기열) 생성
queue<string> skillQueue;
// 1. Enqueue (C++에서는 push라고 부름) - 줄 서기
skillQueue.push("화염구");
skillQueue.push("얼음창");
skillQueue.push("번개폭풍");
cout << "현재 대기 중인 스킬 개수: " << skillQueue.size() << endl; // 출력: 3
// 2. 큐가 비어있지 않을 때까지 순서대로 실행 (FIFO)
while (!skillQueue.empty()) {
// 맨 앞(Front)에 있는 스킬 확인 (제거 X)
string currentSkill = skillQueue.front();
cout << "[스킬 발동] " << currentSkill << "!" << endl;
// 맨 앞 스킬을 큐에서 제거 (Dequeue / C++에서는 pop)
skillQueue.pop();
}
return 0;
배열 선형 탐색 - O(N)