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 相关文章推荐
如何正确理解PHP的错误信息
Oct 09 PHP
PHP 将图片按创建时间进行分类存储的实现代码
Jan 05 PHP
用PHP获取Google AJAX Search API 数据的代码
Mar 12 PHP
整理的9个实用的PHP库简介和下载
Nov 09 PHP
array_multisort实现PHP多维数组排序示例讲解
Jan 04 PHP
PHP使用数组实现队列
Feb 05 PHP
启用Csrf后POST数据时出现的400错误
Jul 05 PHP
php读取torrent种子文件内容的方法(测试可用)
May 03 PHP
thinkphp在php7环境下提示Cannot use ‘String’ as class name as it is reserved的解决方法
Sep 30 PHP
PHP实现加密文本文件并限制特定页面的存取的效果
Oct 21 PHP
php简单随机字符串生成方法示例
Apr 19 PHP
PHP面向对象类型约束用法分析
Jun 12 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
劣质的PHP代码简化
2010/02/08 PHP
PHP连接SQLServer2005 的问题解决方法
2010/07/19 PHP
Symfony2函数用法实例分析
2016/03/18 PHP
PHP中类的继承和用法实例分析
2016/05/24 PHP
php利用递归实现删除文件目录的方法
2016/09/23 PHP
PHP使用redis消息队列发布微博的方法示例
2017/06/22 PHP
PHP安装扩展mcrypt以及相关依赖项深入讲解
2021/03/04 PHP
javascript一个无懈可击的实例化XMLHttpRequest的方法
2010/10/13 Javascript
使用jquery与图片美化checkbox和radio控件的代码(打包下载)
2010/11/11 Javascript
js RuntimeObject() 获取ie里面自定义函数或者属性的集合
2010/11/23 Javascript
jquery事件机制扩展插件 jquery鼠标右键事件
2011/12/21 Javascript
面向对象Javascript核心支持代码分享
2012/05/23 Javascript
js 获取屏幕各种宽高的方法(浏览器兼容)
2013/05/15 Javascript
浅析JQuery中的html(),text(),val()区别
2014/09/01 Javascript
jQueryMobile之Helloworld与页面切换的方法
2015/02/04 Javascript
JS实现仿中关村论坛评分后弹出提示效果的方法
2015/02/23 Javascript
jquery实现的仿天猫侧导航tab切换效果
2015/08/24 Javascript
基于Bootstrap实现图片轮播效果
2016/05/22 Javascript
跨域请求的完美解决方法(JSONP, CORS)
2016/06/12 Javascript
原生js实现对Ajax的封装(仿jquery)
2017/01/22 Javascript
解决angular 使用原生拖拽页面卡顿及表单控件输入延迟问题
2020/04/21 Javascript
[07:54]DOTA2-DPC中国联赛 正赛 iG vs VG 选手采访
2021/03/11 DOTA
Python写的Socks5协议代理服务器
2014/08/06 Python
Python下的twisted框架入门指引
2015/04/15 Python
Python 如何访问外围作用域中的变量
2016/09/11 Python
Python实现一个简单的验证码程序
2017/11/03 Python
django项目搭建与Session使用详解
2018/10/10 Python
python+pyqt5实现24点小游戏
2019/01/24 Python
如何在VSCode上轻松舒适的配置Python的方法步骤
2019/10/28 Python
Django Admin设置应用程序及模型顺序方法详解
2020/04/01 Python
Python3创建Django项目的几种方法(3种)
2020/06/03 Python
实例讲解CSS3中的box-flex弹性盒属性布局
2016/06/09 HTML / CSS
Vans英国官方网站:美国南加州的原创极限运动潮牌
2017/01/20 全球购物
27个经典Linux面试题及答案,你知道几个?
2013/01/10 面试题
业务员简历自我评价
2014/03/06 职场文书
WebWorker 封装 JavaScript 沙箱详情
2021/11/02 Javascript