---@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 物品配置表 {物品ID = 总生成数量} ---@return ItemGenerator 物品生成器实例 local function CreateItemGenerator(period, item_data) local self = setmetatable({}, ItemGenerator) ---@type number 存储生成周期 self.period = period ---@type table 原始配置数据 self.item_data = item_data ---@type number 当前调用次数 self.current_call = 0 ---@type table 物品分布数据结构 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 返回物品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