洗牌的算法有很多,這里主要介紹下幾種主要的算法。
方法一:每次找一個隨機的位置,然后將這54個數放到找的位置中。
步驟:1.用一個整型數組記錄各個位置是否已經放置了數,如果放置了則不為0,否則為0。所以在算法開始的時候,初始化此數組每個元素的值都為0.
2.每次產生一個0-53之間的數,看這個位置是否放置了數,如果已經放置了,則繼續采用同樣的方法找一個隨機的位置進行判斷,如果這個位置還未放置,則設置此位置。
3.反復執行步驟2,直到所有的位置都放好了數。
代碼實現如下:
1 void shuffle(int *dest,int N) 2 { 3 int pos,card; 4 for (card=1;card<=N;card++) 5 { 6 do 7 { 8 pos=rand()%(N-1); 9 } while (dest[pos]!=0); 10 11 dest[pos]=card; 12 } 13 } 14 15 void main() 16 { 17 int dest[54]={0}; 18 shuffle(dest,54); 19 for (int i=0;i<54;i++) 20 { 21 cout<<dest[i]<<" "; 22 } 23 }
此方法有個缺點就是很耗時間,因為隨着空位置越來越少,尋找會越來越困難。
方法二:就是先對數組進行初始化,然后隨機交換數組中任意兩個元素。交換的次數越多就越隨機。此方法也很簡單,而且時間復雜度也比較低,計算量也不大。
代碼實現如下:
1 void shuffle ( int a[], int n ) 2 { 3 int tmp = 0, p1, p2; 4 int cnt = rand() % 1023; 5 while (cnt--) 6 { 7 p1 = rand() % n; 8 p2 = rand() % n; 9 tmp = a[p1]; 10 a[p1] = a[p2]; 11 a[p2] = tmp; 12 } 13 }
方法三:它的基本思想是初始化一個vector,順序加入所有牌,即1-54個數,然后從這個vector中隨機抽取一個到另一個vector中,將這個過程執行54次即可完成。
代碼的實現如下:
1 void vectorShuffle(vector<int> &unshuffle,vector<int> &shuffled) 2 { 3 unsigned int temp,len=unshuffle.size(); 4 while(len) 5 { 6 temp=rand()%(len--); 7 shuffled.push_back(unshuffle[temp]); 8 unshuffle.erase(unshuffle.begin()+temp); 9 } 10 } 11 12 13 void main() 14 { 15 vector<int> uncard,carded; 16 for (int i=0;i<54;i++) 17 { 18 uncard.push_back(i+1); 19 } 20 vectorShuffle(uncard,carded); 21 for (int j=0;j<54;j++) 22 { 23 cout<<carded[j]<<" "; 24 } 25 }
PS:STL中也有一個封裝好了的洗牌算法-random_shuffle。使用方法:如果定義有 vector<int> datas,那么直接調用該函數。例如:random_shuffle(datas.begin(),datas.end()); 還可以定義起始迭代器和末尾迭代器來對序列中的某一部分進行洗牌,並且所耗費的時間也較少。