当前位置:首页 > PHP教程 > php应用 > 列表

php实现概率性随机抽奖代码

发布:smiling 来源: PHP粉丝网  添加日期:2021-07-03 22:01:17 浏览: 评论:0 

本文给大家分享的是使用php根据奖品的权重来实现概率性随机抽奖的代码,非常的使用,有类似需求的小伙伴,可以拿去参考下。

1、初始数据:

权重越大,抽取的几率越高

[奖品1, 权重 5], [ 奖品2, 权重6], [ 奖品3, 权重 7], [ 奖品4, 权重2]

2、处理步骤:

1)N = 5 + 6 + 7 + 2 = 20

2)然后取1-N的随机数M

3)界定各 奖品的权重范围值 奖品 1 : 1-5 ; 奖品2 : 6-11; 奖品3: 12-18; 奖品4: 19-20

4) 如果M在某个奖品的权重范围值内,标识这个奖品被抽取到

  1. <?php 
  2. /** 
  3.  * 奖品 
  4.  */ 
  5. class Prize { 
  6.   # ID 
  7.   public $id = null; 
  8.   # 权重 
  9.   public $weight = null; 
  10.   # 奖品名 
  11.   public $name = null; 
  12.    
  13.   # 权重范围区间起始值 
  14.   protected $start = 0; 
  15.   # 权重范围区间结束值 
  16.   protected $end = 0; 
  17.    
  18.   public function __construct($id, $weight, $name) { 
  19.     if (!$id) { 
  20.       throw new Exception('奖品ID为空.'); 
  21.     } 
  22.     $this->id = $id; 
  23.     $this->weight = $weight ? $weight : 0; 
  24.     $this->name = $name ? $name : '随机奖品' . $id; 
  25.   } 
  26.    
  27.   # id 
  28.   public function getId() { 
  29.     return $this->id; 
  30.   } 
  31.    
  32.   # 权重 
  33.   public function getWeight() { 
  34.     return $this->weight; 
  35.   } 
  36.    
  37.   # 设置权重范围区间 
  38.   public function setRange($start, $end) { 
  39.     $this->start = $start; 
  40.     $this->end = $end; 
  41.   } 
  42.    
  43.   # 判断随机数是否在权重范围区间 
  44.   public function inRange($num) { 
  45.     return ($num >= $this->start) && ($num <= $this->end); 
  46.   } 
  47. } 
  48.    
  49. /** 
  50.  * 奖品池 
  51.  */ 
  52. class PrizePoll implements IteratorAggregate, Countable { 
  53.   # 奖品集 
  54.   protected $items = array(); 
  55.    
  56.   # 加入奖品 
  57.   public function addItem(Prize $item) { 
  58.     $this->items[$item->getId()] = $item; 
  59.     return $this; 
  60.   } 
  61.    
  62.   # 删除奖品 
  63.   public function removeItem($itemId) { 
  64.     if (isset($this->items[$itemId])) { 
  65.       unset($this->items[$itemId]); 
  66.     } 
  67.     return $this; 
  68.   } 
  69.    
  70.   # 更新奖品 
  71.   public function updateItem(Prize $item) { 
  72.     if (isset($this->items[$item->getId()])) { 
  73.       $this->items[$item->getId()] = $item; 
  74.     } 
  75.     return $this; 
  76.   } 
  77.    
  78.   # 获取所有奖品 
  79.   public function getItems() { 
  80.     return $this->items; 
  81.   } 
  82.    
  83.   # 所有所有可用奖品(如果权重为0,说明这个奖品永远不可能抽到) 
  84.   public function getVisibleItems() { 
  85.     $items = array(); 
  86.     foreach ($this->items as $item) { 
  87.       if ($item->getWeight()) { 
  88.         $items[$item->getId()] = $item; 
  89.       } 
  90.     } 
  91.     return $items; 
  92.   } 
  93.    
  94.   # Countable::count 
  95.   public function count() { 
  96.     return count($this->items); 
  97.   } 
  98.    
  99.   # IteratorAggregate::getIterator() 
  100.   public function getIterator() { 
  101.     return new ArrayIterator($this->items); 
  102.   } 
  103. } 
  104.    
  105. /** 
  106.  * 简单的抽奖类 
  107.  */ 
  108. class SimpleTurn { 
  109.   # 奖池 
  110.   protected $poll = null; 
  111.      
  112.   public function __construct(PrizePoll $poll) { 
  113.     if ($poll) { 
  114.       $this->setPoll($poll); 
  115.     } 
  116.   } 
  117.    
  118.   # 抽奖 
  119.   public function run(PrizePoll $poll) { 
  120.     $poll = $poll ? $poll : $this->poll; 
  121.     if ( ! $poll) { 
  122.       throw new Exception('奖池未初始化'); 
  123.     } 
  124.    
  125.     if ($poll->count() <= 0) { 
  126.       throw new Exception('奖池为空'); 
  127.     } 
  128.    
  129.     $items = $poll->getVisibleItems(); 
  130.     if (count($items) <= 0) { 
  131.       throw new Exception('奖池为空'); 
  132.     } 
  133.    
  134.     $sum = 0; 
  135.     foreach ($items as $item) { 
  136.       $start = $sum + 1; 
  137.       $sum += $item->getWeight(); 
  138.       $end = $sum; 
  139.    
  140.       # 设置奖品的权重范围区间 
  141.       $item->setRange($start, $end); 
  142.     } 
  143.    
  144.     # 随机数 
  145.     $rand = $this->getRandNum(1, $sum); 
  146.    
  147.     # 区间段判断 
  148.     foreach ($items as $item) { 
  149.       if ($item->inRange($rand)) { 
  150.         return $item; 
  151.       } 
  152.     } 
  153.     return null; 
  154.   } 
  155.    
  156.   # 获取随机数 
  157.   public function getRandNum($min, $max) { 
  158.     return mt_rand($min ? $min : 1, $max); 
  159.   } 
  160.    
  161.   # 设置奖池 
  162.   public function setPoll(PrizePoll $poll) { 
  163.     $this->poll = $poll; 
  164.   } 
  165. } 
  166.    
  167. # 示例 
  168. try { 
  169.   $prizePoll = new PrizePoll(); 
  170.   $prizePoll->addItem(new Prize(1, 5)) 
  171.     ->addItem(new Prize(2, 6)) 
  172.     ->addItem(new Prize(3, 7)) 
  173.     ->addItem(new Prize(4, 2)); 
  174.    
  175.   $turn = new SimpleTurn($prizePoll); 
  176.   $prize = $turn->run(); 
  177.   var_dump($prize); 
  178. } catch (Exception $e) { 
  179.   print_r($e); 
  180. }

Tags: php概率性随机抽奖

分享到: