乐趣区

关于java:一个理科直男如何看鱿鱼游戏

前言

我一贯不怎么喜爱看棒子片。

然而十一期间却疯狂的追着一部剧:《鱿鱼游戏》。

这片子在全网切实是太火了,火到寰球播放量 1.11 亿次,成为奈飞收视率最高的寰球非英语原创剧。

鱿鱼游戏具备很强的事实社会的隐喻,加上各种有意思的游戏机制和刺激人心脏的画面,胜利吸引了很多人的追捧。甚至包含剧中的各种道具。。

比方我看完居然去某宝买了同款椪糖:

除了盒子和针还有一丝还原度以外,这糖饼的品质真不咋地。厚的来几乎拿针没法戳。我试了下,而后变成了这样。。。

不光是很难拨出来,滋味也齐全不行。一个均匀卖十几块,可想而知毛利有多高。

当然我这篇文章不是为了吐槽椪糖的。

我不晓得大家在看这剧时候有没有这样想过:如果我是一个参赛者,存活的几率有多大?

预计看过剧的小伙伴都会说,百分百 GG。那你晓得每个游戏的生存几率有多大么,这篇文章我就从感性 & 演绎的角度剖析下每个游戏的生存几率。

开始注释。

这剧一共 6 个游戏,别离是:木头人,椪糖,拔河,弹珠,玻璃桥和鱿鱼游戏。

木头人这个游戏,其实要过并不难,次要还在于大家的心理素质和第一次面对大规模屠杀时的恐惧心理,能够必定的是游戏在场地左边的的玩家必定存活几率大点,因为那个娃娃是从右边转头的,也就是说左边的人会比右边的人多进去大略 1 秒多的工夫进行奔跑。

但总体来说,这个没法用数学来演绎出。咱们暂且用剧中的存活概率来计算

木头人 存活概率为:(456-255)/456=44.08%

第二个游戏椪糖游戏,因为每个人拿到的图形不一样,解题思路也不一样,这游戏默认能够采纳“舞弊”伎俩,能够用火溶解,能够用舔狗大法。还波及到一点临场的反馈。同样的也无奈用数学演绎来进行得出,咱们同样用游戏中的存活概率参考。

第一个游戏完结后,大家进行了投票决定回家,而后从新决定来参赛的人有 187 人,第二个游戏中有 79 人淘汰,咱们能够得出:

椪糖游戏存活概率为:(187-79)/187=57.75%

第三个游戏拔河和和第四个游戏弹珠很简略,都是淘汰一半的人,存活概率都为 50%。

第 5 个游戏是重点,玻璃桥。

18 对玻璃,每对玻璃只有一块玻璃能接受人的分量,当你踩到易碎玻璃的时候,玻璃破裂,人就会摔下去 GG。16 集体挨个过。

当然,在得悉游戏规则的前提下,咱们能够很轻易的得出,最初一个人生还的概率是最大的。那每个序号的人生存的概率是多少呢,这个游戏生还多少人的概率为最大呢。

我于是为玻璃桥写了一段程序,去模仿 1 亿次。次数足够多,概率这个货色才有意义。

程序用 java 写,花了 20 分钟就写进去了。代码如下:

public class SquidGame {public static void main(String[] args) {StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Map<Integer,Integer> map = new HashMap<>();

        // 循环总次数,也就是总模仿次数
        int loopCount = 100000000;
        // 桥上一共有几步
        int stepNum = 18;
        // 游戏参与者一共有几人
        int peopleNum = 16;
        // 每一步有多少块玻璃
        int grassNumPerStep = 2;

        // 两头变量,每一次循环的生存者个数
        int surviveNum = 0;
        for (int i = 0; i < loopCount; i++) {surviveNum = calcSurvive(stepNum, peopleNum, grassNumPerStep);
            if (map.containsKey(surviveNum)){map.put(surviveNum, map.get(surviveNum) + 1);
            }else{map.put(surviveNum, 1);
            }
        }
        stopWatch.stop();
        System.out.println(StrUtil.format("玻璃桥步数:{}", stepNum));
        System.out.println(StrUtil.format("参加游戏的人数:{}", peopleNum));
        System.out.println(StrUtil.format("每一步块玻璃块数:{}", grassNumPerStep));
        System.out.println(StrUtil.format("模仿共耗时:{}秒", stopWatch.getTotalTimeSeconds()));
        System.out.println("*******************************************");
        System.out.println(StrUtil.format("鱿鱼游戏第 5 关玻璃桥模仿 {} 次的后果如下:", loopCount));
        for (int i = 0; i <= peopleNum; i++) {System.out.println(StrUtil.format("幸存者个数为 {} 的次数:{}", i, ObjectUtil.isNull(map.get(i))?0:map.get(i)));
        }

        int maxRateSurviveNum = map.entrySet().stream().max(Map.Entry.comparingByValue()).get().getKey();
        System.out.println("*******************************************");
        System.out.println(StrUtil.format("最终论断:存活 {} 人的概率为最大", maxRateSurviveNum));
        System.out.println("*******************************************");
        System.out.println();

        System.out.println("每个序号的人存活概率如下:");
        for (int i = peopleNum,j = 1; i >= 1 && j <= peopleNum; i--, j++) {
            int count = 0;
            for (int x = i; x <= peopleNum; x++) {count += map.get(x);
            }
            BigDecimal surviveRatePercent = new BigDecimal(count).divide(new BigDecimal(loopCount), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
            System.out.println(StrUtil.format("抽到序号为 [{}] 的玩家生存几率为:{}%", j, surviveRatePercent.toString()));
        }
    }

    public static Integer calcSurvive(int stepNum, int peopleNum, int grassNumPerStep){
        // 目前幸存者
        int survive = peopleNum;
        // 以后尝试玻璃步数序号
        int currentStep = 1;
        // 目前尝试的步数还剩几块玻璃
        int currentGrassNum = grassNumPerStep;
        while(true){if (currentStep <= stepNum && survive > 0){
                //1. 每一步的生存概率和每一步有几块玻璃无关,如果每一步有 2 块玻璃,//  死亡概率那就是 50%,有 3 块玻璃,死亡概率就是 66.6%,以此类推
                //2. 如果死亡,survive 就会减 1,同时以后步数的玻璃数目也要减 1。//  当然如果是按剧中的设定,每一步只有 2 块玻璃,那么这一步,死亡一次后,下一个人必然胜利
                //3. 如果以后步数此人存活,survive 不变,那么 currentStep 就会加 1,同时下一步的玻璃块数重置为设置值
                if (new Random().nextInt(1000) > 1000/currentGrassNum){
                    survive--;
                    currentGrassNum--;
                } else{
                    currentStep++;
                    currentGrassNum = grassNumPerStep;
                }
            } else{
                // 以后步数等于最初一步 或者 没有生存者 的状况下,那么游戏完结
                break;
            }
        }
        return survive;
    }
}

程序用剧中的人数 16 人,走 18 步玻璃,每步 2 块玻璃 (还有这玩意么?后续我要加大难度的) 的参数玩了 1 亿次。后果如下:

能够看到,存活 7 人的概率为最大。而且整个存活散布是一个典型的正态分布图:

而每个序号的玩家散布前几位根本无生还心愿,而后 4 位根本能够无忧。抽到 16 序号的人,有高达 99.94% 的存活率,这个游戏说到底还是一个拼人品的游戏啊。

当然这个模仿的前提是:每个人都依照游戏规则去进行。而且排除了后面一个人过来了,前面一个人不记得是哪块玻璃这种状况。

我在网上搜寻了下,有很多探讨就是对于玻璃桥过法的帖子,有说人架在 2 根铁横梁之间过的。有说 16 集体团结在一起的,手拉着手,让最后面一个人去试玻璃的,还有说把衣服都脱下来,打包成一个大布球前面拖根布条,使劲去砸后面一个玻璃的。

形形色色。

当然这些办法从实践上的确行的通,然而人家 vip 喝着小酒,大老远跑过来,能看着你们玩团队合作,情急生智?游戏的解释权还是在官网这里的。所以这些就不要想了。

仅仅是从数学的冀望上来说,玻璃桥这个游戏,其实最终能存活的应该在 6 到 8 集体。而剧中最终存活的只有 3 个。

难道说这届正好是低于期望值的么?

如果依照游戏的规范规定来走,在后面的人每个人至多得有一次尝试未知的 2 块玻璃的机会,而剧中很屡次呈现了兽性扭曲的一面,被推下去的,同归于尽的都有,这样从整个参与者个人的角度去思考,就白白少了几次尝试的机会。而少了几次尝试的机会,会间接拉低整个个人的冀望。这就是最终只存活下来 3 集体的起因。

在程序中,我设置了这样一个参数:grassNumPerStep,每一步有多少块玻璃。剧中的设定是 2。那么如果我加大难度,把 2 块玻璃改成 3 块玻璃呢,那后果又是如何呢?(听着就感觉更加失望)

从 2 块改成 3 块玻璃,看起来如同只是每一步的概率从 50% 升高到 33.3%。

然而还暗藏着一个条件:2 块玻璃的时候,后面一个人无论猜对还是猜错,那前面的人肯定能够胜利的进一步。而 3 块玻璃的时候,当后面一个人猜错失败的时候,你这时仍然有 50% 的几率猜错。这个状况就简单多了。

3 块玻璃持续模仿一亿次的后果:

仅仅是减少一块玻璃,存活率就如降落的如此厉害,连抽到 16 号签的幸运儿也只能有不到 24% 的生还率。预计这种设定,也就没人加入第六个游戏了吧。。。

最初一个游戏,无非就是在目前的存活者当中,决出 1 个进去。其实整个游戏不必算都晓得拿到钱的就是 1 / n 的机会。也就是说,无论你之前如何动脑子,舞弊,揣测,坑蒙拐骗,哪怕你混到最初一关了,最初的存活都要依附人类最原始的蛮力和暴力去解决问题。

这部片子有很强的映射社会的寓意,心愿在当下这个塌实且物欲横流的社会,大家都能好高鹜远的过日子,不要想着一夜暴富。活着且坚持不懈的致力,才是进步幸福感的惟一路径。

看到这里的同学,求点赞,在看,以及分享。

退出移动版