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中fgetcsv()函数用法实例
Nov 28 PHP
php页面函数设置超时限制的方法
Dec 01 PHP
php中magic_quotes_gpc对unserialize的影响分析
Dec 16 PHP
PHP自毁程序(慎用)
Jul 09 PHP
php递归实现无限分类的方法
Jul 28 PHP
PHP按指定键值对二维数组进行排序的方法
Dec 22 PHP
PHP中的session安全吗?
Jan 22 PHP
汇总PHPmailer群发Gmail的常见问题
Feb 24 PHP
Laravle eloquent 多对多模型关联实例详解
Nov 22 PHP
php实现简单的守护进程创建、开启与关闭操作
Aug 13 PHP
php实现根据身份证获取精准年龄
Feb 26 PHP
PHP内存溢出优化代码详解
Feb 26 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
10条PHP编程习惯助你找工作
2008/09/29 PHP
php入门学习知识点一 PHP与MYSql连接与查询
2011/07/14 PHP
解析PHP的session过期设置
2013/06/29 PHP
帝国CMS留言板回复后发送EMAIL通知客户
2015/07/06 PHP
thinkPHP模板引擎用法示例
2016/12/08 PHP
laravel-admin 实现在指定的相册下添加照片
2019/10/21 PHP
UpdatePanel和Jquery冲突的解决方法
2013/04/01 Javascript
JavaScript通过function定义对象并给对象添加toString()方法实例分析
2015/03/23 Javascript
jQuery实现图像旋转动画效果
2016/05/29 Javascript
jQuery EasyUI 获取tabs的实例解析
2016/12/06 Javascript
jQuery Validate验证表单时多个name相同的元素只验证第一个的解决方法
2016/12/24 Javascript
详解Angular4中路由Router类的跳转navigate
2017/06/09 Javascript
在 Vue 应用中使用 Netlify 表单功能的方法详解
2019/06/03 Javascript
JavaScript 如何计算文本的行数的实现
2020/09/14 Javascript
[05:40]DOTA2荣耀之路6:Wings最后进攻
2018/05/30 DOTA
[04:54]DOTA2-DPC中国联赛1月31日Recap集锦
2021/03/11 DOTA
python中类的一些方法分析
2014/09/25 Python
Python爬取附近餐馆信息代码示例
2017/12/09 Python
Python3 requests文件下载 期间显示文件信息和下载进度代码实例
2019/08/16 Python
python 定义类时,实现内部方法的互相调用
2019/12/25 Python
python tkinter 设置窗口大小不可缩放实例
2020/03/04 Python
Django websocket原理及功能实现代码
2020/11/14 Python
Django中ORM的基本使用教程
2020/12/22 Python
cf战队收人广告词
2014/03/14 职场文书
安全责任协议书
2014/04/21 职场文书
美国留学经济担保书
2014/05/20 职场文书
体育口号大全
2014/06/18 职场文书
学习党的群众路线对照检查材料
2014/09/29 职场文书
2014年林业工作总结
2014/12/05 职场文书
2016年先进班集体事迹材料
2016/02/26 职场文书
诉讼和解协议书
2016/03/23 职场文书
六年级情感作文之500字
2019/10/23 职场文书
python实现简单的名片管理系统
2021/04/26 Python
python实现语音常用度量方法的代码详解
2021/05/25 Python
OpenCV-Python实现轮廓的特征值
2021/06/09 Python
我家女友可不止可爱呢 公开OP主题曲无字幕动画MV
2022/04/11 日漫