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
adodb与adodb_lite之比较
Dec 31 PHP
mysql_num_rows VS COUNT 效率问题分析
Apr 23 PHP
php dirname(__FILE__) 获取当前文件的绝对路径
Jun 28 PHP
解析php中反射的应用
Jun 18 PHP
解析php多线程下载远程多个文件
Jun 25 PHP
PHP变量内存分配问题记录整理
Nov 27 PHP
盘点PHP和ASP.NET的10大对比!
Dec 24 PHP
PHP实现的通过参数生成MYSQL语句类完整实例
Apr 11 PHP
php简单的上传类分享
May 15 PHP
php源码之将图片转化为data/base64数据流实例详解
Nov 27 PHP
php/JS实现的生成随机密码(验证码)功能示例
Jun 06 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桌面中心(一) 创建数据库
2007/03/11 PHP
PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数的小问题
2011/05/29 PHP
php number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
一个比较不错的PHP日历类分享
2014/11/18 PHP
php字符集转换
2017/01/23 PHP
Symfony2针对输入时间进行查询的方法分析
2017/06/28 PHP
php判断IP地址是否在多个IP段内
2020/08/18 PHP
thinkphp诸多限制条件下如何getshell详解
2020/12/09 PHP
一段多浏览器的&quot;复制到剪贴板&quot;javascript代码
2007/03/27 Javascript
JQuery 绑定事件时传递参数的实现方法
2009/10/13 Javascript
Jquery下:nth-child(an+b)的使用注意
2011/05/28 Javascript
js原型链原理看图说明
2012/07/07 Javascript
JavaScript高级程序设计(第3版)学习笔记6 初识js对象
2012/10/11 Javascript
js触发onchange事件的方法说明
2014/03/08 Javascript
前端jquery部分很精彩
2016/05/03 Javascript
深入理解Ajax的get和post请求
2016/06/02 Javascript
node 利用进程通信实现Cluster共享内存
2017/10/27 Javascript
vue渲染时闪烁{{}}的问题及解决方法
2018/03/28 Javascript
JS倒计时两种实现方式代码实例
2020/07/27 Javascript
从零学python系列之从文件读取和保存数据
2014/05/23 Python
python处理文本文件并生成指定格式的文件
2014/07/31 Python
python实现将文本转换成语音的方法
2015/05/28 Python
在Python dataframe中出生日期转化为年龄的实现方法
2018/10/20 Python
Django 内置权限扩展案例详解
2019/03/04 Python
调试Django时打印SQL语句的日志代码实例
2019/09/12 Python
Django基于Models定制Admin后台实现过程解析
2020/11/11 Python
将世界上最美丽的摄影作品转化为艺术作品:Photos.com
2017/11/28 全球购物
神话般的珠宝:Ross-Simons
2020/07/13 全球购物
如果重写了对象的equals()方法,需要考虑什么
2014/11/02 面试题
小学教师的个人自我鉴定
2013/10/24 职场文书
2014年三八妇女节活动总结
2014/03/01 职场文书
培训讲师岗位职责
2014/04/13 职场文书
品酒会策划方案
2014/05/26 职场文书
个人贷款收入证明
2014/10/26 职场文书
2015年七一建党节活动总结
2015/03/20 职场文书
vue中的可拖拽宽度div的实现示例
2022/04/08 Vue.js