프로그래머스 코테 연습
팀프로젝트
TRPG 팀프로젝트에 사운드 기능을 추가하려 했다.
#include <windows.h>
PlaySound(TEXT("sound.wav"), NULL, SND_FILENAME | SND_ASYNC);

TRPG 팀프로젝트에 사운드 기능을 추가하려 했다.
#include <windows.h>
PlaySound(TEXT("sound.wav"), NULL, SND_FILENAME | SND_ASYNC);
오늘은 어제 만들었던 RpgLogger의 임시 코드를 제거하고 실제 Monster의 EMontserID를 연결해주었다. 단순 연결이라 달리 할 건 없었다.
이후 회의를 하여 전체적인 흐름도를 만들었다.
나는 도전 기능인 상점을 추가로 담당하기로 했다. 자세한 설계, 구현은 내일!
상점(구매/판매) 기능을 구현했다.
구매는 "구매 가능한 아이템 리스트 출력 → 보유 골드 출력 → 아이템 선택 → 골드가 충분하면 차감 후 인벤토리에 추가"
판매는 "내 인벤토리 리스트 출력 → 판매할 아이템/개수 선택 → 아이템 가격의 60%만큼 골드 획득, 인벤토리에서 차감"
// ShopManager.h
#pragma once
#include <vector>
#include "Inventory.h"
#include "RpgLogger.h"
extern Inventory* inventory;
extern RpgLogger rpgLogger;
class ShopManager
{
public:
// 유저에게 아이템 구매 할건지 판매 할건지
// 구매 -> 구매 가능한 리스트 출력 -> 내가 보유중인 골드 출력
// -> 어떤 아이템을 구매할지 선택 -> 충분한 골드가 있다면 골드 차감 후 인벤토리에 추가
// 판매 -> 내 인벤토리 리스트 출력 -> 어떤 것을 판매할 것 인지 선택 -> 몇 개 판매할 것인지 선택
// 아이템 가격의 60%만큼 플레이어 골드 추가, 인벤토리에서 차감
// 구매 가능한 리스트 출력
void ShowBuyableList() const;
// 구매 가능한 아이템 ID 목록 (ShowBuyableList와 동일한 순서)
std::vector<EItemID> GetBuyableItemIDs() const;
// 아이템 구매
void BuyItem(const ItemData& item, int count) const;
// 판매 가능한 리스트 출력
void ShowSellableList() const;
// 판매 가능한 아이템 ID 목록 (ShowSellableList와 동일한 순서)
std::vector<EItemID> GetSellableItemIDs() const;
// 아이템 판매
void SellItem(const ItemData& item, int count) const;
private:
};
긴 시간 동안 팀 회의로 컨벤션 및 클래스 설계를 진행했다.
내가 맡기로한 레벨업 기능이 플레이어로 합쳐져서 붕 떠버렸기 때문에 남는 단순한 기능인 로그 출력 기능을 맡았다.
// RpgLogger.h
#pragma once
#include <map>
#include <queue>
#include <string>
// 임시로 작성, 추후에 다른 파일에서 가져오기
namespace Test
{
enum class EMonsterID;
extern std::map<EMonsterID, std::string> convertMonsterString;
} // namespace Test
class RpgLogger
{
public:
// Queue에 쌓인 전체 로그 출력
void ShowLogs() const;
// 킬 로그 출력
void ShowKillLogs() const;
// Queue에 로그 추가(10개 까지), 해당 로그 바로 출력
void AddLog(std::string log);
// 몬스터를 처치했을 때 호출, 킬카운트 증가
void OnMonsterKilled(Test::EMonsterID id);
private:
static constexpr size_t MAX_SIZE = 10;
std::queue<std::string> logs;
std::map<Test::EMonsterID, int> killCounts;
};
void TestRpgLogger();
오늘은 개인 과제 제출 이후, 깃 특강과 cpp 보충?을 들었다.
짧게나마 팀 회의를 진행 → 5가지 기능 중 사다리타기로 기능 구현 담당자 정함 → 내일 다시 이어서 회의 진행 예정
각 원칙을 "어떤 코드가 부족한가"를 직접 찾고 고치는 방식으로 하나씩 확인했다.
시작 코드는 damage, durability가 public이라 외부에서 아무 값이나 대입할 수 있었다 (sword.durability = -9999;처럼). 캡슐화는 클래스 내부 데이터를 외부가 함부로 건드리지 못하게 막고, 값의 유효성은 클래스 스스로 책임지는 것이다.
raw pointer 멤버를 다룰 때 복사 생성자와 이동 생성자가 잘 이해되지 않아서, 직접 코드를 짜보면서 개념을 정리했다.
char* 멤버를 가진 Book 클래스를 직접 만들어봤다.
class Book
{
char *arr;
public:
Book(const std::string &title)
{
arr = new char[title.size() + 1];
std::strcpy(arr, title.c_str());
}
~Book() { delete[] arr; }
};
new/delete 연산자에 대해서 복습하던 중, new는 Heap 메모리에 동적으로 공간을 할당하고, 그 주소를 반환하는 연산자이고, delete는 new 연산자가 동적으로 할당한 메모리를 해제하는 연산자라고만 알고 넘어갔었는데, 조금 더 깊게 생각해보기로 했다.
int* p = new int(300);을 단순히 보면 "포인터 p에 new가 반환한 int(300)의 주소를 초기화한다"로 끝난다. 조금 더 들어가 보면,
어제 만든 개념 복습 시스템을 오늘 좀 더 다듬었다.
#include <iostream>이랑 int main() {}부터 치는 게 번거로워서, main()이 필요한 문제는 시작할 때부터 그 틀이 채워져 있게 만들었다.