Php写一个简单的抽奖功能

可重复的抽奖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
$prize_arr = [
	['title' => '500金币', 'id' => 5, 'weight' => 1],
	['title' => '免禁buff48小时体验', 'id' => 1, 'weight' => 2],
	['title' => '防偷buff48小时体验', 'id' => 2, 'weight' => 2],
	['title' => '免禁buff24小时体验', 'id' => 3, 'weight' => 3],
	['title' => '防偷buff24小时体验', 'id' => 4, 'weight' => 3],
	['title' => '100金币', 'id' => 6, 'weight' => 3],
	['title' => '50金币', 'id' => 7, 'weight' => 6],
	['title' => '5金币', 'id' => 8, 'weight' => 10],
];

function getRand($prize_arr) {
	$result = count($prize_arr)-1; // 默认数组最后用一个
	$pro_sum = array_sum(array_map('array_pop', $prize_arr)); // 拿到总数
	// $pro_sum = array_sum(array_column($prize_arr, 'weight'));  // 两个方法都ok

	foreach ($prize_arr as $key => $value) {
		$rand_num = mt_rand(1, $pro_sum);
		if ($rand_num <= $value['weight']) {
			$result = $key;
			break;
		} else {
			$pro_sum -= $value['weight']; // 说明没有抽到,减去权重,继续来
		}
	}
	return $result;
}

30次测试一下

1
2
3
4
5
6
7
8
9
<?php
$test = [0,0,0,0,0,0,0,0];
for ($i=0; $i < 30; $i++) {
	$result = getRand($prize_arr);
	$test[$result] +=1;
	echo $prize_arr[$result]['title'].PHP_EOL;
}

print_r($test);

两次测试结果: 两次测试

不可重复,抽完就少一个

代码上就加一个引用,然后抽一次权重个数减少一个

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
function getRand(&$prize_arr) {  // 地址引用
	$result = count($prize_arr)-1; // 默认数组最后用一个
	$pro_sum = array_sum(array_map('array_pop', $prize_arr)); // 拿到总数
	// $pro_sum = array_sum(array_column($prize_arr, 'weight'));  // 两个方法都ok

	foreach ($prize_arr as $key => $value) {
		$rand_num = mt_rand(1, $pro_sum);
		if ($rand_num <= $value['weight']) {
			$result = $key;
			$prize_arr[$key]['weight'] -= 1;  // 权重减一
			$pro_sum -= 1;  // 总数减一 ,或者把$pro_sum 那一句写进foreach里边
			break;
		} else {
			$pro_sum -= $value['weight']; // 说明没有抽到,减去权重,继续来
		}
	}
	return $result;
}

两次测试结果: 两次测试结果