蒙提霍尔问题

最近看韩国电视剧【D.P逃兵追缉令】里面提到一个有趣的数学概率游戏 -> 蒙提霍尔问题

意思是:参赛者会看见三扇门,其中一扇门的里面有一辆汽车,选中里面是汽车的那扇门,就可以赢得该辆汽车,另外两扇门里面则都是一只山羊,让你任意选择其中一个,然后打开其余两个门中的一个并且是山羊(去掉一个错误答案),这时,让你重新选择。那么你是会坚持原来的选择,还是换选另外一个未被打开过的门呢?

大家可以想一想如果是自己,我们是会换还是不会换?

好了,我当时看到后感觉很有意思,所以我简单写了一套代码,源码贴在下面,大家可以验证一下,先告诉大家,换赢得汽车的概率是2/3,不换赢得汽车的概率是1/3

html 复制代码
<header>
<h1>请选择换不换?</h1><button class="refresh">刷新</button>
</header>
<section>
<div class="box">
  <h2>1</h2>
  <canvas width="300" height="100"></canvas>
  <div class="prize">奖品</div>
</div>
<div class="box">
  <h2>2</h2>
  <canvas width="300" height="100"></canvas>
  <div class="prize">奖品</div>
</div>
<div class="box">
  <h2>3</h2>
  <canvas width="300" height="100"></canvas>
  <div class="prize">奖品</div>
</div>
</section>
<span>请选择号码牌</span>
<select name="" id="">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button class="confirm">确认</button>
<span class="confirm-text"></span>
<span class="opater">
<button class="change">换</button>
<button class="no-change">不换</button>
</span>
<p>
<strong>游戏规则:</strong>
<span>
  上面有三个号码牌,其中一个号码牌的里面有汽车,选中里面是汽车的号码牌,
  你就可以赢得该辆汽车,另外两个号码牌里面则都是一只山羊,
  你任意选择其中一个,然后打开其余两个号码牌中的一个并且是山羊(去掉一个错误答案),
  这时,你有一个重新选择的机会,你选择换还是不换?
</span>
</p>
css 复制代码
.prize {
  width: 300px;
  height: 100px;
  background-color: pink;
  font-size: 36px;
  line-height: 100px;
  text-align: center;
  position: absolute;
}

canvas {
  position: absolute;
  z-index: 2;
}

section {
  display: flex;
}

.box {
  width: 300px;
  height: 200px;
  cursor: pointer;
}

.box+.box {
  margin-left: 8px;
}

header {
  display: flex;
  align-items: center;
}

header button {
  margin-left: 8px;
  height: 24px;
}
p {
  width: 400px;
  background-color: pink;
}
js 复制代码
function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}
function getRandomNumber() {
  return Math.random() > 0.5 ? 1 : 2;
}
let a1 = [0, 1, 2]
let i1 = undefined
let i2 = undefined
let isChange = false
const opater = document.querySelector('.opater')
opater.style.display = 'none'
// 随机一个奖品
const prizes = document.querySelectorAll('.prize')
let a0 = [0, 1, 2]
a0 = shuffleArray(a0)
a0.forEach((v,i) => {
  const innerText = !!v ? '山羊' : '汽车'
  prizes[i].innerText = innerText
})

const canvas = document.querySelectorAll('canvas')
const confirmText = document.querySelector('.confirm-text')
canvas.forEach(c => {
  // 使用canvas实现功能
  // 1. 使用canvas绘制一个灰色的矩形
  const ctx = c.getContext('2d')
  ctx.fillStyle = '#ccc'
  ctx.fillRect(0, 0, c.width, c.height)
  // 2. 刮奖逻辑
  // 鼠标按下且移动的时候,需要擦除canvas画布
  let done = false
  c.addEventListener('mousedown', function () {
    if (i1 === undefined) return alert('请先选择号码牌,并确认!')
    if (!isChange) return alert('请选择换不换!')
    done = true
  })
  c.addEventListener('mousemove', function (e) {
    if (done) {
      // offsetX 和 offsetY 可以获取到鼠标在元素中的偏移位置
      const x = e.offsetX - 5
      const y = e.offsetY - 5
      ctx.clearRect(x, y, 10, 10)
    }
  })
  c.addEventListener('mouseup', function () {
    done = false
  })
})
const confirm = document.querySelector('.confirm')
const refresh = document.querySelector('.refresh')
confirm.onclick = function () {
  let select = document.querySelector('select')
  const options = Array.from(select.children)
  confirmText.innerText = `您选择的号码牌是${select.value},请问现在换不换?`
  // 选择后,去掉一个错误答案
  // i1是下标
  i1 = select.value - 1
  // delValue是值
  let delValue = undefined
  // 通过下标找值
  if (a0[i1] === 0) {
    delValue = getRandomNumber()
  } else {
    delValue = a0[i1] === 1 ? 2 : 1
  }
  // 通过值找下标
  i2 = a0.indexOf(delValue)
  // 选择的是i1, 去掉的是
  const ctx = canvas[i2].getContext('2d')
  ctx.clearRect(0, 0, 300, 100)
  options.map(v => v.disabled = true)
  confirm.style.display = 'none'
  opater.style.display = 'inline-block'
}
const change = document.querySelector('.change')
const noChange = document.querySelector('.no-change')
change.onclick = function () {
  isChange = true
  const x = a1.filter(v => v !== i1 && v !== i2)
  confirmText.innerText = `您确认选择的号码牌是${x[0] + 1},请刮卡!`
  opater.style.display = 'none'
}
noChange.onclick = function () {
  isChange = true
  confirmText.innerText = `您确认选择的号码牌是${i1 + 1},请刮卡!`
  opater.style.display = 'none'
}
refresh.onclick = function () {
  window.location.reload()
}
相关推荐
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新5 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
秦jh_6 小时前
【Linux】多线程(概念,控制)
linux·运维·前端
蜗牛快跑2136 小时前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy6 小时前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js