注册会员 登录
Project1 返回首页

QQEat https://rpg.blue/?326184 [收藏] [复制] [分享] [RSS] 这个人很懒,什么也没留下。

日志

【RM】rand 方法扩展

已有 230 次阅读2020-3-29 18:13

#encoding:utf-8
#==============================================================================
# ■ Kernel 扩展 By_QQEat
#
#   说明:rand 方法扩展
#
#
#   rand(a..b) # 返回一个 a~b 的随机数
#   rand(a...b) # 返回一个 a~b 的随机数(不包括b本身)
#
#   rand(7..9, 10, 3.5, -50..30, 3.0..5.0)
#     # 非 Range 参数自动转换为 value..value
#     # 整数权重为1000, 比如rand(1..3, 1.5..1.6), 有 3000/3100 的概率随机到1~3, 100/3100 的概率随机到1.5~1.6
#
#   以上参数 Range 范围对象均支持小数、且数字大小不分前后, 例:1..8、10.0..-1 都是可以的。
#
#   rand_average(array, max=nil) # 权重随机(权重数组, 权重上限(不填默认为权重总值为上限))
#     # rand_average([5, 30, 4]) # 5/39 的概率返回0, 30/39 的概率返回1, 4/39 的概率返回2
#     # rand_average([5, 30, 4], 100) # 5/100 的概率返回0, 30/100 的概率返回1, 4/100 的概率返回2
#
#==============================================================================

module Kernel
  #--------------------------------------------------------------------------
  # ● 随机数方法
  #--------------------------------------------------------------------------
  alias :qqeat_rand :rand
  def rand(*args)
    accuracy = 1000 # 小数精度
    case args.length
    when 0
      return qqeat_rand(*args)
    when 1
      v = args[0]
      if v.is_a?(Range)
        a, b = v.first, v.last
        a, b = b, a if a > b
        if f = a.is_a?(Float) || b.is_a?(Float) # 小数
          a, b = a*accuracy, b*accuracy
        end
        return (a+qqeat_rand(b-a+(v.exclude_end? ? 0 : 1))) / (f ? accuracy.to_f : 1)
      else
        return qqeat_rand(*args)
      end
    else
      # 参数处理
      args.map! do |v|
        if v.is_a?(Range)
          a, b = v.first, v.last
          a, b = b, a if a > b # Range 两个数前后自动排列
          v.exclude_end? ? a...b : a..b
        else
          v..v # 非 Range 数值
        end
      end
      
      # 取小数
      f = false; float = args.map{|v| v.first.is_a?(Float) || v.last.is_a?(Float) ? f = true : false }

      # 取 Range 元素的差
      arr = args.map.with_index do |v, i|
        a, b = v.first, v.last
        c = (a == b ? 1 : b - a)
        c + (v.exclude_end? ? 0 : (i == 0 || c == c.to_i ? 1 : 0))
      end
      
      # 处理随机
      r = rand(accuracy...(arr.inject(&:+)*accuracy))
      arr.each_with_index do |v, i|
        temp = v*accuracy
        if r > temp
          r -= temp
        else
          re = args[i]
          if re.first == re.last and !re.exclude_end?
            t = args[i].first
          else
            t = args[i].first + (r - (i == 0 ? accuracy : 0)) / accuracy.to_f
          end
          if float[i]
            t = (t * 1000).to_i / 1000.0
          else
            t = f ? t.to_i.to_f : t.to_i
          end
          return t
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 均分随机(权重数组, 最大值)
  #--------------------------------------------------------------------------
  def rand_average(args, max=nil)
    arr = [0]; args.inject(0){|a, b| arr << a+b; arr[-1] }
    max ||= arr[-1]
    r = rand(max)
    arr.each_cons(2).each_with_index do |v, i|
      return i if r >= v[0] and r < v[1]
    end
  end
end

鸡蛋

鲜花

评论 (0 个评论)

facelist doodle 涂鸦笔

您需要登录后才可以评论 登录 | 注册会员

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-26 10:56

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

返回顶部