4

5つの結果があるとしましょう

Console.WriteLine("1");
Console.WriteLine("2");
Console.WriteLine("3");
Console.WriteLine("4");
Console.WriteLine("5");

ウェイトを使用して上記のアクションの1つをランダムに実行したいので、ウェイトを100から開始するとします。

ランダムに1を出力し、重みを5減らして、重みを95にします。

したがって、これが行われた後、昇順の重みは(95、100、100、100、100)であるため、100個の重みすべてが95を超えてランダムに選択される可能性が5%ありますが、95はランダムに選択される可能性がありますが、そうではありません他の人と同じくらい。

サンプル出力:(コンソール出力)

1 (weight = 95)
3 (weight = 95)
1 (weight = 90)
5 (weight = 95)
1 (weight = 85)
2 (weight = 95)
4

3 に答える 3

2

ネストされたcaseステートメントをいじくり回す理由がわかりません。

新しい乱数を生成する必要があるたびに、重みを合計します。

次に、を使用しますRandom.Next(sumOfWeights)

次に、返された乱数を最初の重み、最初の2つの重みの合計、最初の3つの重みの合計などと、未満になるまで比較します。

それがあなたの選択です。次に、その重量を5減らします。

于 2012-12-23T08:01:34.530 に答える
1

これが簡単なコードです。私がよく理解していれば、必要なものを、出発点として使用できます。

class Program
{
    static void Main(string[] args)
    {
        List<ActionWithChance> list = new List<ActionWithChance>()
                                          {
                                              new ActionWithChance("1", 100),
                                              new ActionWithChance("2", 100),
                                              new ActionWithChance("3", 100),
                                              new ActionWithChance("4", 100),
                                              new ActionWithChance("5", 100)
                                          };

        for (int i = 0; i < 10; i++)
        {
            RandomHandler.CreateIntervals(list);
            RandomHandler.GetRandom(list);
        }


    }
}

static class RandomHandler
{
   public static void CreateIntervals(List<ActionWithChance> list)
    {
        int currentBorderMin = 1;
        int currentBorderMax = 0;
        foreach (var actionWithChance in list)
        {
            actionWithChance.TempMin = currentBorderMin;
            actionWithChance.TempMax = currentBorderMax 
                              + actionWithChance.Chance;

            currentBorderMax = actionWithChance.TempMax;
            currentBorderMin = currentBorderMax;
        }
    }

    public static void GetRandom(List<ActionWithChance> list)
    {
        Thread.Sleep(20);
        int allChance = list.Sum(i => i.Chance);
        Random rand = new Random();
        int nextValue = rand.Next(1, allChance + 1);
        ActionWithChance selectedAction = 
list.FirstOrDefault(i => i.TempMin <= nextValue && i.TempMax >= nextValue);

        selectedAction.Chance = selectedAction.Chance > 5 
            ? selectedAction.Chance - 5 : 100;

        selectedAction.DoSomething();
    }
}

class ActionWithChance
{
    public string Name { get; set; }
    public int Chance { get; set; }
    public int TempMin { get; set; }
    public int TempMax { get; set; }

    public void DoSomething()
    {
        Console.WriteLine(Name);
    }


    public ActionWithChance(string name, int chance)
    {
        Name = name;
        Chance = chance;
    }
}
于 2012-12-23T08:02:04.497 に答える
0

別のアプローチ:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace RandomWeights
{
    public class WeightedItem
    {
        public string Text { get; set; }
        public int Weight { get; set; }

        public WeightedItem(string text, int weight)
        {
            Text = text; 
            Weight = weight;
        }
    }
    public class WeightedOutput
    {
        public static readonly int _decreaseIncrement = 5;
        List<WeightedItem> items = new System.Collections.Generic.List<WeightedItem>();

        public WeightedOutput()
        {
            //initialize the five items with weight = 100
            for (int i = 1; i <= 5; i++)
                items.Add(new WeightedItem(i.ToString(), 100));

            for (int x = 0; x < 50; x++)
                WriteSelected();

            Console.ReadLine();
        }

        public void WriteSelected()
        {
            WeightedItem selectedItem = GetItem();
            if (selectedItem != null)
                Console.WriteLine(selectedItem.Text + ": " + selectedItem.Weight);
            else
                Console.WriteLine("All items have 0 probability of getting selected");
        }

        public WeightedItem GetItem()
        {
            int totalWeight = items.Sum(x=>x.Weight);
            Random rnd = new Random((int)DateTime.Now.Ticks);
            int random = rnd.Next(0, totalWeight);

            WeightedItem selected = null;
            foreach (var item in items)
            {
                if (random < item.Weight && item.Weight > 0)
                {
                    //need a new item and not a reference to get the right weights
                    selected = new WeightedItem(item.Text, item.Weight);
                    //decrease item's weight
                    item.Weight -= _decreaseIncrement;
                    break;
                }

                random -= item.Weight;
            }
            return selected;
        }
    }
}
于 2012-12-23T08:48:53.690 に答える