*오늘의 코드카타*
array의 각 element 중 divisor로 나누어 떨어지는 값을 오름차순으로 정렬한 배열을 반환하는 함수, solution을 작성해주세요. divisor로 나누어 떨어지는 element가 하나도 없다면 배열에 -1을 담아 반환하세요.
arr은 자연수를 담은 배열이고, 정수 i,j에 대해 i != j 이면 arr[i] != arr[j] 입니다. divisor는 자연수이고 array는 길이 1 이상인 배열입니다.
(1) sort를 사용한 풀이
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> solution(vector<int> arr, int divisor) {
vector<int> answer;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] % divisor == 0) {
answer.push_back(arr[i]);
}
}
if (answer.empty()) {
answer.push_back(-1);
}
else {
sort(answer.begin(), answer.end());
}
return answer;
}
(2) <algorithm> 헤더의 copy_if 사용하기
주어진 배열이 있고 조건에 맞는 값만 배열에 가져오려고 한다면 copy_if를 사용할 수 있다,.
#include <vector>
#include <algorithm>
vector<int> solution(vector<int> arr, int divisor) {
vector<int> answer;
copy_if(arr.begin(), arr.end(), back_inserter(answer), [divisor](int n) {
return n % divisor == 0;
});
if (answer.empty()) {
return {-1};
}
sort(answer.begin(), answer.end());
return answer;
}
copy_if(시작점, 끝점, 도착점, 조건식); 형태로 사용할 수 있다.
이름 그대로 조건(if)에 맞는 것만 고라서 복사하라는 뜻의 C++ 내장 함수이다. 도착점은 조건식에 해당하는 값을 어디에 넣을 것인지 적는 곳이라고 보면 된다.
back_inserter는 헬퍼 함수로서, 벡터의 진짜 메서드인 push_back을 간접적으로 호출할 수 있게 해주는 외부함수이다.
그래서 answer 배열에 복사할 값이 생길 때마다 알아서 answer.push_back()을 실행해준다.
[divisor](int n) { return n % divisor == 0; } 는 람다 표현식이라고 부르는 함수로서 copy_if가 배열을 돌면서 원소를 하나씩 보고 결과가 참인 것만 복사한다. [divisor]를 써서 divisor라는 변수를 함수 안에서 사용할 수 있게 하고, n % divisor == 0 인지 확인한다.
*그 외*
[프로그래머스]
옷가게 할인 받기
#include <string>
#include <vector>
using namespace std;
int solution(int price) {
int answer = 0;
if (price >= 500000) {
answer = 0.8 * price;
}
else if (price >= 300000) {
answer = 0.9 * price;
}
else if (price >= 100000) {
answer = 0.95 * price;
}
else
answer = price;
return answer;
}
아이스 아메리카노
#include <string>
#include <vector>
using namespace std;
vector<int> solution(int money) {
vector<int> answer;
int americano = 0;
int leftmoney = 0;
americano = money / 5500;
leftmoney = money - americano * 5500;
answer.push_back(americano);
answer.push_back(leftmoney);
return answer;
}
풀이를 개선해보면, return 안에 쓰는 게 한줄로 나와서 더욱 깔끔하다.
#include <vector>
using namespace std;
vector<int> solution(int money) {
return vector<int> {money / 5500, money % 5500};
}
나이출력
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int solution(int age) {
int answer = 2023 - age;
return answer;
}
배열 뒤집기
#include <string>
#include <vector>
using namespace std;
vector<int> solution(vector<int> num_list) {
vector<int> answer;
for (int i = num_list.size() - 1; i >= 0; i--) {
answer.push_back(num_list[i]);
}
return answer;
}
C++의 알고리즘 헤더에 reverse라는 함수가 이미 내장되어 있으니까 활용하는 방법도 있다.
#include <algorithm>
vector<int> solution(vector<int> num_list) {
reverse(num_list.begin(), num_list.end());
return num_list;
뒤집힌 문자열
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
string solution(string my_string) {
string answer = "";
for (int i = my_string.length() - 1; i >= 0; i--)
answer.push_back(my_string[i]);
return answer;
}
당연하겠지만 rbegin()도 사용할 수 있다. 연습하자!
#include <bits/stdc++.h>
using namespace std;
string solution(string my_string) {
return string(my_string.rbegin(), my_string.rend());
}
직각삼각형 출력하기
#include <iostream>
using namespace std;
int main(void) {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << "*";
}
cout << "\n";
}
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main(void) {
int n;
cin >> n;
for(int i = 1; i <= n; ++i)
{
cout << string(i,'*') << endl;
}
return 0;
}
이렇게 string 라이브러리에서 제공하는 문자열 반복 기능을 사용하는 것이 좋다. 단 이때 작은따옴표만 사용 가능하니 주의.
짝수 홀수 개수
#include <string>
#include <vector>
using namespace std;
vector<int> solution(vector<int> num_list) {
vector<int> answer;
answer= {0, 0};
for (int num : num_list) {
if (num % 2 == 0) {
answer[0]++;
}
else {
answer[1]++;
}
}
return answer;
}
약간 응용해보자면, 2로 나눴을 때 홀수는 나머지가 1이고, 짝수는 나머지가 0인 것을 이용해서 나머지 값을 그대로 인덱스에 사용하는 방법도 있다.
#include <string>
#include <vector>
using namespace std;
vector<int> solution(vector<int> num_list) {
vector<int> answer(2, 0);
for (int num : num_list) {
answer[num % 2]++;
}
return answer;
}
문자 반복 출력하기
#include <string>
#include <vector>
using namespace std;
string solution(string my_string, int n) {
string answer = "";
for (char c : my_string) {
answer += string(n, c);
}
return answer;
}
[atanny]
(1)블루프린트와 C++ 연동 방식 이해 :
블루프린트의 주요 장점 : 빠른 반복 개발, 접근성, 실시간 개발
C++의 장점과 블루프린트의 장점 : C++은 복잡한 로직 구현에 효율적. 블루프린트는 빠른 프로토타이핑이 가능.
(2)Enhanced Input System의 구조와 차이점 분석
Enhanced Input System의 핵심적인 구성 요소: Input Action, Input Mapping Context, Input Modifier
Enhanced Input System의 주요 장점: 런타임에 동적으로 입력 매핑 변경 가능, 하나의 액션에 여러 키 쉽게 바인딩, 입력 값에 대한 전처리와 조건 적용 가능.
Input Modifier의 역할: 입력 값이 최종적으로 전달되기 전에 변환 또는 수정.
Input Mapping Context를 캐릭터에 적용하는 방법: Enhanced Input Local Player Subsystem -> Add Mapping Context함수로 추가.
[C++ 프로젝트]
(1) RPG 게임에서의 랜덤 요소 사용 사례 공부.
전투 시스템 (Combat System)
- 데미지 난수 (Damage Variance): 고정된 수치가 아닌, 기준 공격력을 중심으로 일정 범위 내(예: 90%~110%)에서 실제 가해지는 피해량이 무작위로 결정
- 치명타 판정 (Critical Hits): 공격 시 특정 확률에 따라 평소보다 높은 배율의 피해
- 명중 및 회피 (Accuracy & Evasion): 캐릭터의 명중률과 적의 회피율 수치에 기반하여 공격이 적중할지 빗나갈지(Miss) 계산
- 상태이상 확률 (Status Effect Procs): 중독, 기절, 빙결, 출혈 등의 상태이상이 적에게 부여될 확률
- 선공 판정 (Initiative): 턴제 전투에서 주사위 굴림(난수)을 통해 적과 아군 중 누가 먼저 행동할지 순서를 결정
- 스킬 발동 확률 (Passive/Trigger Skills): 피격 시 일정 확률로 반격하거나, 공격 시 일정 확률로 연속 공격이 나가는 등 조건부 패시브 스킬의 발동 여부
아이템 및 보상 (Loot & Rewards)
- 아이템 드랍률 (Drop Rates): 몬스터 처치 시 특정 아이템(장비, 재료, 골드 등)이 떨어질 확률
- 랜덤 옵션 및 접두사/접미사 (Random Affixes): 동일한 장비를 획득하더라도 부여되는 추가 능력치(힘, 민첩 등)나 특수 효과가 무작위로 결정
- 아이템 등급 (Item Rarity): 상자를 열거나 몬스터를 잡았을 때 일반, 희귀, 영웅, 전설 중 어떤 등급의 아이템이 나올지 결정하는 시스템
- 상자 내용물 (Chest Contents): 필드나 던전에 배치된 상자를 열었을 때 획득하는 골드의 양이나 소모품의 종류가 매번 달라짐
- 가챠 및 뽑기 (Gacha/Loot Boxes): 재화를 소모하여 무작위 캐릭터, 펫, 장비 등을 획득하는 시스템
탐험 및 환경 (Exploration & Environment)
- 랜덤 인카운터 (Random Encounters): 필드나 던전을 이동할 때 눈에 보이지 않는 적과 무작위 확률로 조우하여 전투 화면으로 넘어감
- 절차적 맵 생성 (Procedural Generation): 던전에 입장할 때마다 방의 구조, 함정의 위치, 몬스터의 배치, 출구의 위치가 무작위로 조합되어 새롭게 생성
- 날씨 및 시간 변화 (Weather & Time): 비, 눈, 안개 등의 날씨가 무작위로 발생하며, 이에 따라 특정 몬스터가 등장하거나 특정 속성 마법의 위력 변화
- 돌발 이벤트 (Random Events): 길을 걷다가 강도를 만나거나, 도움을 요청하는 NPC를 마주치는 등 예측 불가능한 퀘스트나 상황이 발생
캐릭터 육성 및 시스템 (Character & System)
- 초기 스탯 주사위 (Starting Stat Rolls): 캐릭터 생성 단계에서 주사위를 굴려 힘, 민첩, 지능 등의 기본 스탯 수치를 무작위로 부여
- 레벨업 스탯 상승 (Level-up Variance): 레벨이 오를 때 고정된 수치가 오르는 것이 아니라, 각 스탯별 성장 확률에 따라 능력치가 오를지 말지 결정
- 상점 리스트 갱신 (Merchant Inventory): 주기적으로 또는 특정 조건마다 상인이 판매하는 장비나 소모품의 종류와 품질이 무작위로 변경
- 스킬 판정 (Skill Checks): 자물쇠 따기, 함정 해제, NPC 설득 등의 비전투 행동을 시도할 때 성공 여부가 확률적으로 결정
Text RPG 팀프로젝트(day 3) :
(1) 오전 스크럼: 칸반보드에서 할 일 나눠가지기(역할 분배), 명확한 역할 분배> 무기, 장비, 아이템 이름과 변수 설정 / 강화 로직
RPG 게임의 랜덤요소들: (+) 포션 사용 아이템 선택 창에서 인벤토리에서 포션만 골라서 출력하는 방법.
아이템 랜덤 획득(무기 or 장비 or 강화석 or 골드 강화석은 1~5개 랜덤 획득)
(2) 오전 작업:
-0. 기존에 작성했던 Item.h, Item.cpp 수정(Getter 함수와 Setter함수 사용, AddAttack함수 활용)
#include "Item.h"
#include "../Character.h"
#include <iostream>
void HealthPotion::use(Character* character) {
if (count <= 0) {
std::cout << "체력 포션이 없습니다." << std::endl;
return;
}
count--;
//변수를 선언 하고 getter함수 호출
int currentHealth = character->GetHealth();
int maxHealth = character->GetMaxHealth();
//함수 수정(Entity.h의 AddHealth 함수 활용)
if (currentHealth + healthRestore > maxHealth) {
character->AddHealth(maxHealth - currentHealth);
}
else {
character->AddHealth(healthRestore);
}
std::cout << "체력 회복 (현재 : " << character->GetHealth() << ")" << std::endl;
}
void AttackBoost::use(Character* character) {
if (count <= 0) return;
count--;
//마찬가지로 Entity.h의 AddAttack 함수 활용
character->AddAttack(attackIncrease);
std::cout << "공격력 증가 (현재 : " << character->GetAttack() << ")" << std::endl;
}
-1. 플레이어 아이템 사용 → index를 이용해 인벤토리에서 사용 (나중에 전투 루프 만들어지면 여기다가 삽입해야 함)
아이템 사용을 위한 AddItem(), 메모리 누수 방지를 위한 소멸자 ~Character(), 아이템 이름 getter함수 std::string getName()
//character.cpp
//아이템 메모리 누수 방지
Character::~Character() {
for (Item* item : inventory) {
delete item;
}
inventory.clear( );
}
//인벤토리 기능 구현 위해서 추가
void Character::AddItem(Item* item) {
inventory.push_back(item);
}
-2. 상점 클래스→ 아이템 구입과 판매 + 랜덤 박스 기능도 구현해보았음.
//Shop.h
#pragma once
class Character;
class Shop
{
public:
//아이템 정보 출력, 아이템 선택 구매
void ShowItems( ) const;
void BuyItem(Character* player , int choice);
//상점을 호출 인터페이스
void OpenShop(Character* player);
};
//Shop.cpp
#include "Shop.h"
#include "../Character.h"
#include "Item.h"
#include <iostream>
#include <random>
void Shop::ShowItems( ) const
{
std::cout << "\n======== [ 상 점 ] ========" << std::endl;
std::cout << "1. 체력 포션 (50G)" << std::endl;
std::cout << "2. 공격력 포션 (50G)" << std::endl;
std::cout << "3. 랜덤 박스 (10G)" << std::endl;
std::cout << "0. 상점 나가기" << std::endl;
std::cout << "=========================" << std::endl;
}
void Shop::BuyItem(Character* player , int choice) {
if ( choice == 1 ) {
if ( player->GetGold( ) >= 50 ) {
player->UseGold(50);
player->AddItem(new HealthPotion("체력 포션" , 50 , 1));
std::cout << "남은 골드: " << player->GetGold( ) << " G" << std::endl;
}
else {
std::cout << "골드가 부족합니다." << std::endl;
}
}
else if ( choice == 2 ) {
if ( player->GetGold( ) >= 50 ) {
player->UseGold(50);
player->AddItem(new AttackBoost("공격력 포션" , 10 , 1));
std::cout << "남은 골드: " << player->GetGold( ) << " G" << std::endl;
}
else {
std::cout << "골드가 부족합니다." << std::endl;
}
}
//랜덤박스. 체력 포션(10%), 공격력 포션(10%), 강화석(20%), 5G(20%), 꽝(40%)
else if ( choice == 3 ) {
if ( player->GetGold( ) >= 10 ) {
player->UseGold(10);
std::cout << "랜덤 박스 오픈!" << std::endl;
std::random_device rd;
std::mt19937 gen(rd( ));
std::uniform_int_distribution<int> dis(1 , 100);
int randNum = dis(gen);
if ( randNum <= 10 ) {
std::cout << "체력 포션 당첨!" << std::endl;
player->AddItem(new HealthPotion("체력 포션" , 50 , 1));
}
else if ( randNum <= 20 ) {
std::cout << "공격력 포션 당첨!" << std::endl;
player->AddItem(new AttackBoost("공격력 포션" , 10 , 1));
}
else if ( randNum <= 40 ) {
std::cout << "강화석 당첨!" << std::endl;
player->AddItem(new EnhanceStone("강화석" , 1));
}
else if ( randNum <= 60 ) {
std::cout << "5G 당첨!" << std::endl;
player->AddGold(5);
}
else {
std::cout << "ㅋ" << std::endl;
}
}
else {
std::cout << "골드가 없습니다. 돈을 벌어오세요." << std::endl;
}
}
else if ( choice != 0 ) {
std::cout << "숫자를 다시 입력하세요." << std::endl;
}
}
//OpenShop 함수 -> 전투루프 끝나고 상점 방문 시 호출.
void Shop::OpenShop(Character* player) {
int choice = -1;
while ( choice != 0 ) {
ShowItems( );
std::cout << "번호를 입력하세요: ";
std::cin >> choice;
}
if ( choice != 0 ) {
BuyItem(player , choice);
}
}
현재 Item 로직으로는 구매하였을 때 개수가 추가되는 걸 구현하기가 어려워서 다음과 같이 수정하였음
//Item.h에 다음과 같이 AddCount 함수를 선언하고
void AddCount(int amount) { count += amount; }
//Character.cpp
//...
//인벤토리 기능 구현 위해서 추가, AddItem 함수가 호출될 때 중복 검사
void Character::AddItem(Item* newItem) {
for ( Item* item : inventory ) {
if ( item->getName() == newItem->getName()) {
item->AddCount(newItem->getCount());
std::cout << newItem->getName( ) << "을(를) 획득했습니다." << std::endl;
delete newItem;
return;
}
}
inventory.push_back(newItem);
std::cout << newItem->getName( ) << "을(를) 획득했습니다." << std::endl;
}
AddItem을 위와 같이 수정했음.
//Item.h
//강화석
class EnhanceStone : public Item {
public:
EnhanceStone(std::string name , int count = 1)
: Item(name , count) {
}
void use(Character* character) override;
};
//Item.cpp
void EnhanceStone::use(Character* character) {
if ( count <= 0 ) return;
count--;
std::cout << "무기 장착 시스템, 강화 시스템 추가 예정" << std::endl;
}
아이템 판매와 구매 기능을 구현하기 위해 다음과 같이 수정하였음.
//Character.h
//Item* 해제 위한 소멸자, 인벤토리 기능
~Character();
void AddItem(Item* item);
void ShowInventory( ) const;
void SellItem(int index);
void RemoveItem(int index);
int GetInventorySize( ) const;
Item* GetItem(int index) const;
//Character.cpp
void Character::ShowInventory( ) const {
std::cout << "현재 소지 골드 : " << gold << " G" << std::endl;
std::cout << "=== [ 인벤토리 ] ===" << std::endl;
if ( inventory.empty( ) ) {
std::cout << "(비어 있음)" << std::endl;
return;
}
for ( int i = 0; i < inventory.size( ); ++i ) {
std::cout << i + 1 << ". " << inventory[i]->getName( ) << " (" << inventory[i]->getCount( ) << "개) "
<< "(" << inventory[i]->getSellPrice( ) << " G" << std::endl;
}
}
void Character::SellItem(int index) {
if ( index < 0 || index >= inventory.size( ) ) {
std::cout << "잘못된 번호를 입력했습니다." << std::endl;
return;
}
Item* item = inventory[index];
int sellPrice = item->getSellPrice( );
AddGold(sellPrice);
item->AddCount(-1);
}
void Character::RemoveItem(int index) {
if ( index < 0 || index >= inventory.size( ) ) return;
delete inventory[index];
inventory.erase(inventory.begin( ) + index);
}
int Character::GetInventorySize( ) const {
return inventory.size( );
}
Item* Character::GetItem(int index) const {
if ( index < 0 || index >= inventory.size( ) ) return nullptr;
return inventory[index];
}
//Item.h
//아이템 판매를 위한 가상 함수 추가
virtual int getSellPrice( ) const { return 1; }
//Shop.h
#pragma once
class Character;
class Shop
{
public:
//아이템 정보 출력, 아이템 선택 구매
void ShowItems( ) const;
void BuyItem(Character* player , int choice);
//상점을 호출 인터페이스
void OpenShop(Character* player);
};
#include "Shop.h"
#include "../Character.h"
#include "Item.h"
#include "ItemManager.h"
#include "../../../FrameWork.h"
void Shop::ShowItems( ) const
{
std::cout << "\n======== [ 상 점 ] ========" << std::endl;
std::cout << "1. 체력 포션 (50G)" << std::endl;
std::cout << "2. 공격력 포션 (50G)" << std::endl;
std::cout << "3. 랜덤 박스 (10G)" << std::endl;
std::cout << "4. 아이템 판매" << std::endl;
std::cout << "0. 상점 나가기" << std::endl;
std::cout << "=========================" << std::endl;
}
//1~3 아이템 구입
void Shop::BuyItem(Character* player , int choice) {
if ( choice == 1 ) {
if ( player->GetGold( ) >= 50 ) {
player->UseGold(50);
player->AddItem(ItemManager::getInstance()->CreateItem(ItemType::HealthPotion, 1));
std::cout << "남은 골드: " << player->GetGold( ) << " G" << std::endl;
}
else {
std::cout << "골드가 부족합니다." << std::endl;
}
}
else if ( choice == 2 ) {
if ( player->GetGold( ) >= 50 ) {
player->UseGold(50);
player->AddItem(ItemManager::getInstance()->CreateItem(ItemType::AttackBoost, 1));
std::cout << "남은 골드: " << player->GetGold( ) << " G" << std::endl;
}
else {
std::cout << "골드가 부족합니다." << std::endl;
}
}
//랜덤박스. 체력 포션(10%), 공격력 포션(10%), 강화석(20%), 5G(20%), 꽝(40%)
else if ( choice == 3 ) {
if ( player->GetGold( ) >= 10 ) {
player->UseGold(10);
std::cout << "랜덤 박스 오픈!" << std::endl;
std::random_device rd;
std::mt19937 gen(rd( ));
std::uniform_int_distribution<int> dis(1 , 100);
int randNum = dis(gen);
if ( randNum <= 10 ) {
std::cout << "체력 포션 당첨!" << std::endl;
player->AddItem(ItemManager::getInstance()->CreateItem(ItemType::HealthPotion, 1));
}
else if ( randNum <= 20 ) {
std::cout << "공격력 포션 당첨!" << std::endl;
player->AddItem(ItemManager::getInstance()->CreateItem(ItemType::AttackBoost, 1));
}
else if ( randNum <= 40 ) {
std::cout << "강화석 당첨!" << std::endl;
player->AddItem(ItemManager::getInstance()->CreateItem(ItemType::EnhanceStone, 1));
}
else if ( randNum <= 60 ) {
std::cout << "5G 당첨!" << std::endl;
player->AddGold(5);
}
else {
std::cout << "꽝" << std::endl;
}
}
else {
std::cout << "골드가 없습니다. 돈을 벌어오세요." << std::endl;
}
}
else if ( choice == 4 ) {
int sellChoice = -1;
while ( sellChoice != 0 ) {
player->ShowInventory( );
std::cout << "판매할 아이템 번호를 입력하세요 :" << std::endl;
std::cout << "0. 뒤로가기";
std::cin >> sellChoice;
if ( sellChoice > 0 && sellChoice <= player->GetInventorySize( ) ) {
int index = sellChoice - 1;
Item* soldItem = player->GetItem(index);
if ( soldItem != nullptr ) {
int price = soldItem->GetSellPrice( );
player->AddGold(price);
soldItem->AddCount(-1);
if ( soldItem->GetCount( ) <= 0 ) {
player->RemoveItem(index);
}
}
}
else if ( sellChoice != 0 ) {
std::cout << "잘못된 번호입니다." << std::endl;
}
}
}
else if ( choice != 0 ) {
std::cout << "숫자를 다시 입력하세요." << std::endl;
}
}
//OpenShop 함수 -> 전투루프 끝나고 상점 방문 시 호출.
void Shop::OpenShop(Character* player) {
int choice = -1;
while ( choice != 0 ) {
ShowItems( );
std::cout << "번호를 입력하세요: ";
std::cin >> choice;
}
if ( choice != 0 ) {
BuyItem(player , choice);
}
}
-3. ItemManager (확장성 만들어가면서 아이템 추가)
아이템을 enum class로 관리하기 위해 다음과 같이 추가했음. 현재 체력포션, 공격력 포션, 강화석, 무기, 장비 정도가 있음.
#pragma once
class Item;
enum class ItemType {
HealthPotion,
AttackBoost,
EnhanceStone,
Weapon,
Armor
};
class ItemManager {
private:
static ItemManager* instance;
ItemManager( ) {}
public:
static ItemManager* getInstance( );
Item* CreateItem(ItemType type , int count = 1);
};
#include "ItemManager.h"
#include "Item.h"
#include "Equipment/Weapon.h"
#include "EquipMent/Armor.h"
#include "EquipMent/Equipment.h"
ItemManager* ItemManager::instance = nullptr;
ItemManager* ItemManager::getInstance( ) {
if ( instance == nullptr ) {
instance = new ItemManager( );
}
return instance;
}
Item* ItemManager::CreateItem(ItemType type , int count) {
switch ( type ) {
case ItemType::HealthPotion:
return new HealthPotion("체력 포션" , 50 , count, 50);
case ItemType::AttackBoost:
return new AttackBoost("공격력 포션" , 10 , count, 50);
case ItemType::EnhanceStone:
return new EnhanceStone("강화석" , count, 20);
case ItemType::Weapon:
return new BaseSword("기본 검" , 20, count, 100);
case ItemType::Armor:
return new BaseArmor("기본 갑옷" , 50, count, 100);
default:
return nullptr;
}
}
ItemManager에서는 Equipment.h 의 자식 클래스인 Weapon, Armor를 받아와서 BaseSword, BaseArmor 형태로 enum class 로 만들어 두었음.
//Item.h
public:
//아이템 생성자
Item(std::string itemName, int count, int price)
: name(name), count(count), sellPrice(price) {
}
이후 이제서야 전투 중 아이템 메뉴를 열어 사용가능한 아이템을 사용할 수 있는 로직을 작성함.
//Item.h
//사용 가능한 아이템만 전투 중 인벤토리에 출력하기 위해 가상함수 추가
virtual bool isUsableInBattle( ) const { return false; }
//...
class HealthPotion : public Item {
//...
bool isUsableInBattle() const override {return true;}
bool Character::UseItemInBattle( ) {
vector<int> usableItems;
std::cout << "==== [ 사용 가능한 아이템 ] ====" << std::endl;
int displayIndex = 1;
for ( int i = 0; i < inventory.size( ); ++i ) {
if ( inventory[i]->isUsableInBattle( ) ) {
cout << displayIndex << ". " << inventory[i]->GetName( ) << " (" << inventory[i]->GetCount( ) << "개)" << std::endl;
usableItems.push_back(i);
displayIndex++;
}
}
if ( usableItems.empty( ) ) {
cout << "(비어 있음)" << endl;
return false;
}
std::cout << "0. 뒤로 가기" << std::endl;
std::cout << "사용할 아이템 번호를 입력하세요: ";
int itemChoice;
cin >> itemChoice;
if ( itemChoice == 0 ) {
return false;
}
if ( itemChoice > 0 && itemChoice < displayIndex ) {
int targetInventoryIndex = usableItems[itemChoice - 1];
Item* selectedItem = inventory[targetInventoryIndex];
selectedItem->use(this);
if ( selectedItem->GetCount( ) <= 0 ) {
RemoveItem(targetInventoryIndex);
}
return true;
}
std::cout << "번호를 다시 입력하세요." << std::endl;
return false;
}
(4) 저녁 스크럼:
팀원들과 함께 오늘 한 작업 내용을 공유하고 점검. 컴파일 에러 문제, 변수명 통합, 헤더 파일 정리 등을 했음.
현재 몬스터 드랍테이블이 미완성 된 것을 확인 : 아직 아이템이 존재하지 않아서 강화와 인벤토리에 추가 진행이 어려움을 파악했음. 다음 날 오전 스크럼때 이를 다시 확인하고 이번에는 최대한 작은 단위로 분업해서 프로젝트를 진행하기로 이야기가 되었음.
(5) 트러블 슈팅/해결 및 개선: 역할 분담,
역할 분담을 최대한 세분화해서 업무의 모호함을 제거하기. (아이템이면 아이템 사용, 아이템 생성, 아이템 드랍, 아이템 종류 등, 세부적으로 구분해놓고 업무분담하기)
+ 문서를 통한 커뮤니케이션(진행 상황 확인, 문제상황 빠른 공유)
코딩을 잘하고 그런 것도 중요하지만 결국 팀 단위로 프로젝트를 계속 진행한다는 것을 감안하면 무엇보다도 소통에 문제가 없고 원활하게 소통이 가능해야 할 것 같다.
+코드가 중복작성이 됨. 기존 Auto로 진행되었던 전투가 Manual로 변경되었는데, 두 전투 모드가 동시에 존재해서 충돌이 발생했음. --> 작성 시에 미리 소통하면서 진행하고, 작업하기 전에 새로운 버전을 dev 브랜치에서 가져오는 걸 미리 약속해놓아야 할듯.
+넘길 때 컴파일 에러가 나지 않도록 테스트 하면서 진행해야함!
'TIL' 카테고리의 다른 글
| 05.29 TIL (ch.2 팀프로젝트 day6) (0) | 2026.05.29 |
|---|---|
| 05.28 TIL (ch.2 팀프로젝트 day5) (0) | 2026.05.28 |
| 05.27 TIL (ch.2 팀프로젝트 day4) (0) | 2026.05.27 |
| 05.22 TIL (ch.2 팀프로젝트 day2) (0) | 2026.05.22 |
| 05.21 TIL (ch.2 팀프로젝트 day1) (0) | 2026.05.21 |