Skip to content

简介:拼手气类的游戏,更能激发用户购物和社交的趣味性,以及游戏竞争心理,拼手气类的活动甚至可以影响人们消费心理。拼手气红包就是最简单的例子。

顾名思义,二倍均值算法的核心思想是根据每次剩余的总金额M和剩余人数N,执行M/N再乘以2的操作得到一个边界值E,然后制定一个从0到E的随机区间,在这个随机区间内将产生一个随机金额R, 此时总金额M将更新为M-R,剩余人数N更新为N-1。再继续重复上述执行流程,以此类推,直至最终剩余人数N-1为0,即代表随机数已经产生完毕。

两种生成红包的方式对比

拼手气红包有两种计算方法,一种是预计算,一种是实时算。

预计算在生成拼手气红包的时候,会提前根据总金额M和红包人数N,生成每个红包的金额,在抢红包的过程中,只需要从金额列表中取出,直至取完。这种方式需要占用额外的存储空间并且增加额外的I/O,在高并发场景下并不是最优的解决方案。 实时算采用的是纯内存计算,不需要预算空间存储,实时性很高。

预计算代码实现

java
    /**
     * 拆包
     *
     * @param totalAmount 总金额
     * @param totalCount  总数量
     * @return 拆包结果
     */
    public static List<Integer> divide(int totalAmount, int totalCount) {
        if (totalAmount < 0) {
            throw new IllegalArgumentException("totalAmount cannot be less than the 0");
        }
        if (totalAmount < totalCount) {
            throw new IllegalArgumentException("totalAmount cannot be less than the totalCount");
        }
        List<Integer> result = new ArrayList<>();
        Random random = new Random();

        // 剩余金额
        int remainingAmount = totalAmount;
        // 剩余数量
        int remainingCount = totalCount;
        for (int i = 0; i < totalCount - 1; i++) {
            // 本红包的最大值 人数 / 金额 * 2
            int max = 2 * (remainingAmount / remainingCount);
            // 随机生成一个 1 到 max 之间的金额
            int amount = 1 + random.nextInt(max - 1);
            // 更新剩余金额与人数
            remainingCount--;
            remainingAmount = remainingAmount - amount;

            result.add(amount);
        }
        // 添加最后剩余的金额
        result.add(remainingAmount);
        return result;
    }