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循环获取GET和POST值的代码
Apr 09 PHP
php 字符过滤类,用于过滤各类用户输入的数据
May 27 PHP
PHP 动态随机生成验证码类代码
Apr 09 PHP
PHP实现异步调用方法研究与分享
Oct 27 PHP
PHP 5.3和PHP 5.4出现FastCGI Error解决方法
Feb 12 PHP
[原创]php获取数组中键值最大数组项的索引值
Mar 17 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
Sep 23 PHP
PHP利用超级全局变量$_POST来接收表单数据的实例
Nov 05 PHP
解析PHP之提取多维数组指定列的方法
Jan 03 PHP
PHP实现的简单对称加密与解密方法实例小结
Aug 28 PHP
PHP explode()函数用法讲解
Feb 15 PHP
PHP7 新增常量
Mar 09 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木马攻击防御之道
2008/03/24 PHP
Blitz templates 最快的PHP模板引擎
2010/04/06 PHP
php实例分享之二维数组排序
2014/05/15 PHP
常用的php图片处理类(水印、等比缩放、固定高宽)分享
2015/06/19 PHP
全面解读PHP的Yii框架中的日志功能
2016/03/17 PHP
PHP微信开发之有道翻译
2016/06/23 PHP
Yii2框架制作RESTful风格的API快速入门教程
2016/11/08 PHP
php反射学习之依赖注入示例
2019/06/14 PHP
强制设为首页代码
2006/06/19 Javascript
popdiv
2006/07/14 Javascript
js 通用javascript函数库整理
2011/08/14 Javascript
JQuery for与each性能比较分析
2013/05/14 Javascript
Angular用来控制元素的展示与否的原生指令介绍
2015/01/07 Javascript
浅谈javascript:两种注释,声明变量,定义函数
2016/10/05 Javascript
js关于getImageData跨域问题的解决方法
2016/10/14 Javascript
Bootstrap基本插件学习笔记之模态对话框(16)
2016/12/08 Javascript
jQuery完成表单验证的实例代码(纯代码)
2017/09/30 jQuery
如何在js代码中消灭for循环实例详解
2018/07/29 Javascript
详解使用Nuxt.js快速搭建服务端渲染(SSR)应用
2019/03/13 Javascript
如何让Nodejs支持H5 History模式(connect-history-api-fallback源码分析)
2019/05/30 NodeJs
Vue多环境代理配置方法思路详解
2019/06/21 Javascript
React Native 混合开发多入口加载方式详解
2019/09/23 Javascript
vue滚动插件better-scroll使用详解
2019/10/18 Javascript
JS addEventListener()和attachEvent()方法实现注册事件
2021/01/11 Javascript
python实现Decorator模式实例代码
2018/02/09 Python
python中利用zfill方法自动给数字前面补0
2018/04/10 Python
python中itertools模块zip_longest函数详解
2018/06/12 Python
对python中xlsx,csv以及json文件的相互转化方法详解
2018/12/25 Python
python给微信好友定时推送消息的示例
2019/02/20 Python
计算机二级python学习教程(2) python语言基本语法元素
2019/05/16 Python
Python timeit模块的使用实践
2020/01/13 Python
CSS3 实现穿梭星空动画
2020/11/13 HTML / CSS
工程师自我评价怎么写
2013/09/19 职场文书
中专毕业个人的自荐信格式
2013/09/21 职场文书
物业公司管理制度
2015/08/05 职场文书
导游词之山东八仙过海景区
2019/11/11 职场文书