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 相关文章推荐
IIS下PHP连接数据库提示mysql undefined function mysql_connect()
Jun 04 PHP
PHP句法规则详解 入门学习
Nov 09 PHP
基于PHP Socket配置以及实例的详细介绍
Jun 13 PHP
PHP中foreach()用法汇总
Jul 02 PHP
使用PHP如何实现高效安全的ftp服务器(一)
Dec 20 PHP
反射调用private方法实践(php、java)
Dec 21 PHP
php中简单的对称加密算法实现
Jan 05 PHP
PHP操作MySQL中BLOB字段的方法示例【存储文本与图片】
Sep 15 PHP
ThinkPHP框架实现的邮箱激活功能示例
Jun 15 PHP
深入理解 PHP7 中全新的 zval 容器和引用计数机制
Oct 15 PHP
php实现算术验证码功能
Dec 05 PHP
laravel 错误处理,接口错误返回json代码
Oct 25 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
教你如何把一篇文章按要求分段
2006/10/09 PHP
PHP UTF8编码内的繁简转换类
2009/07/20 PHP
php分页代码学习示例分享
2014/02/20 PHP
PHP获取photoshop写入图片文字信息的方法
2015/03/31 PHP
ThinkPHP模板Volist标签嵌套循环输出多维数组的方法
2016/03/23 PHP
PHP面向对象五大原则之开放-封闭原则(OCP)详解
2018/04/04 PHP
PHP实现的DES加密解密类定义与用法示例
2020/11/02 PHP
PHP code 验证码生成类定义和简单使用示例
2020/05/27 PHP
Extjs TimeField 显示正常时间格式的代码
2011/06/28 Javascript
JS控件的生命周期介绍
2012/10/22 Javascript
html+javascript实现可拖动可提交的弹出层对话框效果
2013/08/05 Javascript
jQuery封装的获取Url中的Get参数示例
2013/11/26 Javascript
node.js中的fs.writeSync方法使用说明
2014/12/15 Javascript
JavaScript Length 属性的总结
2015/11/02 Javascript
JavaScript数据类型学习笔记
2016/01/25 Javascript
jquery实现超简单的瀑布流布局【推荐】
2017/03/08 Javascript
详解ES6之用let声明变量以及let loop机制
2017/07/15 Javascript
详解Angular6.0使用路由步骤(共7步)
2018/06/29 Javascript
vue-i18n实现中英文切换的方法
2020/07/06 Javascript
vue实现的多页面项目如何优化打包的步骤详解
2020/07/19 Javascript
[51:20]完美世界DOTA2联赛PWL S2 Magma vs PXG 第一场 11.28
2020/12/01 DOTA
Ubuntu下创建虚拟独立的Python环境全过程
2017/02/10 Python
python的Tqdm模块的使用
2018/01/10 Python
pytorch构建网络模型的4种方法
2018/04/13 Python
python读取文件名称生成list的方法
2018/04/27 Python
python 读取txt中每行数据,并且保存到excel中的实例
2018/04/29 Python
python-opencv颜色提取分割方法
2018/12/08 Python
python简单实现矩阵的乘,加,转置和逆运算示例
2019/07/10 Python
手写一个python迭代器过程详解
2019/08/27 Python
Jupyter notebook如何实现指定浏览器打开
2020/05/13 Python
受欢迎的大学生自我评价
2013/12/05 职场文书
ktv筹备计划书
2014/05/03 职场文书
感恩小明星事迹材料
2014/05/23 职场文书
应聘教师求职信范文
2015/03/20 职场文书
2019森林防火宣传标语大全!
2019/07/03 职场文书
Python利用zhdate模块实现农历日期处理
2022/03/31 Python