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 |