

기존 GameManager는 다양한 역할을 가지고 있었다.
UIManager를 도입하여 화면 출력코드를 UIManager로 이동시켰다.
BattleService에 있는 출력문도 UIManager에서 담당하기로 하였다.
전투 메뉴 선택같은곳에서는 _getch를 사용하고, 캐릭터 이름 설정에서는 cin을 사용했어서 모두 Enter를 눌러야하는 cin으로 통일했다.
BattleResult BattleService::battle(Character* p, Monster* m) {
player = p;
monster = m;
RewardManager* rewardManager = RewardManager::getInstance();
BattleResult result = rewardManager->generateRewards(monster);
uiManager.showBattleStart(monster->isBossMonster());
uiManager.showMonsterInfo(
monster->getName(),
monster->getMobInfo(),
monster->getHealth(),
monster->getMaxHealth(),
monster->getAttack()
);
uiManager.waitForKeyPress();
if (monster->isBossMonster()) {
return bossBattle();
} else {
return normalBattle();
}
}
normalBattle() (기존 턴제 전투 유지)
bossBattle() 전체 흐름
BattleResult BattleService::bossBattle() {
uiManager.showBossEncounter(monster->getName());
std::string bossName = monster->getName();
auto quizzes = getBossQuizzes(bossName);
std::random_device rd;
std::mt19937 rng(rd());
std::shuffle(quizzes.begin(), quizzes.end(), rng);
int playerCorrect = 0;
const int MAX_ROUNDS = 3;
for (int i = 0; i < MAX_ROUNDS; ++i) {
uiManager.showQuizRound(i + 1, MAX_ROUNDS);
std::string question = quizzes[i].first;
std::string correct = quizzes[i].second;
std::string answer = uiManager.askQuizAnswer(question);
std::string lowerAnswer = toLower(answer);
std::string lowerCorrect = toLower(correct);
bool isCorrect =
lowerAnswer.find(lowerCorrect) != std::string::npos ||
lowerCorrect.find(lowerAnswer) != std::string::npos;
if (isCorrect) {
playerCorrect++;
uiManager.showQuizResult(true, "정답!", playerCorrect, i + 1);
} else {
uiManager.showQuizResult(false, "틀렸습니다! 정답: " + correct, playerCorrect, i + 1);
}
if (i < MAX_ROUNDS - 1) {
Sleep(1500);
}
}
auto* rewardManager = RewardManager::getInstance();
BattleResult result = rewardManager->generateRewards(monster);
result.playerWon = (playerCorrect == MAX_ROUNDS);
result.turnCount = MAX_ROUNDS;
uiManager.showQuizFinalResult(result.playerWon, playerCorrect, MAX_ROUNDS);
uiManager.waitForKeyPress();
return result;
}
내일은 보스별 퀴즈셋 정의, 입출력 다듬고 자동버전 하나 더 만들면 될 것같다.
PointerLich는 포인터, 팀 프로젝트/폴리 드래곤 보스는 다형성 관련 문제를 낸다.
☆오늘의 최고 시간먹는 괴물☆
몬스터정보를 한글로 출력하면 감싸고 있는 박스가 밀렸다.
수많은 노력의 흔적들 (실제로는 오십장이 넘음)





clearScreen함수로 콘솔창을 비우게 되는데 이때 보스몬스터를 처치하고나서 나오는 메시지가 지워지고 다음 페이즈로 넘어가서 안보이는거였다.clearScreen위치를 수정해서 해결하였다.playerName이나 monsterName에 따라서 테두리를 동적으로 변경해주어야 했다.
기존 한글이름

기존 영어이름

const int BOX_WIDTH = 60;
int displayWidth = 0;
// 플레이어 이름의 표시 너비 계산
for (size_t i = 0; i < playerName.length(); ) {
unsigned char c = playerName[i];
if ((c & 0x80) == 0) {
// ASCII (영문/숫자) - 1칸
displayWidth += 1;
i += 1;
} else {
// 한글 등 멀티바이트 - 2칸
displayWidth += 2;
// UTF-8에서 한글은 3바이트
i += 3;
}
}
// "의 턴" 추가: 의(2칸) + 공백(1칸) + 턴(2칸) = 5칸
displayWidth += 5;
int totalPadding = BOX_WIDTH - displayWidth;
int leftPadding = totalPadding / 2;
int rightPadding = totalPadding - leftPadding;
std::cout << "╔════════════════════════════════════════════════════════════╗\n";
std::cout << "║" << std::string(leftPadding, ' ') << turnTitle << std::string(rightPadding, ' ') << "║\n";
std::cout << "╚════════════════════════════════════════════════════════════╝\n";
std::cout << "\n⚔️ " << playerName << "의 공격!\n";
std::cout << "→ " << monsterName << "에게 " << damage << " 데미지!\n";
if (isMonsterDead) {
std::cout << "→ " << monsterName << "을(를) 쓰러뜨렸다!\n";
}
변경 후


이모지를 제거하고 한글은 따로 처리를 해서 해결하였다.