avatar

大兜

右手寫程式,左手寫音樂

~C語言程式設計~亂數不重複函數~

今天完成的XDD 還是熱的
這大概是黃金版本了XD(自以為)
放上來當作開放式原碼吧^^~
想套的人可以拿去=3=

ps.函數什麼東西都可以回傳,包括指標> <

使用方法:
1.在main之前先宣告 int* getRand(int,int,int);
2.在main後面複製貼上函數
3.在main裡呼叫時請寫下面兩行:

int *randNum;  //這個等等要拿來指向getRand傳回的東西
randNum = getRand(MIN,MAX,NUM);  //randNum指向getRand回傳的指標
/*MIN放入最小值,MAX放最大值,NUM放你想要幾個亂數

例如:

int *randNum;
randNum = getRand(1,42,6);
//這樣就是樂透開獎啦~~~

而得到的六個亂數會被放在randNum[0],ransNum[1],randNum[2]…randNum[5]

下面是原碼:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MIN 1  //代表不重複亂數的最小值 
#define MAX 42  //代表不重複亂數的最大值 
#define NUM 6  //代表需要幾個不重複亂數的個數
//例如這個預設值代表從1到42選6個不重複的亂數(就是樂透開獎啦!) 
int* getRand(int,int,int);  //宣告一個函數可以input三個整數然後回傳一個整數指標 
int main(void){ 
    int *randNum;  //這個等等要拿來指向getRand傳回的東西 
    int i;  //迴圈專用 
    randNum = getRand(MIN,MAX,NUM);  //randNum指向getRand回傳的指標
    for(i=0;i<NUM;i++){  //印出來
        printf("%d\n",*(randNum+i));
    }
    getchar();
    return 0;
}
int* getRand(int min, int max, int num){
    int tol = max - min +1;  //算出總數
    int a[30000];  //放min~max的所有數字 
    static int b[30000];  //放取出的亂數 
    int i,j;
    for(i=0;i<tol;i++){  //跟電腦要記憶格放數字,從小排到大放進a[0]~a[tol-1] 
        *(a+i) = min+i;
    }
    srand(time(0));
    int ctr;  //這只是個容器,拿來裝a[n]裡的n,而這個n是用亂數製造的 
    for(i=0;i<num;i++){
        ctr = rand()%(tol-i);
        b[i] = a[ctr];  //把抓好的亂數丟到b裡面 
        for(j=ctr;j<(tol-1-i);j++){  //這是整個不重複亂數函數的經髓所在!
            a[j] = a[j+1];  //很微妙的通通往前移動一格 
        }
    }
    return b;
}

2015-04-15 更新

這篇是是筆者大一的時候寫的呢,想不到那時候還會加上無謂的表情符號,根本小屁孩啊XD

事隔多年,如果還是要做同樣的功能,可能就會用洗牌的方式了吧:

#include <stdlib.h>
#include <time.h>
#define SWAP(x, y) do{ typeof(x) tmp = x; x = y; y = tmp; } while(0)

int* shuffle(int *ary, int length){
  srand(time(NULL));
  for(int i = length - 1; i; i--){
    int idx = rand() % i;
    SWAP(ary[idx], ary[i]);
  }
  return ary;
}

洗完後只要依序拿前 n 個或是後 n 個就可以得到亂數不重複的陣列。當然更進一步的做法是 SWAP n 次以後就可以停下了,不需要全洗乾淨。

標籤