计算战利品的概率 Table

Calculate probability from a Loot Table

我最近用 C# 设计了一个战利品 table,效果非常好。不过,我想添加最后一件事,这是一种计算可以从 table 中挑选项目的概率百分比的方法。我已经知道百分比概率应该是多少,因为我已经将所有数据输入到在线交互式图表中,我只是不知道如何手动计算它。这是我的战利品表 class:

using System;
using System.Collections.Generic;
using System.Linq;

namespace NovaEngineFramework.Framework.Probability
{
    public class LootTable
    {
        private readonly List<string> _lootTable;
        private readonly Dictionary<string , uint> _cachedLoot;
        private readonly Random _rngInstance;
        private bool _isRebuildRequired;

        public LootTable()
        {
            _rngInstance = new Random();
            _cachedLoot = new Dictionary<string , uint>();
            _lootTable = new List<string>();
        }

        public LootTable( Random random )
        {
            this._rngInstance = random;
            _cachedLoot = new Dictionary<string , uint>();
            _lootTable = new List<string>();
        }

        public void AddLoot( uint probability , string name )
        {
            if( !_cachedLoot.ContainsKey( name ) )
            {
                this._cachedLoot.Add( name , probability );
                _isRebuildRequired = true;
            }
            else
            {
                throw new Exception( "Item: " + name + " Already Exists!" );
            }

        }

        public void DeleteLoot( string name )
        {
            if( _cachedLoot.ContainsKey( name ) )
            {
                this._cachedLoot.Remove( name );
                _isRebuildRequired = true;
            }
            else
            {
                throw new Exception( "Item: " + name + " Did not exist!" );
            }
        }

        public double CalculateProbability(string name)
        {
            if( _cachedLoot.ContainsKey( name ) )
            {
                return 0; // Calculate the actual percent probability here
            }
            throw new Exception( "Item: " + name + " Does not exist." );
        }

        public uint CheckRarity( string name )
        {
            if( _cachedLoot.ContainsKey( name ) )
            {
                return _cachedLoot[ name ];
            }
            throw new Exception( "Item: " + name + " Does not exist." );
        }

        public List<string> CheckLoot()
        {
            return this._cachedLoot.Keys.ToList();
        }

        public void EditLoot( string name , uint newProbability )
        {
            if( _cachedLoot.ContainsKey( name ) )
            {
                this._cachedLoot[ name ] = newProbability;
                _isRebuildRequired = true;
            }
            else
            {
                throw new Exception( "Item: " + name + " Does not exist." );
            }
        }

        public void ClearAllLoot()
        {
            this._cachedLoot.Clear();
            this._isRebuildRequired = true;
        }

        private void Build()
        {
            _lootTable.Clear();
            foreach( KeyValuePair<string , uint> pair in _cachedLoot )
            {
                for( int i = 0; i < pair.Value; i++ )
                {
                    _lootTable.Add( pair.Key );
                }
            }
            _isRebuildRequired = false;
        }

        public string NextRandomItem()
        {
            if( !_isRebuildRequired )
            {
                return _lootTable[ _rngInstance.Next( _lootTable.Count ) ];
            }
            this.Build(); // A rebuild is needed, let's go ahead and take care of it!
            return _lootTable[ _rngInstance.Next( _lootTable.Count ) ];
        }
    }
}

这是我的测试实现:

        LootTable swordTable = new LootTable();
        swordTable.AddLoot( 1 , "Sword_Legendary_SwordOfIllimitableDemise" );
        swordTable.AddLoot( 200 , "Sword_Common_SteelGreatSword" );
        swordTable.AddLoot( 50 , "Sword_Rare_MagicImbuedLongBlade" );
        swordTable.AddLoot( 15 , "Sword_Epic_Hopesfire" );
        swordTable.AddLoot( 400 , "Sword_Trash_RustySword" );
        Console.WriteLine(swordTable.NextRandomItem());

还有一张有助于更好理解的图片:

这是交互式图表 link,如果将鼠标悬停在该图表上,则会显示实际的基于百分比的概率。 Interactive Chart

我正在寻找的输出的视觉示例:

像在线图表那样计算战利品概率 table 的正确方法是什么?

上次编辑 对于那些想要包含答案的最终产品的人,这里是 class:

的 pastebin link

LootTable.cs

_cachedLoot 中的项目总数相加,然后将相关项目的数量除以总数。

double total = _cachedLoot.Values.Sum(n => (int)n);
return _cachedLoot[name] / total;

(注意转换为 double - 这是防止 integer division 所必需的。)


如果想return一个适合打印的值,可以稍微修改上面的:

double total = _cachedLoot.Values.Sum(n => (int)n);
double percent = _cachedLoot[name] / total;
return Math.Round(percent * 100, 2);