119 lines
4.0 KiB
Lua
119 lines
4.0 KiB
Lua
|
|
---@class ItemGenerator 物品生成器类
|
|||
|
|
local ItemGenerator = {
|
|||
|
|
item_data = {},
|
|||
|
|
period = 100,
|
|||
|
|
item_distributions = {}
|
|||
|
|
}
|
|||
|
|
ItemGenerator.__index = ItemGenerator
|
|||
|
|
|
|||
|
|
---数组洗牌函数(Fisher-Yates算法)
|
|||
|
|
---@param array any[] 需要打乱顺序的数组
|
|||
|
|
local function ShuffleArray(array)
|
|||
|
|
for i = #array, 2, -1 do -- 从后往前遍历
|
|||
|
|
local j = math.random(i) -- 生成1到i的随机数
|
|||
|
|
array[i], array[j] = array[j], array[i] -- 交换元素位置
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
---创建物品生成器实例
|
|||
|
|
---@param period number 生成周期次数
|
|||
|
|
---@param item_data table<number, number> 物品配置表 {物品ID = 总生成数量}
|
|||
|
|
---@return ItemGenerator 物品生成器实例
|
|||
|
|
local function CreateItemGenerator(period, item_data)
|
|||
|
|
local self = setmetatable({}, ItemGenerator)
|
|||
|
|
---@type number 存储生成周期
|
|||
|
|
self.period = period
|
|||
|
|
---@type table<number, number> 原始配置数据
|
|||
|
|
self.item_data = item_data
|
|||
|
|
---@type number 当前调用次数
|
|||
|
|
self.current_call = 0
|
|||
|
|
---@type table<number, number[]> 物品分布数据结构
|
|||
|
|
self.item_distributions = {}
|
|||
|
|
self:InitializeDistributions()
|
|||
|
|
return self
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
---初始化物品分布数据
|
|||
|
|
function ItemGenerator:InitializeDistributions()
|
|||
|
|
-- 遍历所有物品配置
|
|||
|
|
for item_id, total in pairs(self.item_data) do
|
|||
|
|
-- 计算基础值和余数(保证总数 = 基础值*period + 余数)
|
|||
|
|
local base = math.floor(total / self.period)
|
|||
|
|
local remainder = total % self.period
|
|||
|
|
|
|||
|
|
-- 创建初始分布数组(全部填充基础值)
|
|||
|
|
local distribution = {}
|
|||
|
|
for i = 1, self.period do
|
|||
|
|
distribution[i] = base
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
-- 生成索引数组并洗牌(用于随机分配余数)
|
|||
|
|
local indices = {}
|
|||
|
|
for i = 1, self.period do
|
|||
|
|
indices[i] = i
|
|||
|
|
end
|
|||
|
|
ShuffleArray(indices) -- 打乱索引顺序
|
|||
|
|
|
|||
|
|
-- 将余数随机分配到前remainder个位置
|
|||
|
|
for i = 1, remainder do
|
|||
|
|
distribution[indices[i]] = distribution[indices[i]] + 1
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
-- 存储当前物品的分布数组
|
|||
|
|
self.item_distributions[item_id] = distribution
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
---重置生成器状态(当调用次数超过N时触发)
|
|||
|
|
function ItemGenerator:Reinitialize()
|
|||
|
|
self:InitializeDistributions() -- 重新生成分布数据
|
|||
|
|
self.current_call = 0 -- 重置调用计数器
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
---生成物品列表(每次调用产生一个周期的结果)
|
|||
|
|
---@return number[] 包含物品ID的数组(结果经过随机排序)
|
|||
|
|
function ItemGenerator:Generate()
|
|||
|
|
-- 当超过周期次数时重置状态
|
|||
|
|
if self.current_call >= self.period then
|
|||
|
|
self:Reinitialize()
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local current_step = self.current_call + 1 -- 获取当前步骤(1-based)
|
|||
|
|
local result = {} -- 结果收集器
|
|||
|
|
|
|||
|
|
-- 遍历所有物品的分布数据
|
|||
|
|
for item_id, distribution in pairs(self.item_distributions) do
|
|||
|
|
local count = distribution[current_step] -- 获取当前步骤应生成数量
|
|||
|
|
for _ = 1, count do
|
|||
|
|
table.insert(result, item_id) -- 按数量添加物品ID到结果集
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
ShuffleArray(result) -- 打乱结果顺序保证随机性
|
|||
|
|
self.current_call = self.current_call + 1 -- 增加调用计数器
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
---获取当前未生成的物品剩余数量
|
|||
|
|
---@return table<number, number> 返回物品ID和剩余数量的映射表
|
|||
|
|
function ItemGenerator:GetRemainingItems()
|
|||
|
|
local remaining = {}
|
|||
|
|
local current_step = self.current_call -- 注意这里使用已调用次数(0-based)
|
|||
|
|
|
|||
|
|
-- 遍历所有物品的分布数据
|
|||
|
|
for item_id, distribution in pairs(self.item_distributions) do
|
|||
|
|
local total_remaining = 0
|
|||
|
|
|
|||
|
|
-- 计算从下一个步骤到周期结束的总数量
|
|||
|
|
for step = current_step + 1, self.period do
|
|||
|
|
total_remaining = total_remaining + distribution[step]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
remaining[item_id] = total_remaining
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return remaining
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return CreateItemGenerator
|