今天学习ThinkPHP6,不知道写什么鬼,于是想了想,快过年了,整个抢红包的功能。百度了几种,亲测有效的3种,保存到这里,万一哪天用上了!

展示一下结果:

PHP 抢红包功能

1、封装公共方法

<?php
// 应用公共文件

/**
 * 随机抢红包 - 方法1
 * 整数红包
 * @param  number total 红包金额
 * @param int num 拆成的个数
 * @return array
 */
function open_int_red($total, $num) {
    $min=1;//每个人最少能收到1元
    $sub_arr = [];
    for ($i=1;$i<$num;$i++)
    {
        $safe_total=($total-($num-$i)*$min)/($num-$i);//随机安全上限
        $money=mt_rand($min,$safe_total);
        $total=$total-$money;
        //echo '第'.$i.'个红包:领'.$money.' 元,余额:'.$total.' 元 <br/>';
        $sub_arr[] = $money;
    }
    //echo '00第'.$num.'个红包:'.$total.' 元,余额:0 元';
    array_push($sub_arr, $total);
    return $sub_arr;
}

/**
 * 随机抢红包 - 方法2
 * 保留2位小数点红包
 * @param  number total 红包金额
 * @param int num 拆成的个数
 * @return array
 */
function open_float_red($total, $num) {
    $min=0.01;//每个人最少能收到0.01元
    $sub_arr = [];
    for ($i=1;$i<$num;$i++)
    {
        $safe_total=($total-($num-$i)*$min)/($num-$i);//随机安全上限
        $money=mt_rand($min*100,$safe_total*100)/100;
        $total=$total-$money;
        //echo '第'.$i.'个红包:领'.$money.' 元,余额:'.$total.' 元 <br/>';
        $sub_arr[] = $money;
    }
    //echo '00第'.$num.'个红包:'.$total.' 元,余额:0 元';
    array_push($sub_arr, $total);
    return $sub_arr;
}

/*********************************  抢红包方法3:封装开始 ***************************************/
/**
 * 功能:求一个数的平方
 */
function _sqr($n){
    return $n*$n;
}

/**
 * 功能:生产min和max之间的随机数,但是概率不是平均的,从min到max方向概率逐渐减小。
 * 先平方,然后产生一个平方值范围内的随机数,再开方,这样就产生了一种“膨胀”再“收缩”的效果。
 * @param $point_min 每个小红包的最小额
 * @param $point_max 每个小红包的最大额
 * @return int
 */
function _xRandom($point_min,$point_max){
    $sqr = intval(_sqr($point_max-$point_min));
    $rand_num = rand(0, ($sqr-1));
    return intval(sqrt($rand_num));
}

/**
 * 功能:产生红包
 * @param $total_point   红包总额
 * @param $total_people  红包个数
 * @param $point_max     每个小红包的最大额
 * @param $point_min     每个小红包的最小额
 * @return array         存放生成的每个小红包的值的一维数组
 */
function _getBonus($total_point, $total_people, $point_max, $point_min) {
    $result = array();
    $average = $total_point / $total_people;
    if($point_max < $average){
        for ($i = 0; $i < $total_people; $i++){
            $result[$i] = 5;
        }
        return $result;
    }

    for ($i = 0; $i < $total_people; $i++) {
        //因为小红包的数量通常是要比大红包的数量要多的,因为这里的概率要调换过来。
        //当随机数>平均值,则产生小红包
        //当随机数<平均值,则产生大红包
        if (rand($point_min, $point_max) > $average) {
            // 在平均线上加积分
            $temp = $point_min + _xRandom($point_min, $average);
            $result[$i] = $temp;
            $total_point -= $temp;
        } else {
            // 在平均线上减钱
            $temp = $point_max - _xRandom($average, $point_max);
            $result[$i] = $temp;
            $total_point -= $temp;
        }
    }
    // 如果还有余积分,则尝试加到小红包里,如果加不进去,则尝试下一个。
    while ($total_point > 0) {
        for ($i = 0; $i < $total_people; $i++) {
            if ($total_point > 0 && $result[$i] < $point_max) {
                $result[$i]++;
                $total_point--;
            }
        }
    }
    // 如果积分是负数了,还得从已生成的大于最小红包的红包中抽取回来
    while ($total_point < 0) {
        for ($i = 0; $i < $total_people; $i++) {
            if ($total_point < 0 && $result[$i] > $point_min) {
                $result[$i]--;
                $total_point++;
            }
        }
    }
    return $result;
}
/*********************************  抢红包方法3:封装结束 ***************************************/

2、调用上面的方法:

public function index()
    {
        // 1、抢红包
//        $result = open_int_red(1000,20);
//        $a = array_sum($result);
//        dump($a);
//        dump($result);die;

        // 2、抢红包方法
        $a = _getBonus(1000,50,200,1);
        dump(array_sum($a));
        dump($a);die;



        return View::fetch('login');
    }

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-06-23
  • 2022-12-23
  • 2021-05-26
  • 2021-07-06
  • 2022-02-05
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-04-08
  • 2021-10-05
  • 2018-03-27
  • 2021-11-23
相关资源
相似解决方案