I am trying to figure out how to create a random float with custom odds.
The game i am trying to replicate is Crash. So the minimum number would be 1, and the max could be for example 1000.
I have the formula from this site https://bitcointalk.org/index.php?topic=5265896.0
CRASH MULTIPLIER = [(E*100 - H)/(E-H)]/100
Also there is some .js code here from getting the number https://roobet.com/fair but it has hashes and stuff (i dont have them, and i dont need them for this project)
And found this thread too: Math behind generating random number (Crash game BTC Casino)
Anyone know how to do this in C#?
Also should i be using System.Random in this? is it actually "random"?
I know how to set the odds, it would go something like this:
Random random = new Random();
double Number = random.NextDouble() * (100 - 1) + 1;
if (Number == 50) //would give me 1% odds
{
CrashRandomNumber = 1; // = means that the Crash game would crash instantly upon starting
}
In C# try implementing it using this algorithm. It worked for me, hope it does for you
using System;
public class myClass
{
public static void Main(string[] args)
{
Console.Write("Please enter a value for E :" );
double E = Convert.ToDouble(Console.Read());
Random rnd = new Random();
double H = rnd.Next(1, Convert.ToInt32(E+1));
double crash = (E*100 - H)/(100*(E-H));
Console.WriteLine($" The value of crash is : {crash}");
}
}
Related
I want a rare object in my game to spawn 1 out of 100 times. This is my code:
int random = Random.Range(0, 99);
if (random < 1)
{
//rare gameobject spawns
}
else
{
//common gameobject spawns
}
This makes sense to me but it doesn´t seem to work correctly. I have seen this rare gameobject about 1 in 20-30 times. Why does it happen so often?
The problem with that is that making things really random is quite a diffucult task for a computer. There is lot of literature on generating random and pseudo-random values and I'm not an expert in this subject, but the basic idea consists of taking an occurring and continually changing value on your system (e.g. the time) and modify it in order to receive a "random" value.
When you won't receive values that fit your purpose (in your case, the event occurs too often), try to use another (equals more complex) algorithm.
Edit: Test your function isolated by surrounding it with some kind of test function like this:
using UnityEngine;
public class RandomTest : MonoBehaviour
{
private const int TestRuns = 1000000;
private const int Probability = 1;
// Use this for initialization
void Start ()
{
int hits = 0;
for (int i = 0; i < TestRuns; i++)
{
int randomValue = Random.Range(0, 100);
if (randomValue < Probability)
{
hits++;
}
}
float probability = (float) hits / TestRuns * 100;
Debug.Log("Outcome: " + probability.ToString("f4") + " %");
}
}
For me, the values are quite close to what is expected and should (didn't calculate it) lay within the standard distribution:
Outcome: 0.9984 %
I would like to know if this simulator works as it should because I don't think these are logical answers, but can't capture mistake either.
I have written a simulator for the following game(Given a deck of cards and 1 point) to find most optimal strategy(what is dealers highest card to continue game)
1. Dealer picks a card and shows it to you(Dealer can't pick Joker)
2. You decide whether to play or no
3.1. If you don't play you get current points and finish game
3.2. If you play you pick a Card
3.2.1. If your card is higher you get double points and go back to step 1
3.2.2. If your and dealer's cards are equal you go back to step 1
3.2.3. If dealer's card is higher you lose all points and finish
The simulation shows win coefficient for choosing each MAX card to play.It shows these numbers which is highly doubtful to me.I expected it to grow to 1.5 till 7 and then go back to 1.
(First-Win/number of simulations,Second-Max card dealer can get for you to continue game)
1 -1
1.0853817 0
1.1872532 1
1.3126581 2
1.4672619 3
1.6704736 4
1.9485809 5
2.2674231 6
2.9993735 7
3.5692085 8
4.3581477 9
4.0109722 10
2.3629856 11
0 12
Here's C# code:
using System;
namespace Codeforces
{
class Program
{
static int[] k = new int[54];
static Random rand = new Random();
static long Doubling(int i, long f)
{
int d = rand.Next(52);
if (k[d] > i) return f;
int ch = d;
while (ch == d) ch = rand.Next(54);
if (k[d] > k[ch]) return 0;
if (k[d] == k[ch]) return Doubling(i, f);
return Doubling(i, f * 2);
}
static void Main(string[] args)
{
for (int i = 0; i < 54; i++) k[i] = i / 4;
for (int i = -1; i < 13; i++)
{
long sum = 0;
for (int j = 0; j < 1e7; j++)
{
sum += Doubling(i, 1);
}
Console.WriteLine(sum / 1.0e7 + " " + i);
}
}
}
}
I'm not a C# programmer, but it looks like your basic approach is mostly correct. I would recommend using a loop rather than recursion.
Your problem description is vague regarding the value of jokers and whether dealer discards jokers when drawn or magically just doesn't draw them—you seem to have gone for the latter if I'm reading your code correctly.
It also appears that the way you implemented the recursion implicitly replaces cards in the deck after each play of the game rather than playing through the deck.
When I implemented this independently in another language, I got comparable results. Looks to me like your intuition is wrong.
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
// Create a string array that consists of ten lines.
string[] personalNumbers; // declare personalNumbers as a 10-element array
personalNumbers = new string[10]; //= { "First number", "Second number", "Third line", etc}
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
Random random = new Random();
int randomNumber = random.Next(1, 50);
string RandomNumberText = Convert.ToString(randomNumber);
personalNumbers[i] = RandomNumberText;
}
Hi, I know that this SEEMS to be a duplicate of previously asked questions, but I am trying to
generate a series of random numbers between 1 and 50 to populate an array
The problem is, if I do it as we were taught in class, each number is the same
I know that the problem is that the tight loop causes the random to be seeded with the same number
What NONE of the other threads addresses however, is HOW to fix this problem when using a loop iteration....
All of the explanations thus far are so far advanced beyond our level that I (and the other askers BTW) have no clue how to implement them as a solution, which I also cannot submit in class as they are techniques that we have not covered
The tutorials at Microsoft insist that putting the random inside the loop is the right solution
I've tried putting an instance of random outside the loop and then calling it from inside the loop but this has caused an exception
Is there a straightforward way to use random to create a series of random numbers that doesn't run into this problem?
Create the random instance outside of the loop:
Random random = new Random();
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
MSDN:
The random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated. One
way to produce different sequences is to make the seed value
time-dependent, thereby producing a different series with each new
instance of Random. By default, the parameterless constructor of the
Random class uses the system clock to generate its seed value, while
its parameterized constructor can take an Int32 value based on the
number of ticks in the current time. However, because the clock has
finite resolution, using the parameterless constructor to create
different Random objects in close succession creates random number
generators that produce identical sequences of random numbers.
You have to define the Random object outside the loop and just get a number each time inside the loop. If you create it each time again, it will be created with the same initial value because the interval between creations is too small.
Random random = new Random();
for (int i = 0; i < 9; i++) {
int randomNumber = random.Next(1, 50);
}
I've tried putting an instance of random outside the loop and then
calling it from inside the loop but this has caused an exception
Here are two concrete examples, one for a Console app, and the other for a WinForms app.
This is one way to declare it in a Console app. random can be used from anywhere within the application, even in methods other than Main():
class Program
{
private static Random random = new Random();
static void Main(string[] args)
{
// ... code ...
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
int randomNumber = random.Next(1, 50);
personalNumbers[i] = randomNumber.ToString();
}
// ... code ...
}
}
This is one way to declare it for use in a WinForms app. random in this example can be used anywhere within Form1:
public partial class Form1 : Form
{
private Random random = new Random();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// ... code ...
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
int randomNumber = random.Next(1, 50);
personalNumbers[i] = randomNumber.ToString();
}
// ... code ...
}
}
This should cover most simple homework assignments. Nothing fancy here.
thank you for the input, it is much appreciated!
I have posted the complete code thus far, which is now giving me what seems like "random" numbers
in that they are always different when I run it
#Steve thank you...I have looked at those questions, but all of the solutions involve using some other technique than random() which I am not allowed to use
#Oerkelens thank you, when I moved the code for random() outside the loop, I got two possible results
one was a series of 9, 9-digit random numbers, or an exception that says
Error 1 A local variable named 'randomNumber' cannot be declared in this scope because
it would give a different meaning to'randomNumber', which is already used in a 'parent or current' scope to denote something else
I have posted the larger bit of code to show what I have changed to get it to work...I don't really understand how to properly call the random() from within the loop, but for some reason, having the same line both inside and outside of the loop did the trick
#Preston - we don't have a textbook for this course, and we are only allowed to use techniques that are contained within the Microsoft C# video tutorials by Bob Tabor (learnvisualstudiodotnet) and Envato (learn C# in 30 days)
I apologize if this all seems obvious to you, but we are in the position of being told that half-way through the course that we are switching from learning to program in Visual Basic to C#, so all of our work now needs to be re-written in C#, without any particular instruction in how to how to use this language...needless to say, it is a huge stress and we are being left without any resources to do this, so much of what we are doing is guesswork
the more complete code that is "working"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace GuessingGameProgram
{
class Program
{
int randNum;
static void Main(string[] args)
{
// Create a string array that consists of ten lines.
string[] personalNumbers; // declare personalNumbers as a 10-element array
personalNumbers = new string[10]; //= { "First number", "Second number", "Third line", etc}
Random outsideLoopRandom = new Random();
int randomNumber = outsideLoopRandom.Next(1, 50);
for (int i = 0; i < 9; i++) // populate the array with 10 random values
{
randomNumber = outsideLoopRandom.Next(1, 50);
string RandomNumberText = Convert.ToString(randomNumber);
personalNumbers[i] = RandomNumberText;
}
// WriteAllLines creates a file, writes a collection of strings to the file,
// and then closes the file.
//System.IO.File.WriteAllLines(#"C:\Users\Public\TestFolder\WriteLines.txt", lines);
foreach (string i in personalNumbers) // this is just a test to see what the output is
{
Console.Write("{0} ", i);
}
Console.ReadLine();
}
}
}
//randNum = Random.Equals(1, 50);
//StreamReader myReader = new StreamReader("personalNumbers.txt");
//string line = "";
//while (line != null)
//{
// line = myReader.ReadLine();
// if (line != null)
// Console.WriteLine(line);
//}
//myReader.Close();
//Console.ReadLine();
//personalNumbers = RandomNumbers.next(1, 10);
//int returnValue = personalNumbers.Next(1, 50);
//int Guess = 0;
//Console.WriteLine("Please guess a number between 1 and 50");
//Console.ReadLine();
////while (Guess = Convert.ToInt32(Console.Read());
//if (Guess < returnValue)
//{
// Console.WriteLine("Wrong! the number that I am thinking of is higher than " + Guess + ". Try again!");
// Console.ReadLine();
//}
//if (Guess > returnValue)
//{
// Console.WriteLine("Wrong! The number that I am thinking of is lower than " + Guess + ". Try again!");
// Console.ReadLine();
//}
// else if (Guess = returnValue)
// Console.WriteLine("Correct! The number that I was thinking of was " + Guess + ". Congratulations!");
// //{
//Console.WriteLine("Let's play a guessing game!")
//Console.WriteLine("")
//Console.WriteLine("guess a number between 1 and 10")
//Console.WriteLine("")
//randNum = randomGenerator.Next(1, 10)
//While userGuess <> randNum
// {
// userGuess = Console.ReadLine()
// }
// If userGuess > randNum Then
// Console.WriteLine("too high, guess again!")
// {
// If userGuess < randNum Then
// Console.WriteLine("too low, guess again!")
// }
// Else
//End While
//Console.WriteLine("Correct! the secret number is " & randNum)
//Console.ReadLine()
My program needs to:
a. Generate an array of 20 random integers from zero to nine. Search for the first occurrence, if any, of the number 7, and report its position in the array.
b. Repeat the computation of part a 1000 times, and for each position in the array, report the number of times that the first occurrence of a 7 in the array is at that position
However whenever I run the program I get strange results (different every time) such as:
No sevens found at any position
1000 sevens found at one position and no sevens found anywhere else
Hundreds of sevens found in 2 positions, and none found anywhere else.
Does anyone have an idea what is wrong with my program?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Week_6_Project_2
{
class Program
{
static int intArrayLength = 20;
static int[] resultsArray = new int[intArrayLength];
public static Array generateRandomArray() {
int[] randomNumberArray = new int[intArrayLength];
Random random = new Random();
int popcounter = 0;
while (popcounter < intArrayLength) {
randomNumberArray[popcounter] = random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void searchForSevens()
{
int counter = 0;
int[] randomArray = (int[])generateRandomArray();
while (counter < intArrayLength)
{
if (randomArray[counter] == 7)
{
resultsArray[counter] += 1;
counter = intArrayLength;
}
counter += 1;
}
}
static void Main()
{
int searchCounter = 0;
while (searchCounter < 1000)
{
searchForSevens();
searchCounter += 1;
}
int displayCounter = 0;
while (displayCounter < intArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, resultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Your main problem is that each searchForSevens() test only takes a small fraction of time and the Random class uses auto-seeding from the clock. The clock however has a limited resolution. The result is that many (sometimes all) of your random sequences will be the same. And at most you will have 2 or 3 different result sets.
The simple fix for this single-threaded program is to use 1 static instance of Random.
You're instantiating a new instance of Random every time you call the generateRandomArray method. Since the random number generator uses the current time as a seed, instantiating two Random instances at the same time results in the same numbers being generated, which explains your unexpected results.
To solve your problem, you should only instantiate one Random instance, store it in private field, and reuse it every time you call the Next method.
The problem I assume stems from the fact, that Random() uses current time as seed. And the computation happens so fast, that each time new Random() is called, it uses same time. So you get same sequence of numbers.
To fix this, you simply need to set seed by yourself, incremmenting it every cycle should be enough.
long base = DateTime.Now.TotalMilliseconds;
Random rand = new Random(base+searchCounter);
.. something like that.
I will not answer but will try to give an analogy for the people that think that they need more then one Random instance...
Suppose that you need to fill 6 sheets of paper with random numbers from 1-6. Ask yourself this: do you need 6 dices or one to do the job? If you answer that you need more than one dice, ask yourself this: how different or more random is throwing different dice instead of same dice every time?
I mean, if you throw ONE on a dice, next throw of a dice won't have any less chance to be ONE again than it would be any other number. It goes against intuition, but it is mathematically and statistically so.
In your original code, you're calling the Random method in rapid succession [broken example based on OP's original code], thus seeding the method with the same number, resulting in duplicate "random" numbers. Creating a static member will ensure randomness simply because you're only creating a single instance of it.
Try creating a single static instance of random like this. [static member example].
static readonly Random Random = new Random();
Based on this, here's how I would solve your particular problem.
using System;
namespace Week_6_Project_2
{
class Program
{
// ******************************************
// THIS IS A SINGLE INSTANCE OF Random.
// read below as to why I'm seeding the instantiation of Random();
static readonly Random Random = new Random(Guid.NewGuid().GetHashCode());
// ******************************************
private const int IntArrayLength = 20;
static readonly int[] ResultsArray = new int[IntArrayLength];
public static Array GenerateRandomArray()
{
var randomNumberArray = new int[IntArrayLength];
var popcounter = 0;
while (popcounter < IntArrayLength)
{
randomNumberArray[popcounter] = Random.Next(0, 10);
popcounter += 1;
}
return randomNumberArray;
}
public static void SearchForSevens()
{
var counter = 0;
var randomArray = (int[])GenerateRandomArray();
while (counter < IntArrayLength)
{
if (randomArray[counter] == 7)
{
ResultsArray[counter] += 1;
counter = IntArrayLength;
}
counter += 1;
}
}
static void Main()
{
var searchCounter = 0;
while (searchCounter < 1000)
{
SearchForSevens();
searchCounter += 1;
}
var displayCounter = 0;
while (displayCounter < IntArrayLength)
{
Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, ResultsArray[displayCounter]);
displayCounter += 1;
}
Console.ReadLine();
}
}
}
Further reading about Random()
Beyond the answer above, sometimes it is necessary to seed Random(int); (I like to use the HashCode of a Guid) to ensure further randomness. This is because the default seed uses the clock which from the docs [microsoft] has a finite resolution. If your class is instantiated multiple times in quick succession (< 16ms), you will get the same seed from the clock... this breaks stuff.
[example of seeded Random(int) run in rapid succession with random results]
"using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers."
hear me when I say that you should NOT instantiate a new Random on every iteration of a loop -- use a static member
Another valid reason to implement your own seed is when you want to recreate a random sequence [example of two identical lists based on same seed]. Re-using the same seed will recreate the sequence since the sequence is based on the seed.
note: others might say that seeding it is not necessary [link], but I personally believe that for the additional few keystrokes and the microscopic hit on the clock, you might as well increase the probability of a unique seed. It doesn't hurt anything, and in some situations it can help.
I know that the C# Random class does not make "true random" numbers, but I'm coming up with an issue with this code:
public void autoAttack(enemy theEnemy)
{
//Gets the random number
float damage = randomNumber((int)(strength * 1.5), (int)(strength * 2.5));
//Reduces the damage by the enemy's armor
damage *= (100 / (100 + theEnemy.armor));
//Tells the user how much damage they did
Console.WriteLine("You attack the enemy for {0} damage", (int)damage);
//Deals the actual damage
theEnemy.health -= (int)damage;
//Tells the user how much health the enemy has left
Console.WriteLine("The enemy has {0} health left", theEnemy.health);
}
I then call the function here (I called it 5 times for the sake of checking if the numbers were random):
if (thePlayer.input == "fight")
{
Console.WriteLine("you want to fight");
thePlayer.autoAttack(enemy1);
thePlayer.autoAttack(enemy1);
thePlayer.autoAttack(enemy1);
}
However, when I check the output, I get the exact same number for each 3 function calls. However, each time I run the program, I get a different number (which repeats 3 times) like this:
You attack the enemy for 30 damage.
The enemy has 70 health left.
You attack the enemy for 30 damage.
The enemy has 40 health left.
You attack the enemy for 30 damage.
The enemy has 10 health left.
I will then rebuild/debug/run the program again, and get a different number instead of 30, but it will repeat all 3 times.
My question is: how can I make sure to get a different random number each time I call this function? I am just getting the same "random" number over and over again.
Here is the random class call that I used:
private int randomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
My guess is that randomNumber creates a new instance of Random each time... which in turn creates a new pseudo-random number generator based on the current time... which doesn't change as often as you might think.
Don't do that. Use the same instance of Random repeatedly... but don't "fix" it by creating a static Random variable. That won't work well either in the long term, as Random isn't thread-safe. It will all look fine in testing, then you'll mysteriously get all zeroes back after you happen to get unlucky with concurrency :(
Fortunately it's not too hard to get something working using thread-locals, particularly if you're on .NET 4. You end up with a new instance of Random per thread.
I've written an article on this very topic which you may find useful, including this code:
using System;
using System.Threading;
public static class RandomProvider
{
private static int seed = Environment.TickCount;
private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>
(() => new Random(Interlocked.Increment(ref seed)));
public static Random GetThreadRandom()
{
return randomWrapper.Value;
}
}
If you change your new Random() call to RandomProvider.GetThreadRandom() that will probably do everything you need (again, assuming .NET 4). That doesn't address testability, but one step at a time...
You didn't show us the code for randomNumber. If it looks anything like
private int randomNumber(int m, int n) {
Random rg = new Random();
int y = rg.Next();
int z = // some calculations using m and n
return z;
}
Well, then there is your issue. If you keep creating new instances of Random, it's possible that they will sometimes have the same seed (the default seed is the system clock which has limited precision; create them quickly enough and they get the same seed) and then the sequence produced by this generator will always be the same.
To fix this, you have to instantiate an instance of Random once:
private readonly Random rg = new Random();
private int randomNumber(int m, int n) {
int y = this.rg.Next();
int z = // some calculations using m and n
return z;
}
And to clear up another point, even if you do this, the output from Random is still not "true" random. It's only psuedorandom.
What is randomNumber?
Typically a pseudo-random number generator is seeded (with a time-related thing, or something random like a time between two keypresses or network packets or something).
You don't indicate what generator you are using, nor how it is seeded.
Instantiate the object random outside the method.
( Random random = new Random(); should be written before the method)
It is also vital that you understand that random isn't really random.
if you generate random numbers in loop it will probably wont be random. because random numbers are basically created internally on current system time.
So place this code in the loop:
Thread.Sleep(10);
So the system will go to sleep for 10 m sec. And you will get new fresh random number.
Its a guaranteed solution. But this will also effect to performance of the system.