ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 랜덤함수
    프로그래밍 언어 C, C++ 2021. 1. 17. 22:07
    728x90

    랜덤(Random), 난수란게 순서나 규칙이 눈에 보이지 않아야 하며, 연속적인 임의의 수여야 합니다.

    이전과 이후의 수열이 예측되지 않도록 독립적인 임의성을 가져야 하며,

    수의 범위내에 있는 모든 수가 최대한 동일한 확률에 가까워야 하는 분포도여야 한다.


    다행인건 기본적인 함수는 제공해준다.

    게임에서 간단하게 쓰려면 이 정도까지만 해도 괜찮을(?)지도 모른다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
     
    void main()
    {
        // 앱이 구동되면 한번만 호출.(seed 값 1번 설정)
        // main이 호출 되는 시점 또한 랜덤하기 때문에,
        // time(NULL)이 seed값으로 무난하게 쓰인다.
        srand((unsigned)time(NULL));
        
        // 10의 랜덤 수를 구한다.
        for(int i=0; i<10; i++)
            printf("rand[%d] = %d\n", i, rand());
    }
     
    cs

     

    근데 뭔가 찜찜하다..

    게임 개발하면서 최소 한번 이상은 랜덤에 대해 고민하게 될것이다.

    공격 크리티컬 판정, 회피율, 아이템 드랍율, 강화성공, 등등

    지금 당장은 게임에 이런저런 복합적인 요소들이 들어가지 않더라도,

    언젠가는 인기있는 게임자가 될테니...그때를 대비하여서라도 준비를 해두는것도 괜찮을 것이다.

     

    함수 rand()는 int 자료형의 크기가 2바이트(=16비트)일때 만들어진 함수다.

    그래서 반환되는 랜덤 생성 범위가 0 ~ 32,767 밖에 안된다.

    만드는 게임에 따라 이 정도면 충분할 수도 있고, 많이 부족할수도 있다.

    수학을 조금? 아는 사람이라면 분포도가 고르지 못하다는것도 대충 어림짐작 할 것이다.

     

    그럼 직접 간단히 만든다면, 대충 이와 비슷하지 않을까?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
     
    unsigned int seed;
    void SRAND(unsigned int s = 5323)
    {
        seed = s;
    }
     
    unsigned RAND()
    {
        seed = 8253729 * seed + 2396403;
        return seed % 32768;
    }
     
    void main()
    {
        SRAND();
        
        for(int i=0; i<10; i++)
            printf("rand[%d] = %d\n", i, RAND());
    }
     
    cs

    근데 이건 pseudo-random number generator(PRNG)란 거다.

    일단 아이디어가 떠오르면 만들려고 하지 말고, 검색부터 해보자.

    왠만한건 사람들이 다 만들어 놓았다.

    WELL Random number generator

    링크를 타고 가면 4개가 보일것인데, 어느것을 사용하더라도

    더 나은 결과물을 얻게 된다. 링크 타고 가보면 딱히 어려운 부분도 없어서 그대로 쓰기에도 딱 좋다.

    www.iro.umontreal.ca/~panneton/WELLRNG.html

     

    WELL Random number generator

     

    www.iro.umontreal.ca

    쉐이더토이

    쉐이더 프로그래밍하는곳에서도 다양하게 만든 랜덤함수들을 보게 될것이다.

    시간을 이용하기도 하고, perlin noise같은 여러 노이즈를 활용하는 등의 다양한 랜덤을 볼수 있다.

    이 부분은 지문이 너무 길어져서..;;

    공식 사이트 www.shadertoy.com/

     

    Shadertoy BETA

     

    www.shadertoy.com

    페이스북에 국내 모임도 있으니 참고하면 좋을것이다.

    www.facebook.com/groups/1339783682699494/

     

    Shadertoy Korea

    Shadertoy로 재밌고 신나게 놀아보자는 겁니다.

    www.facebook.com

    다시, 자작용 함수를 고민해보자.

    rand()함수의 한계를 극복하고, 램덤 생성 수의 범위를 넓혀 4바이트짜리로 만들어 보는 것이다.

    1
    2
    3
    4
    5
    6
    7
    unsigned int RAND()
    {
        int hi = rand();
        int lo = rand() + rand();
        return (hi << 16+ lo;
    }
     
    cs

    이 함수는 4바이트의 램덤수가 생성되지만, 균일한 분포가 확률적이지가 않다.

     

    4바이트는 16진수로 표시하면 0x00000000 ~ 0xFFFFFFFF 이렇고, 8자리다.

    각 자리 0x0 ~ 0xF 랜덤하게 생성하고 밀어붙이는 것이다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    unsigned int RAND()
    {
        unsigned int n = 0;
        for(int i=0; i<8; i++)
        {
            n <<= 4;
            n |= rand() % 0x10;    // 0x0 ~ 0xF 나오도록 0x10으로 나머지 연산
        }
        return n;
    }
     
    cs

    대충 괜찮은 함수 같다. 8바이트 짜리를 생성한다면 for에서 16번을 호출하고 타입만 바꾸면 된다.

     

    반복문을 줄이고 싶으면, 각 자리 0x00 ~ 0xFF 랜덤하게 생성하고 밀어 붙이는 것이다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    unsigned int RAND()
    {
        unsigned int = n = 0;
        for(int i=0; i<4; i++)
        {
            n <<= 8;
            n |= rand() % 0x100;// 0x00~0xFF 나오도록 0x100으로 나머지연산
        }
        return n;
    }
     
    cs

     

    랜덤에는 정답이 없지만 그렇다고 딱히 어려운것은 없다.

    다만, 본인이 만들고 있는 게임에 적당한 랜덤 함수를 찾아내는것이 어렵다.

     

    1
    2
    3
    #define randomM1to1    ( (rand() / (float)0x3fff- 1.0f )
    #define random0to1    ( rand() / (float)0x7fff )
     
    cs

    그럼 매크로만 남기고 글을 마친다.

    '프로그래밍 언어 C, C++' 카테고리의 다른 글

    visual studio c/c++에서 보기 싫은 인라인  (0) 2022.12.14
    문자열 처리 - 한글 개념  (0) 2021.01.22
    정의 vs 선언 2  (0) 2021.01.16
    정의 vs 선언 1  (0) 2021.01.16
    프로그래머 워밍업 2  (0) 2021.01.09
Designed by Tistory.