43. 경험치 누적·레벨업의 비원자 처리 (C#)
난이도 중 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// 시나리오: MMORPG 성장 — 경험치 획득과 레벨업(다중 레벨 상승) 처리
//
// 서버 권위(server-authoritative)로 경험치를 관리한다. 한 플레이어는 여러 경로에서
// 거의 동시에 경험치를 얻을 수 있다(파티 몹 처치 보상, 퀘스트 완료 보상, 이벤트 등).
// 경험치가 다음 레벨 요구치를 넘으면 레벨이 오르고, 한 번에 여러 레벨이 오를 수도
// 있다(대량 경험치). 레벨업 시 스탯 포인트/HP 상한 등이 증가한다.
//
// 요구사항:
// - 부여한 총 경험치는 유실·이중 반영 없이 정확히 누적되어야 한다.
// - 레벨은 건너뛰지 않고 순차적으로 올라야 하며, 레벨업 보상(스탯 등)은 오른 레벨
// 수만큼 정확히 한 번씩만 적용되어야 한다.
// - 서로 다른 경로의 동시 경험치 부여에도 정확해야 한다.
//
// 다수의 게임 로직 스레드가 같은 플레이어에게 경험치를 부여할 수 있다. 아래를 검토하라.
using System;
public sealed class PlayerProgress
{
public long Xp; // 현재 레벨 기준 누적 경험치
public int Level = 1;
public int StatPoints;
// 레벨 L 에서 L+1 로 가는 데 필요한 경험치
private static long XpToNext(int level) => 100L * level;
// 로직 스레드: 경험치 부여 + 레벨업 처리
public void GrantXp(long amount)
{
Xp = Xp + amount; // (A) 경험치 누적
while (Xp >= XpToNext(Level)) // (B) 여러 레벨 동시 상승 처리
{
Xp -= XpToNext(Level);
Level++; // (C)
StatPoints += 5; // 레벨업 보상
}
}
public (int level, long xp, int sp) Snapshot() => (Level, Xp, StatPoints);
} 결함 코드 · C++
// 시나리오: MMORPG 성장 — 경험치 획득과 레벨업(다중 레벨 상승) 처리 (C++)
//
// 서버 권위로 경험치를 관리한다. 한 플레이어는 여러 경로(파티 처치 보상, 퀘스트,
// 이벤트)에서 거의 동시에 경험치를 얻을 수 있다. 경험치가 요구치를 넘으면 레벨이
// 오르고, 한 번에 여러 레벨이 오를 수도 있다. 레벨업 시 스탯 포인트가 증가하고,
// 특정 레벨에서 신규 스킬 객체를 언락 목록에 추가한다.
//
// 요구사항:
// - 부여한 총 경험치는 유실·이중 반영 없이 정확히 누적.
// - 레벨은 건너뛰지 않고 순차 상승, 보상은 오른 레벨 수만큼 정확히 한 번씩.
// - 서로 다른 경로의 동시 경험치 부여에도 정확해야 한다.
//
// 다수의 로직 스레드가 같은 플레이어에게 경험치를 부여한다. 진행 상태를 읽는
// 스레드는 GetUnlocked 로 언락된 스킬 목록을 순회한다. 아래를 검토하라.
#include <vector>
#include <string>
#include <cstdint>
class PlayerProgress {
public:
// 로직 스레드: 경험치 부여 + 레벨업 처리
void GrantXp(int64_t amount) {
xp_ = xp_ + amount; // (A) 경험치 누적
while (xp_ >= XpToNext(level_)) { // (B) 다중 레벨 상승
xp_ -= XpToNext(level_);
level_++; // (C)
statPoints_ += 5;
if (level_ % 10 == 0)
unlockedSkills_.push_back("skill_L" + std::to_string(level_)); // (D)
}
}
// 다른 스레드: 언락된 스킬 순회(UI/판정)
const std::vector<std::string>& GetUnlocked() const { return unlockedSkills_; }
int Level() const { return level_; }
int64_t Xp() const { return xp_; }
private:
static int64_t XpToNext(int level) { return 100LL * level; }
int64_t xp_ = 0;
int level_ = 1;
int statPoints_ = 0;
std::vector<std::string> unlockedSkills_;
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.