thinkphp 抽奖算法
最近公司要做一个抽奖的小程序,经过两天的查阅资料,终于鼓捣出来一个。
大家如果觉得还OK ,就拿去用:
算法原理:
每个奖项都有一定的概率,比如说:0.01 0.09等等,所有奖项的概率的总和一定要为1.
对于一个奖项来说,每次中奖的概率都是一致的,只有当该奖品的数量为0 的时候,概率才会被清空,然后加到默认奖项(未中奖)中。
1、数据库设计(奖励表):
2、用的是thinkphp框架,大家凑合着看。
public function index() {
$award = M ( "prize" );
$list = $award->select ();
$prize = $this->_get_prize (100); //基数为100
$this->assign ( "award", $prize );
$this->display ();
}
/**
*
* @param unknown_type $mount 基数 100,1000
* @throws Exception
* @return unknown
*/
private function _get_prize($mount) {
$model = M ( "prize" );
// $prize = $model->select();
$prize = $model->order ( "award desc" )->getField ( "id,name,p,mount,award" ); //以id为键的关联数组
$gl = array (); // 概率数组,以奖励的id为key的关联数组
$num = 0; // 每个奖项的区间最大值
foreach ( $prize as $key => $value ) {
if ($value ["p"] == 0)
continue;
if ($value ["p"] > 1)
throw new Exception ( "概率不能大于1" );
$num += floor ( $mount * $value ["p"] );
$gl [$key] = $num;
}
$rand = mt_rand ( 1, $mount ); //随机数,当处于哪个区间,就中哪个奖励
foreach ( $gl as $k => $v ) {
if ($rand <= $v) {
if ($prize [$k] ["award"] == 0) //默认奖项
return $prize [$k];
$model->startTrans();
$model->where ( "id=" . $k )->setDec ( "mount", "1" );
if ($prize[$k]["mount"] == 1) {
$data1 = array("id"=>$k,"p"=>0);
$model->save($data1);
$model->execute("UPDATE prize SET p = p+{$prize[$k]["p"]} WHERE award = 0");
}
$model->commit();
return $prize [$k];
}
}
}
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
