蒙提霍尔问题

最近看韩国电视剧【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()
}
相关推荐
Setsuna_F_Seiei5 小时前
前端的 AI 学习之路 01 之 Agent API 调用 - 和 Agent 的基础对话
前端·人工智能·ai编程
threerocks5 小时前
AI 原生软件开发生命周期手册 - 如何借助 AI,逐阶段改造软件开发生命周期
前端·javascript·后端
徐小夕5 小时前
3分钟从想法到Agent上线:我们开源了一款AI可视化工作流“IDE”
前端·算法·github
why技术7 小时前
eli5,我觉得这个全网在吹的技能,使用体验真的很一般啊。
前端·人工智能·后端
excel7 小时前
记录升级 nuxt3 到 nuxt4 记录
前端
剑胆琴心静水深流8 小时前
全栈之路6---web集成与呈现
前端·vue.js·spring boot·分布式·spring·前端框架·npm
前端snow8 小时前
ai agent -- Memory汇总
前端
ITresearchGuest8 小时前
AI 焦虑下,前端该何去何从
前端·人工智能
Codiggerworld9 小时前
Chrome DevTools 隐藏神技:这 5 个调试技巧你可能从来没用过
前端·chrome·chrome devtools
旋生万物9 小时前
【终极实战】用Python从零“生成“一个宇宙:螺旋干涉模型的代码实现
开发语言·前端·人工智能·react.js·php·wpf