C # game of chance

I am new to C #.

What am i trying to do

I am trying to create a random system here.

This is basically the case:

My question is: How do I do what I'm trying to do?

+6
source share
5 answers

There is a tough mistake in your code example: you wrote 150/208 and 190/209 . This is integer division, and both results result in zero . You should have written: 150.0/208 and 190.0/209 to instruct the compiler to separate them as double integers.

Edit:
Assuming the RNG system is flat and that your table looks like this:

 [item] [amount] 0 3 000 000 25 1 500 000 50 2 000 000 75 300 000 100 10 000 150 10 000 (no typo) sum = 6820000 

Then your randomizer might look like this:

 int randomItemNumber = Random.Next(6820000); // 0..6819999 if(randomItemNumber < 3000000) Console.WriteLine("Aah, you've won the Item type #0\n"); else if(randomItemNumber < 3000000+1500000) Console.WriteLine("Aah, you've won the Item type #1\n"); else if(randomItemNumber < 3000000+1500000+2000000) Console.WriteLine("Aah, you've won the Item type #2\n"); else if(randomItemNumber < 3000000+1500000+2000000+300000) Console.WriteLine("Aah, you've won the Item type #3\n"); else if(randomItemNumber < 3000000+1500000+2000000+300000+10000) Console.WriteLine("Aah, you've won the Item type #4\n"); else if(randomItemNumber < 3000000+1500000+2000000+300000+10000+10000) Console.WriteLine("Aah, you've won the Item type #5\n"); else Console.WriteLine("Oops, somehow you won nothing, the code is broken!\n"); 

The idea is that you put all the items in the looong line one by one, but you keep them in your groups. So, at launch, there are three million of the first grade, then the millionth half of the second type, and so on. In total there are 6820000 items in the line. Now you randomly select a number from 1 to 6820000 (or from 0 to 6819999) and use it as the item NUMBER in LINE.

Since the elements are present in the line with their correct statistical distribution, then if the randomization 1-6820000 was FLAT, then the final "lottery" will have the distribution exactly as you wanted.

The only trick to explain is how to guess which item was selected. This is why we saved items in groups. The first part of 3,000,000 elements is the first type, so if the number was less than 3,000,000, we fell into the first type. If more than that, but below the next 1,500,000 (below 4,500,000), then the second type appears .. etc.

+5
source

As others have said, your code has a whole division error.

In any case, you need to look: Inverse transformation.

Basically, this allows you to take a uniform random number (which gives most PRNGs) and convert it to a random sample from any distribution. To do this, you need to use the target distribution CDF.

Links and useful pages:

[ Record CiteHistory ]

Edited: I actually meant the categorical distribution, not the polynomial distribution. These two distributions are often combined (especially in my area), but the difference is important. Two distributions are equivalent only when the multinomial distribution is parameterized with n = 1 (i.e., one test).

+1
source

I did something similar in my application and will convert it to your problem below: In the pseudocode:

  • Pick all the values โ€‹โ€‹(to get the total)
  • Get a random value between 0 and the sum
  • Scroll through all the elements, summing all the values โ€‹โ€‹up to that element
  • When a random number is reached, this element is a value belonging to this value.

The elements of the class are as follows (some non-essential lines are removed and comments with // are added

 public class Items : List<Item> { public Items() { Add(new Item( 0, 3000000)); Add(new Item(25, 1500000)); Add(new Item(50, 2000000)); // etc } /// <summary> /// Returns a random item based on value. /// </summary> /// <returns></returns> public Item GetRandomItem() { var sum = this.Sum(item => item.Value); var randomValue = new Random().Next(sum); // Iterate through itemsuntil found. var found = false; var itemIndex = 0; var visitedValue = 0; while (!found) { var item = this[itemIndex]; if ((visitedValue + item.Value ) > randomValue) { found = true; } else { itemIndex++; visitedValue += item.value; } } return this[itemIndex]; } 

The Item class is nothing more than a placeholder for the name and value.

It looks long, but it has some advantages:

  • When changing the value, the amount is calculated automatically.
  • When adding an item, only one line needs to be changed.
0
source

One divider must be double to avoid zeros from division. To calculate the probability you need to collect up to 100% (or 1):

 // Element - Probability - Cumulative Probability // Item100 10000 / 6820000 0.001466275659824 // Item75 300000 / 6820000 0.0439882697947214 + 0.001466275659824 // Item50 2000000 / 6820000 0.2932551319648094 + 0.0454545454545454 // Item25 1500000 / 6820000 0.219941348973607 + 0.3387096774193548 const double Item100 = 0.001466275659824; const double Item75 = 0.0454545454545454; const double Item50 = 0.3387096774193548; const double Item25 = 0.5586510263929618; int getRandomItem(Random rnd) { double value = rnd.NextDouble(); if (value <= Item100) { // use one of both possible items (100 or 150) int which = rnd.Next(0, 2); return which == 0 ? 100 : 150; } else if (value <= Item75) return 75; else if (value <= Item50) return 50; else if (value <= Item25) return 25; else return 0; } 

How do you use it:

 var rnd = new Random(); var items = new List<int>(); for (int i = 0; i < 100; i++) items.Add(getRandomItem(rnd)); Console.Write(string.Join(Environment.NewLine, items)); 

Please note that I am reusing a random instance. If I created it in a loop, "the random value would always be the same, since it would be sown at the same time."

0
source

Something like this should do. This may not be the best example in the world, but that should be enough:

 class Item { public string Name { get ; private set ; } public int Amount { get ; private set ; } public Item( string name , int amount ) { if ( string.IsNullOrWhiteSpace(name) ) throw new ArgumentException("name") ; if ( amount < 0 ) throw new ArgumentException("amount") ; this.Name = name ; this.Amount = amount ; return ; } } static void Main( string[] args ) { Random rng = new Random() ; Item[] items = { new Item( "item--0" , 3000000 ) , new Item( "item-25" , 1500000 ) , new Item( "item-50" , 2000000 ) , new Item( "item-75" , 300000 ) , new Item( "item-100" , 10000 ) , new Item( "item-150" , 10000 ) , } ; int total = items.Sum( x => x.Amount ) ; for ( int i = 0 ; i < 100 ; ++i ) { int r = rng.Next(0, total ) ; // get a random integer x such that 0 <= x < total int n = 0 ; Item selected = null ; int lo = 0 ; int hi = 0 ; for ( int j = 0 ; j < items.Length ; ++j ) { lo = n ; hi = n + items[j].Amount ; n = hi ; if ( r < n ) { selected = items[j] ; break ; } } Console.WriteLine( "iteration {0}. r is {1} <= {2} < {3}. Selected item is {4}" , i , lo , r , hi , selected.Name ) ; } return; } 
0
source

Source: https://habr.com/ru/post/922784/


All Articles