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 相关文章推荐
手把手教你使用DedeCms的采集的图文教程
Mar 11 PHP
ionCube 一款类似zend的PHP加密/解密工具
Jul 25 PHP
关于Iframe如何跨域访问Cookie和Session的解决方法
Apr 15 PHP
深入array multisort排序原理的详解
Jun 18 PHP
微信公众号点击菜单即可打开并登录微站的实现方法
Nov 14 PHP
PHP通过串口实现发送短信
Jul 08 PHP
PHP的Yii框架使用中的一些错误解决方法与建议
Aug 21 PHP
PHP的Yii框架的基本使用示例
Aug 21 PHP
php实现按天数、星期、月份查询的搜索框
May 02 PHP
PHP中子类重载父类的方法【parent::方法名】
May 06 PHP
php获取excel文件数据
Apr 21 PHP
PDO::prepare讲解
Jan 29 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
DedeCMS dede_channeltype表字段注释
2010/04/07 PHP
thinkPHP利用ajax异步上传图片并显示、删除的示例
2018/09/26 PHP
php+js实现裁剪任意形状图片
2018/10/31 PHP
PHP操作Redis常用命令的实例详解
2020/12/23 PHP
在Javascript中为String对象添加trim,ltrim,rtrim方法
2006/09/22 Javascript
jQuery 插件 将this下的div轮番显示
2009/04/09 Javascript
JS删除数组元素的函数介绍
2013/03/27 Javascript
js中settimeout方法加参数的使用实例
2014/02/27 Javascript
JQuery中绑定事件(bind())和移除事件(unbind())
2015/02/27 Javascript
JavaScript和JQuery的鼠标mouse事件冒泡处理
2015/06/19 Javascript
jquery.validate提示错误信息位置方法
2016/01/22 Javascript
jquery 遍历数组 each 方法详解
2016/05/25 Javascript
JavaScript的字符串方法汇总
2016/07/31 Javascript
JS实现仿PS的调色板效果完整实例
2016/12/21 Javascript
vue-cli2打包前和打包后的css前缀不一致的问题解决
2018/08/24 Javascript
Nuxt.js SSR与权限验证的实现
2018/11/21 Javascript
解决微信小程序中转换时间格式IOS不兼容的问题
2019/02/15 Javascript
Vue函数式组件-你值得拥有
2019/05/09 Javascript
Vue select 绑定动态变量的实例讲解
2020/10/22 Javascript
Python聊天室实例程序分享
2016/01/05 Python
python中json格式数据输出的简单实现方法
2016/10/31 Python
python入门基础之用户输入与模块初认识
2016/11/14 Python
深入理解python中的select模块
2017/04/23 Python
python3使用SMTP发送简单文本邮件
2018/06/19 Python
用Python PIL实现几个简单的图片特效
2019/01/18 Python
Python高级特性之闭包与装饰器实例详解
2019/11/19 Python
python将时分秒转换成秒的实例
2019/12/07 Python
Python实现发票自动校核微信机器人的方法
2020/05/22 Python
python“静态”变量、实例变量与本地变量的声明示例
2020/11/13 Python
HTML5所有标签汇总及标签意义解释
2015/03/12 HTML / CSS
美国摄影爱好者购物网站:Focus Camera
2016/10/21 全球购物
美国隐形眼镜销售网站:ContactsDirect
2017/10/28 全球购物
小区保洁员岗位职责
2015/04/10 职场文书
二年级数学教学反思
2016/02/16 职场文书
大学生创业计划书常用模板
2019/08/07 职场文书
pytorch显存一直变大的解决方案
2021/04/08 Python