蒙提霍尔问题

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

意思是:参赛者会看见三扇门,其间一扇门的里边有一辆轿车,选中里边是轿车的那扇门,就能够赢得该辆轿车,别的两扇门里边则都是一只山羊,让你恣意挑选其间一个,然后翻开其他两个门中的一个并且是山羊(去掉一个过错答案),这时,让你重新挑选。那么你是会坚持本来的挑选,仍是换选别的一个未被翻开过的门呢?

我们能够想一想如果是自己,我们是会换仍是不会换?

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

<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>
.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;
}
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()
}