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


Posted in PHP onJanuary 02, 2016

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在某个奖品的权重范围值内,标识这个奖品被抽取到

<?php
/**
 * 奖品
 */
class Prize {
  # ID
  public $id = null;
  # 权重
  public $weight = null;
  # 奖品名
  public $name = null;
 
  # 权重范围区间起始值
  protected $start = 0;
  # 权重范围区间结束值
  protected $end = 0;
 
  public function __construct($id, $weight, $name) {
    if (!$id) {
      throw new Exception('奖品ID为空.');
    }
    $this->id = $id;
    $this->weight = $weight ? $weight : 0;
    $this->name = $name ? $name : '随机奖品' . $id;
  }
 
  # id
  public function getId() {
    return $this->id;
  }
 
  # 权重
  public function getWeight() {
    return $this->weight;
  }
 
  # 设置权重范围区间
  public function setRange($start, $end) {
    $this->start = $start;
    $this->end = $end;
  }
 
  # 判断随机数是否在权重范围区间
  public function inRange($num) {
    return ($num >= $this->start) && ($num <= $this->end);
  }
}
 
/**
 * 奖品池
 */
class PrizePoll implements IteratorAggregate, Countable {
  # 奖品集
  protected $items = array();
 
  # 加入奖品
  public function addItem(Prize $item) {
    $this->items[$item->getId()] = $item;
    return $this;
  }
 
  # 删除奖品
  public function removeItem($itemId) {
    if (isset($this->items[$itemId])) {
      unset($this->items[$itemId]);
    }
    return $this;
  }
 
  # 更新奖品
  public function updateItem(Prize $item) {
    if (isset($this->items[$item->getId()])) {
      $this->items[$item->getId()] = $item;
    }
    return $this;
  }
 
  # 获取所有奖品
  public function getItems() {
    return $this->items;
  }
 
  # 所有所有可用奖品(如果权重为0,说明这个奖品永远不可能抽到)
  public function getVisibleItems() {
    $items = array();
    foreach ($this->items as $item) {
      if ($item->getWeight()) {
        $items[$item->getId()] = $item;
      }
    }
    return $items;
  }
 
  # Countable::count
  public function count() {
    return count($this->items);
  }
 
  # IteratorAggregate::getIterator()
  public function getIterator() {
    return new ArrayIterator($this->items);
  }
}
 
/**
 * 简单的抽奖类
 */
class SimpleTurn {
  # 奖池
  protected $poll = null;
   
  public function __construct(PrizePoll $poll) {
    if ($poll) {
      $this->setPoll($poll);
    }
  }
 
  # 抽奖
  public function run(PrizePoll $poll) {
    $poll = $poll ? $poll : $this->poll;
    if ( ! $poll) {
      throw new Exception('奖池未初始化');
    }
 
    if ($poll->count() <= 0) {
      throw new Exception('奖池为空');
    }
 
    $items = $poll->getVisibleItems();
    if (count($items) <= 0) {
      throw new Exception('奖池为空');
    }
 
    $sum = 0;
    foreach ($items as $item) {
      $start = $sum + 1;
      $sum += $item->getWeight();
      $end = $sum;
 
      # 设置奖品的权重范围区间
      $item->setRange($start, $end);
    }
 
    # 随机数
    $rand = $this->getRandNum(1, $sum);
 
    # 区间段判断
    foreach ($items as $item) {
      if ($item->inRange($rand)) {
        return $item;
      }
    }
    return null;
  }
 
  # 获取随机数
  public function getRandNum($min, $max) {
    return mt_rand($min ? $min : 1, $max);
  }
 
  # 设置奖池
  public function setPoll(PrizePoll $poll) {
    $this->poll = $poll;
  }
}
 
# 示例
try {
  $prizePoll = new PrizePoll();
  $prizePoll->addItem(new Prize(1, 5))
    ->addItem(new Prize(2, 6))
    ->addItem(new Prize(3, 7))
    ->addItem(new Prize(4, 2));
 
  $turn = new SimpleTurn($prizePoll);
  $prize = $turn->run();
  var_dump($prize);
} catch (Exception $e) {
  print_r($e);
}
PHP 相关文章推荐
玩转虚拟域名◎+ .
Oct 09 PHP
php数组函数序列之array_push() 数组尾部添加一个或多个元素(入栈),返回新长度。
Nov 07 PHP
深入理解ob_flush和flush的区别(ob_flush()与flush()使用方法)
Feb 06 PHP
file_get_contents(&quot;php://input&quot;, &quot;r&quot;)实例介绍
Jul 01 PHP
php调用MySQL存储过程的方法集合(推荐)
Jul 03 PHP
php中mail函数发送邮件失败的解决方法
Dec 24 PHP
WampServer搭建php环境时遇到的问题汇总
Jul 23 PHP
PHP版本升级到7.x后wordpress的一些修改及wordpress技巧
Dec 25 PHP
详解PHP的Yii框架的运行机制及其路由功能
Mar 17 PHP
php关闭warning问题的解决方法
May 17 PHP
php实现微信模拟登陆、获取用户列表及群发消息功能示例
Jun 28 PHP
详解如何实现Laravel的服务容器的方法示例
Apr 15 PHP
php实现给一张图片加上水印效果
Jan 02 #PHP
前端必学之PHP语法基础
Jan 01 #PHP
WordPress中登陆后关闭登陆页面及设置用户不可见栏目
Dec 31 #PHP
WordPress中获取指定分类及其子分类下的文章数目
Dec 31 #PHP
Swoole-1.7.22 版本已发布,修复PHP7相关问题
Dec 31 #PHP
WordPress中给媒体文件添加分类和标签的PHP功能实现
Dec 31 #PHP
简单了解将WordPress中的工具栏移到底部的小技巧
Dec 31 #PHP
You might like
无线电广播的开始
2002/01/30 无线电
社区(php&amp;&amp;mysql)一
2006/10/09 PHP
PHP防盗链的基本思想 防盗链的设置方法
2015/09/25 PHP
PHP基于递归实现的约瑟夫环算法示例
2017/08/27 PHP
JavaScript入门系列之知识点总结
2016/03/24 Javascript
Bootstrap 粘页脚效果
2016/03/28 Javascript
Node.js设置CORS跨域请求中多域名白名单的方法
2017/03/28 Javascript
微信小程序 跳转方式总结
2017/04/20 Javascript
微信小程序 选项卡的简单实例
2017/05/24 Javascript
jQuery实现的模仿雨滴下落动画效果
2018/12/11 jQuery
如何实现小程序tab栏下划线动画效果
2019/05/18 Javascript
vue中利用Promise封装jsonp并调取数据
2019/06/18 Javascript
package.json配置文件构成详解
2019/08/27 Javascript
Vue中component标签解决项目组件化操作
2020/09/04 Javascript
[45:14]Optic vs VP 2018国际邀请赛淘汰赛BO3 第二场 8.24
2018/08/25 DOTA
[48:24]完美世界DOTA2联赛PWL S3 Forest vs INK ICE 第一场 12.09
2020/12/12 DOTA
Python代理抓取并验证使用多线程实现
2013/05/03 Python
Python实例之wxpython中Frame使用方法
2014/06/09 Python
Python中的字符串查找操作方法总结
2016/06/27 Python
python 输出所有大小写字母的方法
2019/01/02 Python
Python 使用list和tuple+条件判断详解
2019/07/30 Python
Python爬虫实现模拟点击动态页面
2020/03/05 Python
Python函数参数分类原理详解
2020/05/28 Python
利用scikitlearn画ROC曲线实例
2020/07/02 Python
Python中logging日志记录到文件及自动分割的操作代码
2020/08/05 Python
Pycharm Plugins加载失败问题解决方案
2020/11/28 Python
简单掌握CSS3中resize属性的用法
2016/04/01 HTML / CSS
基于 HTML5 WebGL 实现的医疗物流系统
2019/10/08 HTML / CSS
兼职学生的自我评价
2013/11/24 职场文书
学习标兵获奖感言
2014/02/20 职场文书
学校端午节活动方案
2014/08/23 职场文书
财务总监岗位职责
2015/02/03 职场文书
2015年见习期个人工作总结
2015/05/28 职场文书
中国古代史学名著《战国策》概述
2019/08/09 职场文书
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis
java泛型通配符详解
2021/07/25 Java/Android