从战利品表中计算概率

时间:2015-05-20 23:08:46

标签: c# probability

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

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());

图片有助于更好地理解: enter image description here

以下是交互式图表链接,如果鼠标悬停,则显示实际的基于%的概率。 Interactive Chart

我正在寻求的输出的可视示例: enter image description here

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

上次修改 对于那些想要包含答案的最终产品的人,这里是类的pastebin链接:

LootTable.cs

1 个答案:

答案 0 :(得分:2)

_cachedLoot中添加项目总数,然后将相关项目的金额除以总计。

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

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

如果要返回适合打印的值,可以稍微修改上述内容:

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