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 相关文章推荐
WINDOWS 2000下使用ISAPI方式安装PHP
Sep 05 PHP
php echo 输出字符串函数详解
May 13 PHP
PHP基础陷阱题(变量赋值)
Sep 12 PHP
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
Jun 20 PHP
PHP定时更新程序设计思路分享
Jun 10 PHP
PHP和Mysql中转UTF8编码问题汇总
Oct 10 PHP
PHP中的密码加密的解决方案总结
Oct 26 PHP
PHP 微信扫码支付源代码(推荐)
Nov 03 PHP
PHP 搜索查询功能实现
Nov 29 PHP
PHP实现财务审核通过后返现金额到客户的功能
Jul 04 PHP
php5.6.x到php7.0.x特性小结
Aug 17 PHP
Laravel5.5 视图 - 创建视图和数据传递示例
Oct 21 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多进程编程实例详解
2017/07/19 PHP
Display SQL Server Login Mode
2007/06/21 Javascript
javascript 清除输入框中的数据
2009/04/13 Javascript
ExtJS4 组件化编程,动态加载,面向对象,Direct
2011/05/12 Javascript
关于jQuery新的事件绑定机制on()的使用技巧
2013/04/26 Javascript
jQuery动画效果-slideUp slideDown上下滑动示例代码
2013/08/28 Javascript
解析Javascript中难以理解的11个问题
2013/12/09 Javascript
append和appendTo的区别以及appendChild用法
2013/12/24 Javascript
transport.js和jquery冲突问题的解决方法
2015/02/10 Javascript
基于javascript实现窗口抖动效果
2016/01/03 Javascript
jquery操作select元素和option的实例代码
2016/02/03 Javascript
在小程序/mpvue中使用flyio发起网络请求的方法
2018/09/13 Javascript
Node.js console控制台简单用法分析
2019/01/04 Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
2020/05/01 Javascript
webstorm建立vue-cli脚手架的傻瓜式教程
2020/09/22 Javascript
[00:47]DOTA2荣耀之路6:天火,天火!
2018/05/30 DOTA
[49:08]OpTic vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
实践Python的爬虫框架Scrapy来抓取豆瓣电影TOP250
2016/01/20 Python
Python 常用string函数详解
2016/05/30 Python
使用XML库的方式,实现RPC通信的方法(推荐)
2017/06/14 Python
Django中利用filter与simple_tag为前端自定义函数的实现方法
2017/06/15 Python
python版简单工厂模式
2017/10/16 Python
python flask几分钟实现web服务的例子
2019/07/26 Python
利用setuptools打包python程序的方法步骤
2020/01/18 Python
Django自定义列表 models字段显示方式
2020/04/03 Python
Tensorflow与Keras自适应使用显存方式
2020/06/22 Python
pytorch 中forward 的用法与解释说明
2021/02/26 Python
世界上最大的售后摩托车零配件超市:J&P Cycles
2017/12/08 全球购物
Hurley官方网站:扎根于海滩生活方式的全球青年文化品牌
2020/05/18 全球购物
社会学专业学生职业规划书
2014/02/07 职场文书
银行内勤岗位职责
2014/04/09 职场文书
爱护草坪标语
2014/06/24 职场文书
民警群众路线教育实践活动对照检查材料
2014/10/04 职场文书
党小组意见范文
2015/06/08 职场文书
2016天猫双十一广告语
2016/01/28 职场文书
2016年综治和平安建设宣传月活动总结
2016/04/01 职场文书