2009년 9월 23일 수요일

random array

만들때마다 짜증나는 랜덤배열...


오늘은 하루종일 집안에 박혀있는 날이라 허니에게 배운 프로세싱으로 이것저것 끄적대고 있는데..

보드게임을 프로세싱으로 구현하려다가 랜덤배열을 만들일이 생겼다.

(고스톱이나 포커 등 카드게임에서의 셔플기능을 프로그래밍에서 구현하려면 거의 필수로 들어가는..)



:: 랜덤배열 ::

배열의 칸에 숫자가 랜덤으로 들어가되, 중복되는 숫자가 없도록 만드는 배열.

단순히 배열 처음부터 끝까지 랜덤한 숫자를 집어넣게 되면

중복되는 수가 생기므로, 셔플기능 구현하려다가 카드 복제기능이 되버림




그래서 대충 머릿속에서 생각나는대로 코드를 끄적여 봤더니

//--------------------------------------------------------//

// 카드 순서 정하는 함수
void cards_default_order(){

// 구현하려는 게임 특징상 카드갯수가 81장임. (무슨게임일까요?)
  for(int i=0;i<81;i++){

   temp=int(random(cards.length));
//일단 임시로 랜덤숫자를 구한 후
 
   for(int j=0;j<i;j++){
     if(ord[j]==temp){
       temp=82;
     }
// 카드 배열의 처음부터 이번에 넣으려는 카드배열까지 검색 후에
// 이번에 뽑은 랜덤수가 쓰인적이 있다면 82로 셋팅
 

   if(temp!=82){
     ord[i]=temp;
   }else{
     i--;
   }
// temp가 82가 아니라면 (이번 랜덤수가 지금까지 쓰인적이 없다면)
// 이번칸에 집어넣고, 혹시 82라면 (이번 랜덤수가 쓰인적이 있다면)
// i 감소로서 이번자리의 랜덤수를 다시 구함.

  }
//이하 81개의 칸을 모두 채울때까지 반복.
}

//--------------------------------------------------------//



음..

일단 코딩후 동작시켜본 바로는 정상적으로 잘 동작합니다.

단, 실행 횟수가 최대 무한대(겹치치 않는 랜덤수가 나올때까지 반복하므로)까지 반복할수도..

어떻게 보면 비효율적이지만, 이런 형식이 아닌 랜덤배열을 구하는 알고리즘은 잘 생각이 나질 않는군요.




P.S) 이렇게 머리아플때는 오락실 펌프가 최고

P.S2) 위 알고리즘의 최선, 최악, 평균 등의 복잡도를 구해주시면 신림 백순대 쏩니다.

P.S3) 위에는 안좋은것만 써놓았는데.. 최적의 경우에는 그 어떤 랜덤배열보다도 실행횟수가 가장 짧아질 수 있습니다. 물론 최악의 경우의 리스크가 좀 크긴 하지만요..

7 개의 댓글:

  1. 신림백순대라... 그럼 신림에서 사주시나여???



    서울에서 사주시는거라면... 차비로 먹고 말겠습니다 ㅋㅋ

    답글삭제
  2. @MaJ3stY - 2009/09/24 00:54
    그럼 배달로 보내주리? ㅋㅋ



    나중에 올라오면 연락혀~ ㅎ

    답글삭제
  3. 음~ 형이 직접 내려오신다면... 신림 저희집에서 가까워요 ㅋㅋㅋ



    같이 원조집 가서 먹어요 ㅎㅎㅎ



    올라가면 연락할께요~ ㅎㅎ

    답글삭제
  4. 실제 카드 셔플을 프로그램으로 그대로 모방해 보는 것도 하나의 방법입니다.



    일단 배열에 1~82까지 수를 순서대로 채운 다음에...



    1~82의 랜덤한 i, j 값을 각각 구합니다. i,j는 서로 다른 수가 되도록 하면 더 좋겠죠. 그런다음 swap(i, j) 즉 i와 j번째의 수를 서로 자리바꿈 합니다.



    이런 랜덤 자리바꿈 횟수를 늘리면 늘릴수록 숫자가 잘 섞이겠죠.





    int random(int max_num)

    {

    return (double)rand() / (RAND_MAX + 1) * max_num;

    }



    int _tmain(int argc, _TCHAR* argv[])

    {

    const int MAX_NUM = 82;

    int arr[MAX_NUM];



    int n;

    for (n = 1; n <= MAX_NUM; ++n)

    arr[n-1] = n;





    int i, j;

    srand( (unsigned int)time(NULL) );



    for (n = 1; n <= 10000; ++n)

    {

    i = random(MAX_NUM);

    j = random(MAX_NUM);

    std::swap(arr[i], arr[j]);

    }



    // print

    for (n = 0; n < MAX_NUM; ++n)

    printf("%d ", arr[n]);



    printf("\n");



    return 0;

    }

    답글삭제
  5. @시즈하 - 2009/09/26 06:23
    아.... 왜 이생각을 못했을까요;



    이게 정답인듯..



    nice idea, 감사합니다 :)

    답글삭제
  6. @MaJ3stY - 2009/09/24 21:34
    아 ㅋ 원조집에서 싸서 갖구와 ㅋㅋ

    답글삭제
  7. trackback from: 랜덤배열 카드셔플
    은근히 랜덤배열 찾는분들이 많더군요. 일전에 썼던 글의 내용을 조금 갖고와서 살짝 정리를 해보자면, 1. 이건 processing 에서 쓰던 코딩입니다. (자바문법을 따라감) :: 이 알고리즘의 문제점과 기타 설명은 (http://blueh4g.textcube.com/20) 을 참조해주세요. //--------------------------------------------------------// void cards_default_order(){..

    답글삭제