关于牌类游戏麻将洗牌算法法一问:怎样才算把牌洗

博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)void shuffle(in&&
假定N=54,首先,我们有一个随机函数发生器,能够产生1-54之间的随机数,如何保证抽第一张牌是54中可能,抽第二张牌是53中可能,……
可以这样做,假设扑克牌是一个54维的数组card,
我们要做的就是从这个数组中随机取一个元素,然后在剩下的元素里再随机取一个元素…
这里涉及到一个问题,就是每次取完元素后,我们就不会让这个元素参与下一次的选取。
我们要实现的目的是以等概率的方式将这54个数随机打乱排列,因此,可以这样处理:
第一次抽牌在初始54张牌中,将 随机产生的牌x,与第一个元素互换,
第二次抽牌在剩下的53张牌中,将 随机产生的牌y,与第二个元素互换,
void RandomShuffle(int a[], int n){
for(int i=0; i&n; ++i){
int j = rand() % (n-i) +// 产生i到n-1间的随机数
Swap(a[i], a[j]);//交换位置
解析: 最直观的思路是什么?很简单,每次从牌堆中随机地拿一张出来。那么,
第一次拿有52种可能,拿完后剩下51张;第二次拿有51种可能,第三次拿有50种可能,
…,一直这样随机地拿下去直到拿完最后1张,我们就从52!种可能中取出了一种排列, 这个排列对应的概率是1/(52!),正好是题目所要求的。
接下来的问题是,如何写代码去实现上面的算法?假设扑克牌是一个52维的数组cards,
我们要做的就是从这个数组中随机取一个元素,然后在剩下的元素里再随机取一个元素…
这里涉及到一个问题,就是每次取完元素后,我们就不会让这个元素参与下一次的选取。 这个要怎么做呢。
我们先假设一个5维数组:1,2,3,4,5。如果第1次随机取到的数是4,
那么我们希望参与第2次随机选取的只有1,2,3,5。既然4已经不用,
我们可以把它和1交换,第2次就只需要从后面4位(2,3,1,5)中随机选取即可。同理,
第2次随机选取的元素和数组中第2个元素交换,然后再从后面3个元素中随机选取元素, 依次类推。 代码: #include
&iostream& #include &cstdlib& using namespace
void Swap(int &a, int &b){//
有可能swap同一变量,不能用异或版本
} void RandomShuffle(int a[], int n){
for(int i=0;
i&n; ++i){
int j = rand() % (n-i) +//
产生i到n-1间的随机数
Swap(a[i], a[j]);
srand((unsigned)time(0));
int n = 9;
int a[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9
RandomShuffle(a, n);
for(int i=0; i&n; ++i)
cout&&a[i]&&
return 0; }
void Rand(int a[],int N)
for(int i=0;i&N;i++)
j=rand%(n-i)+i;
swap(a[i],a[j]);
依次遍历数组,对第n个元素,以1/n的概率与前n个元素中的某个元素互换位置,最后生成的序列即满足要求,1/n的概率可通过rand() % n实现。见如下程序:
void swap(int &a, int &b)
void shuffle(int *arr, int n)
for(i = 0; i & i++) {
int idx = rand() % (i + 1); //选取互换的位置
swap(&arr[idx], &arr[i]);
可以先将N张扑克牌生成一个全排列,将每个排列的编号存入一个数组中,然后用随机函数生成一个索引,可以在数组中任意取一种排列就算一种洗牌的方式。
voidshuffle(inta[],intlen)
if (a == NULL)
for(int i = 0; i & ++i)
int j = i + random() % (len - i);
swap(a[i], a[j]);
void shuffle(int arr[],int n)
for(int i=0;i&n-1;i++)
int val=i+rand()%(n-i);
int temp=a[i];
a[i]=a[val];
void get_rand_number(int card[],int size)
int m1,m2,
if(card==NULL||size==0)
for(int i=0;i&i++)
m1=i+rand()/size-i;
temp=card[i];
card[i]=card[m1];
card[m1]=card[i];
public class Test {
public static void main(String[] args)
String[] s =
{&2&,&3&,&4&,&5&,&6&,&7&,&8&,&9&,&10&,&J&,&Q&,&K&,&A&};
pushCard(s);
static void pushCard(String[] s){
Random random = new Random();
for (int i = 0; i & 30; i++)
int rand = random.nextInt(13);
int rand2 =
random.nextInt(13);
String t = s[rand];
s[rand2] =
for (String string : s)
System.out.print(string+& &);
随机交换任意两张牌的顺序N次即可完成洗牌
public class User {
public static void main(String[] args) {
shuffle();
public static void shuffle() {
List&Integer& list = new ArrayList&Integer&();
int a=(int)( Math.random()*10);
list.add(a);
for (int i = 1; i & 10; i++) {
a=(int) (Math.random()*10);
if(list.contains(a)){
list.add(a);
for(int i=0;i&list.size();i++){
System.out.print(list.get(i)+& &);
void xipai(int &a[],int len)
for(int i=0;i&i++)
int j=i+rand()%(len-i);
int temp=a[i];
a[i]=a[j];
* @brief shuffle 洗牌算符
* @param a 扑克牌,里面存放着扑克盘的数值
* @param len 扑克的数量
void shuffle(int a[],int len)
for(int i=0;i&++i)
int val=i+rand()%(len-i);//通过随即按函数获得要交换的扑克的位置
int temp=a[val];
a[val]=a[i];
for(int i = 0; i & N; i++){
int j = random(i,
swap(card[i], card[j]); }
只要能够保证洗牌算法均匀即可,下面给出个经典的洗牌算法的伪代码:
for i in 1….n:
randomly select a card j from [1,i]
swap card i with card j
这道题你会答吗?花几分钟告诉大家答案吧!
扫描二维码,关注牛客网
下载牛客APP,随时随地刷题
京ICP备号-4
扫一扫,把题目装进口袋这是一篇旧文,点击以旧主题模式浏览。洗牌算法怎样才够乱? - 知乎26被浏览<strong class="NumberBoard-itemValue" title="分享邀请回答55 条评论分享收藏感谢收起jianshu.com/p/1a23d7c28d49这是我第一次接触洗牌算法,也强烈建议题主实现一下这个算法1添加评论分享收藏感谢收起写回答  斗地主之类的游戏大家都玩过,有没有想过,游戏是如何给我们发牌的呢?
  我们先将问题做一下抽象:我们将扑克牌抽象为数字,那么洗牌的问题就转化为
给定一个长度为54的整型数列,请将其顺序随机打乱,保证每个数出现在任意一个位置的概率相同。
朴素的想法——抽牌
每次随机从牌堆中选一个位置抽牌,如果该位置的牌已被抽走,则继续随机选取位置,直到将所有牌抽完。
  显然,这种做法时间复杂度很高。那么不妨稍微优化下。
每次随机从牌堆中选一个位置抽牌,然后将该位置后面的牌依次向前移动一个位置,下一次从新牌堆(数量-1)中抽取,循环到抽完所有牌为止。
  这样也能完成要求,单这样的做法,对于数据规模比较小的数据可以接受,但数据量一旦变大,反而不如不优化的算法效率高。我们还得继续想办法优化。
每次随机从牌堆中选一个位置抽牌,然后将最后一张牌移动到被选择的位置,下一次从新牌堆(数量-1)中抽取,循环到抽完所有牌为止。
  这样优化完以后,时间复杂度降低到了O(N),应该能满足要求了。
经典的洗牌算法——交换
  上面的算法需要额外的辅助空间,那么能不能就地洗牌呢?答案当然是可以的。
还是每次随机一个位置,然后将该位置上的牌与 i 位置上的牌交换,直到 i 遍历玩所有位置为止。
1 void MySwap(int &x, int &y)
int temp =
8 void Shuffle(int n)
<span style="color: #
for(int i=n-<span style="color: #; i&=<span style="color: #; i--)
<span style="color: #
<span style="color: #
MySwap(num[i], num[rand()%(i+<span style="color: #)]);
<span style="color: #
<span style="color: # }
  该洗牌算法的时间复杂度为O(N),空间复杂度为O(N)。
阅读(...) 评论()

我要回帖

更多关于 扑克牌洗牌算法 的文章

 

随机推荐