23,404
社区成员
发帖
与我相关
我的任务
分享
/**
* <ul>
* <li>三扇门中,其中一扇后面有一辆车;其余两扇后面则是山羊。</li>
* <li>参赛者在三扇门中挑选一扇。他并不知道内里有什么。</li>
* <li>主持人知道每扇门后面有什么。</li>
* <li>主持人必须开启剩下的其中一扇门,并且必须提供换门的机会。</li>
* <li>主持人永远都会挑一扇有山羊的门。
* <ul>
* <li>如果参赛者挑了一扇有山羊的门,主持人必须挑另一扇有山羊的门。</li>
* <li>如果参赛者挑了一扇有汽车的门,主持人随机在另外两扇门中挑一扇有山羊的门。</li>
* </ul>
* <li>参赛者会被问是否保持他的原来选择,还是转而选择剩下的那一道门。</li>
* </ul>
* 转换选择可以增加参赛者的机会吗?
*/
public static void main(String[] args) throws Exception {
// 随机性更强一些吧!
final Random rand = new SecureRandom();
// 请自行调节,不过如果想看CSV,建议不要超过65536,否则MS Office不能保证打开
final int total = 1000000;
// 只计算去除一个错误答案后,换门成功的次数
int count = 0;
// 如果想看CSV,请取消相关注释
// System.setOut(new PrintStream(new File(System.getProperty("user.home"), "MontyHall.csv")));
// System.out.println("car,firstChoice,opened,secondChoice,bingoAfterChange");
// 以下流程,严格按照游戏规则,不对的地方请指出
for (int i = 0; i < total; i++) {
// 汽车的位置
int car = rand.nextInt(3);
// 第一个选择
int firstChoice = rand.nextInt(3);
// 主持需要打开的带有山羊的门
int opened;
if (firstChoice != car) {
// 如果参赛者挑了一扇有山羊的门,主持人必须挑另一扇有山羊的门。
// 1 × 2 × 3 = 6,所以倒过来除可以找出第三个
opened = (6 / (car + 1) / (firstChoice + 1)) - 1;
} else { // i.e.: firstChoice = car
// 如果参赛者挑了一扇有汽车的门,主持人随机在另外两扇门中挑一扇有山羊的门。
// 为了表示主持人抛硬币,如果正面,就选择参赛者选的门顺时针方向的门,反面,选逆时针。
// 有人说“最边上的怎么办”,不用多讲,地球是圆的总可以了吧:P
if (rand.nextBoolean()) {
opened = (firstChoice + 1) % 3;
} else {
// Why + 3 first??? Just ask yourself.
opened = (firstChoice + 3 - 1) % 3;
}
}
// 只算改选,计算公式同上
int secondChoice = (6 / (opened + 1) / (firstChoice + 1)) - 1;
boolean bingoAfterChange = secondChoice == car;
if (bingoAfterChange) {
count++;
}
// 可以到在Excel里面打开一下CSV,用统计函数研究一下,看看是否有猫腻
// System.out.printf("%d,%d,%d,%d,%d%n", car, firstChoice, opened, secondChoice, bingoAfterChange ? 1 : 0);
}
System.out.println(count);
// System.out.flush();
}