最新编辑2:
又有网友提出,造成这个结果是因为 随机数Random.Next的方法永远拿不到上限值,也就是说 r.Next(0,2) 永远拿不到2。去source上查了一下确实如此,微软这个方法有点坑。
PS:特别感谢 御坂14491 号的提出,以及MatPopLeaSpo、言心亡、日后再说好不好、最萌的伊卡洛斯等朋友的在线对狙。
最后,公布最新的源码和跑的结果,先看结果:
改变选择有66465此中奖,不改变选择有33535此中奖,总数100000,
主持人选对了次数0
代码修改为:
public class Program { static Random r = new Random(); // 三门随机数生成器 static Random R = new Random(); // 我的第一次选择随机数生成器 static Random r_host = new Random(); //主持人选择随机数生成器 static bool[] GetDoors() // 随机产生一个门 { switch (r.Next(0, 3)) { case 0: return new bool[3] { true, false, false }; case 1: return new bool[3] { false, true, false }; default: return new bool[3] { false, false, true }; } } //主持人根据我的第一次选择随机选一个非门 static int GetHostSelection(bool[] door, int my_firstguess) { if (door[my_firstguess]) //如果我第一次猜中了,那么主持人任选一扇门 { var guess = r_host.Next(0, 3); while (guess == my_firstguess) guess = r_host.Next(0, 3); return guess; } else //如果我第一次猜错了,那么主持人必须选择错误的那扇门 { for (int i = 0; i < 3; i++) { if (i != my_firstguess && door[i] == false) return i; } } return -1; } static int ChangeMySelection(bool[] door, int host_guess, int my_firstguess) //改变我的选择 { for (int i = 0; i < 3; i++) if (i != host_guess && i != my_firstguess) return i; return -1; } static void Main(string[] args) { int right = 0; //改变选择 int right2 = 0; //不改变选择 int host_right = 0; //主持人选对了 for (int i = 0; i < 100000; i++) { bool[] door = GetDoors(); //随机生成三门 int my_firstguess = R.Next(0, 3); // 我随机猜一个门 // 主持人根据我猜的结果随机选择一个非豪车的门 int host_guess = GetHostSelection(door, my_firstguess); //改变我的选择 int my_finalguess = ChangeMySelection(door, host_guess, my_firstguess); if (door[my_finalguess]) right++; else if (door[my_firstguess]) right2++; if (door[host_guess]) host_right++; } Console.WriteLine(string.Format("改变选择有{0}此中奖,不改变选择有{1}此中奖,总数{2},主持人选对了次数{3}", right, right2, 100000, host_right)); Console.ReadKey(); }
最新编辑:
有网友提出,我应该对比改变选择与不改变不选择中奖的比例,因此我把程序改为如下:
public class Program { static Random r = new Random(); // 三门随机数生成器 static Random R = new Random(); // 我的第一次选择随机数生成器 static Random r_host = new Random(); //主持人选择随机数生成器 static bool[] GetDoors() // 随机产生一个门 { switch (r.Next(0, 2)) { case 0: return new bool[3] { true, false, false }; case 1: return new bool[3] { false, true, false }; default: return new bool[3] { false, false, true }; } } static int GetHostSelection(bool[] door, int my_firstguess) //主持人根据我的第一次选择随机选一个非门 { if(door[my_firstguess]) //如果我第一次猜中了,那么主持人任选一扇门 { var guess = r_host.Next(0, 2); while(guess== my_firstguess) guess = r_host.Next(0, 2); return guess; } else //如果我第一次猜错了,那么主持人必须选择错误的那扇门 { for (int i = 0; i < 3; i++) { if (i != my_firstguess && door[i] == false) return i; } } return -1; } static int ChangeMySelection(bool[] door, int host_guess ,int my_firstguess) //改变我的选择 { for (int i = 0; i < 3; i++) if (i != host_guess && i != my_firstguess) return i; return -1; } static void Main(string[] args) { int right = 0; //改变选择 int right2 = 0; //不改变选择 for (int i=0;i<100000;i++) { bool[] door = GetDoors(); //随机生成三门 int my_firstguess = R.Next(0, 2); // 我随机猜一个门 int host_guess = GetHostSelection(door, my_firstguess); // 主持人根据我猜的结果随机选择一个非豪车的门 int my_finalguess = ChangeMySelection(door, host_guess, my_firstguess); //改变我的选择 if(door[my_finalguess]) right++; if (door[my_firstguess]) right2++; } Console.WriteLine(string.Format("改变选择有{0}此中奖,不改变选择有{1}此中奖,总数{2}", right, right2, 100000)); Console.ReadKey(); }
运行结果是:
改变选择有50026此中奖,不改变选择有49974此中奖,总数100000
B站有个视频讲三门问题:
一个美国的电视台节目有个游戏:有三扇门,随机两扇里面是羊,有一扇门是豪车。
参赛选手不知晓哪扇门是豪车,他先任意选一扇门。
主持人知道答案,在选手选择第一扇门后,主持人必须从剩下的两扇门中选择是羊的门。
现在参赛选手选择是否换门,因为他手里的可能是羊也可能是豪车。
这个B站的UP主说换门的中奖概率是2/3,我不同意这个观念。我的理由是,参赛选手实际选择门的次数只有一次,而这一次可以选的门是两扇,前面的都是迷惑眼球的文字游戏。
为了验证我的想法,根据大数字规律,我做了一个C#的程序验证之:
public class Program { static Random r = new Random(); // 三门随机数生成器 static Random R = new Random(); // 我的第一次选择随机数生成器 static Random r_host = new Random(); //主持人选择随机数生成器 static Random R_final = new Random(); static bool[] GetDoors() // 随机产生一个门 { switch (r.Next(0, 2)) { case 0: return new bool[3] { true, false, false }; case 1: return new bool[3] { false, true, false }; default: return new bool[3] { false, false, true }; } } static int GetHostSelection(bool[] door, int my_firstguess) //主持人根据我的第一次选择随机选一个非门 { if(door[my_firstguess]) //如果我第一次猜中了,那么主持人任选一扇门 { var guess = r_host.Next(0, 2); while(guess== my_firstguess) guess = r_host.Next(0, 2); return guess; } else //如果我第一次猜错了,那么主持人必须选择错误的那扇门 { for (int i = 0; i < 3; i++) { if (i != my_firstguess && door[i] == false) return i; } } return -1; } static int GetMySelection(bool[] door, int host_guess ,int my_firstguess) //我根据主持人的选择按50%的概率选择是否改变 { if (R_final.Next(0, 1) > 0) { for (int i = 0; i < 3; i++) if (i != host_guess && i != my_firstguess) return i; } return my_firstguess; } static void Main(string[] args) { int right = 0; int wrong = 0; for (int i = 0; i < 100000; i++) { //随机生成三门 bool[] door = GetDoors(); // 我随机猜一个门 int my_firstguess = R.Next(0, 2); // 主持人根据我猜的结果随机选择一个非豪车的门 int host_guess = GetHostSelection(door, my_firstguess); //我的最终选择 int my_finalguess = GetMySelection(door, host_guess, my_firstguess); if (door[my_finalguess]) { right++; } else { wrong++; } } Console.WriteLine(string.Format("有{0}此中奖,有{1}此未中奖,总数{2}", right, wrong, 100000)); Console.ReadKey(); }
运行答案是:
有49925此中奖,有50075此未中奖,总数100000
结果不言自明。