본문 바로가기
C++

CS) RandomEngine 구현하기

by 준모 2025. 1. 23.

 

 

프로젝트를 진행하다보면 랜덤값이 필요한 경우가 많다.

 

예를들어 몬스터를 처치했을 경우에 아이템이 드랍될 확률을 구할 때,

 

또, 어떤 아이템이 드랍될지 확률을 통해 결정할 때 등등 다양한 경우들 있다.


 

std::random_device

C++에서 난수 생성에 사용되는 클래스 중 하나로,

 

진정한 난수(True Random Number)를 생성할 수 있는 기능을 제공한다.

#include <iostream>
#include <random>

int main() {
    // std::random_device 인스턴스 생성
    std::random_device rd;

    // 난수 생성
    for (int i = 0; i < 5; ++i) {
        std::cout << rd() << std::endl;
    }

    return 0;
}

 

 

실행할 때마다 다른 난수를 생성하지만, 

 

출력값은 매우 큰 숫자가 될 수 있다. (std::random_device::result_type은 unsigned int).

 

또한 std:random_device는 하드웨어 난수를 생성하기 때문에 일반적으로 속도가 느리다.

 

따라서 빠른 난수가 필요한 경우에는 std:mt19937과 같은 유사난수 엔진과 조합하여 사용하는 것이 바람직하다.

#include <iostream>
#include <random>

int main() {
    std::random_device rd;                // 랜덤 디바이스
    std::mt19937 gen(rd());               // Mersenne Twister 초기화
    std::uniform_int_distribution<> dis(1, 100); // 1~100 사이 균등 분포

    for (int i = 0; i < 5; ++i) {
        std::cout << dis(gen) << std::endl; // 난수 출력
    }

    return 0;
}

 

std::random_device를 사용하여 시드 값을 생성하면,

 

std::mt19937도 더 예측 불가능한 난수를 생성할 수 있다.


결론

std:random_device는 하드웨어 난수 생성기를 활용하여 진정한 난수를 생성하는데 사용되지만, 

 

속도가 느리기 때문에 std:mt19937같이 고속의 유사난수 엔진과 조합하여 사용하는 것이 좋다.


예시

아래는 몬스터를 처치했을 때 20% 확률로 서로다른 확률의 아이템을 뽑아 드랍하는 로직이다.

 

함수의 윗 부분은 20%의 학률을 판별하는 부분이다.

 

randomNum가 1~5 사이의 난수로 설정되는데, 5일 경우에만 드랍이 되도록 구현하였다.

 

 

함수의 아래 부분은 아이템별 드랍될 확률을 통해 어떤 아이템이 드랍될 지 정해주는 부분이다.

 

우선 _TotalProbability는 각각의 아이템의 드랍확률의 총 합이다.

 

아이템의 드랍확률은 아이템 가격에 따라 차등하게 주었으며, 가격이 높을 수록 적은 확률을 넣어주었다.

Item* DropManager::DropItem()
{
    std::uniform_real_distribution<> dist; 
    dist.param(std::uniform_int_distribution<>::param_type(1, 5));
    int randomNum = dist(gen);	// 1~5 사이의 난수 생성
	
    // 20% 확률로 Drop
    if ( randomNum != 5 )
        return nullptr;

//////////////////////////////////////////////////////////////////////////////////////////////////////////

    dist.param(std::uniform_int_distribution<>::param_type(1 , _TotalProbability));
    randomNum = dist(gen); // 1 , _TotalProbability 사이의 난수 생성

    int cumulativeRate = 0;
    for ( size_t i = 0; i < _Items.size(); i++ )
    {
        cumulativeRate += _Probability[i];

        if ( randomNum <= cumulativeRate )
        {
            return _Items[i];
        }
    }

    return nullptr;
}

 

'C++' 카테고리의 다른 글

CS) STL 기본구조  (0) 2025.02.03
CS) 싱글톤 패턴  (1) 2025.01.08
CS) 가상함수, 순수가상함수  (0) 2025.01.07
CS) SOLID 원칙  (0) 2025.01.07
CS) 스마트포인터  (0) 2025.01.07