洗牌的算法有很多,这里主要介绍下几种主要的算法。
方法一:每次找一个随机的位置,然后将这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()); 还可以定义起始迭代器和末尾迭代器来对序列中的某一部分进行洗牌,并且所耗费的时间也较少。