如何给扑克洗牌才能更公平

简介: 该文章讨论了在线桌游中实现公平洗牌的算法,介绍了几种随机化技术来确保卡牌或游戏元素的排列真正随机,从而保证游戏的公正性和玩家体验。

📻前言

平常在日常生活中,我们总会遇到公平性这个话题。比如,几个人分奖品,怎么样才能公平分配?又或者,年会来个抽奖转盘,怎么样才能让它更公平呢?

那在下面这篇文章呢,我们将谈论关于洗牌的公平性。一起来了解吧~

一、🎙️需求分析 - 洗牌问题

有时候我们在闲暇之余可能会打打斗地主之类的扑克游戏,但是这扑克要怎么去洗牌,才能不失公平性呢?

扑克牌

那么接下来,我们由浅入深的来讲解一种实现效果。

二、💿实现版本

1. 版本一:常规思维

先附上代码:

JS 代码:

const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

function shuffle(cards) {
   
  return [...cards].sort(() => Math.random() > 0.5 ? -1 : 1);
}

console.log(shuffle(cards)); // [5, 4, 3, 2, 1, 9, 0, 6, 8, 7]

如果说要公平,那很多小伙伴刚开始想的应该是随机打乱。但是其实 Math.random() 并不能真正起到真正的随机。

它的随机性跟原来的位置相关,它是随机的去交换原来两个数的位置,而这个位置是否会产生交换的不确定性也很大,所以它并没办法达到真正的公平。

2. 版本二:验证公平性

先附上代码:

JS 代码:

const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

function shuffle(cards) {
   
  return [...cards].sort(() => Math.random() > 0.5 ? -1 : 1);
}

const result = Array(10).fill(0);

for(let i = 0; i < 1000000; i++) {
   
  const c = shuffle(cards);
  for(let j = 0; j < 10; j++) {
   
    result[j] += c[j];
  }
}

console.log(result);

依据版本一的例子,我们来看下它为什么不公平。先看下打印效果:

打印效果

大家可以看到,如果这个算法是公平的,那它从第一个数到最后一个数应该都是比较平均的,而在这个算法中,越靠后的数,其数值会越大,所以这个随机性明显是有问题的。一般来说,如果用这个算法的话,排在越后面的同学的中奖概率,会比排在前面的同学的中奖概率要

3. 版本三:交换法则

先附上代码:

JS 代码:

const cards = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

function shuffle(cards) {
   
  const c = [...cards];
  for(let i = c.length; i > 0; i--) {
   
    const pIdx = Math.floor(Math.random() * i);
    [c[pIdx], c[i - 1]] = [c[i - 1], c[pIdx]];
  }
  return c;
} 

//验证是否公平
const result = Array(10).fill(0);

for(let i = 0; i < 10000; i++) {
   
  const c = shuffle(cards);
  for(let j = 0; j < 10; j++) {
   
    result[j] += c[j];
  }
}

console.log(shuffle(cards));
console.log(result);

基于前面两个版本的瑕疵,我们来实现一种公平的写法。上面的这种算法呢,其复杂度是 O(n) ,它的实现逻辑是,在整个有序数组中,先随机抽取任意一个数,把它放到最后的位置,之后再随机抽取任意一个数,再把它换到最后一个位置进行交换,以此类推。具体思路如下图所示:

洗牌交换法实现思路

下面来看控制台打印效果:

交换法打印效果

大家可以看到,控制台打印出来的数都是相对比较平均的,而不会前后差异特别大。所以,这个算法是公平的。

三、📺在线Online

以上三个版本的在线地址:

四、📹结束语

在上面的文章中,我们首先谈论了平常常用的随机洗牌法的不公平性,之后重新介绍了一种新的交换法则来实现洗牌的公平性。不知道大家对洗牌问题是否有了进一步了解呢?

如果您觉得这篇文章有帮助到您的的话不妨点赞支持一下哟~~😉

📸往期推荐

👉紧跟月影大佬的步伐,一起来学习如何写好JS(上)

👉紧跟月影大佬的步伐,一起来学习如何写好JS(下)

👉每天都在红绿灯前面梭行,不如自己来实现个红绿灯?

👉幂等问题 vs 如何判断是否是4的幂

相关文章
|
6月前
|
算法 测试技术 C#
【广度优先搜索】【分类讨论】900. 最佳运动员的比拼回合
【广度优先搜索】【分类讨论】900. 最佳运动员的比拼回合
|
6月前
|
存储 算法 PHP
开发一款扑克游戏,请给出一套洗牌算法,公平的洗牌并将洗好的牌存储在一个整形数组里?
开发一款扑克游戏,请给出一套洗牌算法,公平的洗牌并将洗好的牌存储在一个整形数组里?
41 1
开发一款扑克游戏,请给出一套洗牌算法,公平的洗牌并将洗好的牌存储在一个整形数组里?
【JavaProject】洗牌斗牛系统
JavaProject & 洗牌斗牛系统 结合ArrayList类的使用,小小实践一下吧
65 0
|
人工智能 资源调度 算法
理解 P/NP 问题时,我产生了一种已经触碰到人类认知天花板的错觉?!
咱研究算法的时候,一定遇到过动态规划中的 旅行商问题(TSP)! TSP 是一个 NP 完全问题,今天咱要聊聊正是七大 千禧年大奖难题 之首的 【P/NP 问题】!
简单设计一下洗牌和发牌
简单设计一下洗牌和发牌
101 0
简单设计一下洗牌和发牌
|
算法
算法学习之路|棋盘问题(博弈)
小明和小红在玩一种棋盘游戏,棋盘的尺寸为n个方格*m个方格。一开始在棋盘的右上角(1,m)放一枚硬币,每次一个人可以将硬币向左、下或左下的方格移动。
2148 0
|
算法
小玩意 - 抢红包算法(公平版 & 手速版)
小玩意 - 抢红包算法(公平版 & 手速版)
266 0
小玩意 - 抢红包算法(公平版 & 手速版)
|
算法 JavaScript
【青训营】- 如何给扑克洗牌才能更公平?
平常在日常生活中,我们总会遇到公平性这个话题。比如,几个人分奖品,怎么样才能公平分配?又或者,年会来个抽奖转盘,怎么样才能让它更公平呢? 那在下面这篇文章呢,我们将谈论关于洗牌的公平性。一起来了解吧~
【青训营】- 如何给扑克洗牌才能更公平?
|
人工智能
AlphaGo单挑五虎将获胜,连笑配对AlphaGo笑到最后
经历过 AlphaGo与柯洁第一场势均力敌,第二场热血沸腾的比赛之后,今天,乌镇围棋峰会进入了配对赛与团体赛的争夺。上午 10:59 分,连笑八段联手 AlphaGo 执白战胜古力九段与 AlphaGo 的组合,赢得了史上首次人机配对赛。而在下午 16::32 时,五位世界冠军组成的团队在与 AlphaGo 的对决中收官阶段认输,团体赛告于段落。
333 0
AlphaGo单挑五虎将获胜,连笑配对AlphaGo笑到最后
斗地主三步走——洗牌、发牌和看牌
斗地主三步走——洗牌、发牌和看牌
223 0