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 header()函数使用详细(301、404等错误设置)
Apr 17 PHP
php实现斐波那契数列的简单写法
Jul 19 PHP
PHP+MYSQL会员系统的开发实例教程
Aug 23 PHP
php实现监控varnish缓存服务器的状态
Dec 30 PHP
PHP微信开发之查询城市天气
Jun 23 PHP
超强多功能php绿色集成环境详解
Jan 25 PHP
PHP实现对数字分隔加千分号的方法
Mar 18 PHP
php统计数组不同元素的个数的实例方法
Sep 26 PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
Nov 21 PHP
PHP实现笛卡尔积算法的实例讲解
Dec 22 PHP
php反序列化长度变化尾部字符串逃逸(0CTF-2016-piapiapia)
Feb 15 PHP
windows系统php环境安装swoole具体步骤
Mar 04 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中使用imagick实现把PDF转成图片
2015/01/26 PHP
php格式化json函数示例代码
2016/05/12 PHP
php similar_text()函数的定义和用法
2016/05/12 PHP
php多线程并发实现方法
2016/09/30 PHP
浅析php-fpm静态和动态执行方式的比较
2016/11/09 PHP
php数据库操作model类(使用__call方法)
2016/11/16 PHP
thinkPHP中验证码的简单实现方法
2016/12/05 PHP
PHP面向对象程序设计之构造方法和析构方法详解
2019/06/13 PHP
User Scripts: Video Download by User Scripts
2007/05/14 Javascript
Js event事件在IE、FF兼容性问题
2011/01/01 Javascript
点弹代码 点击页面任何位置都可以弹出页面效果代码
2012/09/17 Javascript
js nextSibling属性和previousSibling属性概述及使用注意
2013/02/16 Javascript
Flash图片上传组件 swfupload使用指南
2015/03/14 Javascript
JavaScript获取指定元素位置的方法
2015/04/08 Javascript
详解Javascript继承的实现
2016/03/25 Javascript
使用Ajax和Jquery配合数据库实现下拉框的二级联动的示例
2018/01/25 jQuery
css配合JavaScript实现tab标签切换效果
2018/10/11 Javascript
小程序实现自定义导航栏适配完美版
2019/04/02 Javascript
详解 javascript对象创建模式
2020/10/30 Javascript
[00:23]DOTA2群星共贺开放测试 25日无码时代来袭
2013/09/23 DOTA
pyqt5 QScrollArea设置在自定义侧(任何位置)
2019/09/25 Python
详解pyinstaller selenium python3 chrome打包问题
2019/10/18 Python
pytorch 实现打印模型的参数值
2019/12/30 Python
Python3如何使用多线程升程序运行速度
2020/08/11 Python
浅谈CSS3 动画卡顿解决方案
2019/01/02 HTML / CSS
Html5实现首页动态视频背景的示例代码
2019/09/25 HTML / CSS
ESDlife健康生活易:身体检查预订、搜寻及比较
2019/05/10 全球购物
大学专科生推荐信范文
2013/11/23 职场文书
客房主管岗位职责
2013/12/09 职场文书
职业生涯规划书的格式
2013/12/29 职场文书
私人会所最新创业计划书范文
2014/03/24 职场文书
班干部演讲稿
2014/04/24 职场文书
孔繁森观后感
2015/06/10 职场文书
SQL实现LeetCode(177.第N高薪水)
2021/08/04 MySQL
唤醒紫霞仙子,携手再游三界!大话手游X《大话西游》电影合作专属剧情任务
2022/04/03 其他游戏
victoriaMetrics库布隆过滤器初始化及使用详解
2022/04/05 Golang