Я создал простой класс LootTable для хобби, над которым я работаю, и работает отлично. Тем не менее, я широко осведомлен о недостатке, который присутствует в коде. Когда я говорю об ошибке, я на самом деле имею в виду: область реализации, которая может быть улучшена/упрощена, чтобы облегчить обработку/вычислительные затраты. Я попытаюсь объяснить, как лучше всего, как я могу, и прежде, чем я, вот код для моего LootTable класса:Упрощение распределения вероятности LootTable
using System;
using System.Collections.Generic;
using System.Linq;
using DreamforceFramework.Framework.Game.Logic.Structs;
using DreamforceFramework.Framework.Probability;
namespace DreamforceFramework.Framework.Game.Probability
{
public class LootTable
{
public string Name;
private readonly List<string> _lootTable;
private readonly Dictionary<string, int> _cachedLoot;
private bool _isRebuildRequired;
public LootTable()
{
_cachedLoot = new Dictionary<string, int>();
_lootTable = new List<string>();
}
public LootTable(string name)
{
this.Name = name;
_cachedLoot = new Dictionary<string, int>();
_lootTable = new List<string>();
}
public void Add(string name, int probability)
{
this._cachedLoot.Add(name, probability);
_isRebuildRequired = true;
}
public bool Contains(string name)
{
return _cachedLoot.ContainsKey(name);
}
public void Add(LootTableItem item)
{
this._cachedLoot.Add(item.Name, item.Rarity);
_isRebuildRequired = true;
}
public void Add(List<LootTableItem> items)
{
foreach (LootTableItem lootTableItem in items)
{
this._cachedLoot.Add(lootTableItem.Name, lootTableItem.Rarity);
}
_isRebuildRequired = true;
}
public void Remove(string name)
{
this._cachedLoot.Remove(name);
_isRebuildRequired = true;
}
public double ComputeProbability(string name)
{
double total = _cachedLoot.Values.Sum(n => n);
double percent = _cachedLoot[name]/total;
return Math.Round(percent * 100, 2);
}
public void Edit(string name, int newProbability)
{
this._cachedLoot[name] = newProbability;
_isRebuildRequired = true;
}
public void Clear()
{
this._cachedLoot.Clear();
this._isRebuildRequired = true;
}
private void Rebuild()
{
_lootTable.Clear();
foreach (KeyValuePair<string, int> pair in _cachedLoot)
{
for (int i = 0; i < pair.Value; i++)
{
_lootTable.Add(pair.Key);
}
}
_isRebuildRequired = false;
}
public string Next()
{
if (_isRebuildRequired)
{
this.Rebuild();
}
return _lootTable[DreamforceRandom.NextInteger(_lootTable.Count)];
}
public List<string> Next(int quantity)
{
List<string> returnList = new List<string>();
if (_isRebuildRequired)
{
this.Rebuild();
}
for (int i = 0; i < quantity; i++)
{
returnList.Add(_lootTable[DreamforceRandom.NextInteger(_lootTable.Count)]);
}
return returnList;
}
}
}
А также LootTableItem структура:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DreamforceFramework.Framework.Game.Logic.Structs
{
public struct LootTableItem
{
public string Name;
public int Rarity;
public LootTableItem(string name, int rarity)
{
this.Name = name;
this.Rarity = rarity;
}
}
}
Для тех из вас, которые просматривают вышеприведенный код, вы увидите неэффективную область, о которой я говорю. Чтобы создать внутреннюю таблицу лута, я создаю список строк, равный редкости элемента. Так скажите, что я помещал «Ржавый Меч» в таблицу лута с редкостью 20. Это означает, что когда таблица добычи будет перестроена, она добавит 20 строк «Ржавый Меч» к таблице. Не так ли? Но теперь скажем, что я добавляю два объекта. Я добавляю «Ruby» со значением 100 и «Изумруд» со значением 100 в таблицу добычи. Ну, это значит, что я буду создавать 200 строк в таблице добычи, что ужасно глупо, когда его можно просто упростить до добавления 1 строки Ruby и 1 строки Emerald. Это обеспечило бы такую же вероятность, которая составляет 50/50.
Так что мой вопрос: Как упростить вероятность добавления элементов в LootTable, чтобы он автоматически оптимизировал данные, а не создавал один гигантский список строк.
Надеюсь, я объяснил это достаточно ясно, иногда мне недостает, когда речь заходит о письменной артикуляции.
EDIT:
Вот рабочее решение, предложенное выбранный ответ: http://pastebin.com/4w0B0V6y
Выглядит отлично и хорошо объяснено. – Krythic
Ваш пример кода вызывает у меня много ошибок. Я пробовал реализовать все это сегодня; кажется, что вы, возможно, путаете несколько ваших типов и переменных-членов, например, в предложенном вами новом методе Rebuild(). Сейчас я пытаюсь понять, что вы намеревались. Однако помощь будет оценена. – Krythic
Эх, неважно. Я понял. Обновление оригинального сообщения с помощью решения рабочего класса в случае, если кто-нибудь в следующий раз столкнется с этим потоком. – Krythic