Flip a coin problem - c#

I have been playing around and wrote this little piece of code. I am trying to flip a coin defined number of times and then count how many tails and heads I am getting. So here it is:
private void Start_Click(object sender, EventArgs e)
{
int headss = 0;
int tailss = 0;
int random2, g;
string i = textBox1.Text;
int input2, input;
bool NumberCheck = int.TryParse(i, out input2);
if (textBox1.Text == String.Empty) // check for empty string, when true
MessageBox.Show("Enter a valid number between 0 and 100000.");
else // check for empty string, when false
if (!NumberCheck) // number check, when false
{
textBox1.Text = String.Empty;
MessageBox.Show("Enter a valid number between 0 and 100000.");
}
else
{
input = Convert.ToInt32(textBox1.Text);
for (g = 0; g < input; g++)
{
Random random = new Random();
random2 = random.Next(2);
if (random2 == 0)
{
headss++;
}
else if (random2 == 1)
{
tailss++;
}
}
}
heads.Text = Convert.ToString(headss);
tails.Text = Convert.ToString(tailss);
}
The problem is that I keep getting problems while displaying the content. It's not even close to display they right result. Any ideas?
EDIT. Solution: move following line 3 lines up :D
Random random = new Random();

Instead of
for (g = 0; g < input; g++)
{
Random random = new Random();
random2 = random.Next(2);
}
Declare a single Random for use throughout:
private Random randomGenerator = new Random();
private void Start_Click(object sender, EventArgs e)
{
// ...
for (g = 0; g < input; g++)
{
random2 = randomGenerator.Next(2);
}
// ...
}

You should use only one Random object to generate good (as good as default Random does) random sequence.

The default constructor for random take the systmem time as seed. Therefore, if you generate lots of them in a short amount of time they will all generate the same sequence of random numbers. Pull the random object out of the loop and this effect will not occur.

With RandomGenerator. This code will count how many times coin has been flipped. It will end with 3 consecutive HEADS.
private RandomGenerator rgen = new RandomGenerator ();
public void run () {
int value = 0;
int total = 0;
while (value != 3) {
String coinFlip = rgen.nextBoolean() ? "HEADS" : "TAILS";
println (coinFlip);
if (coinFlip == "HEADS") {
value+=1;
} else {
value=0;
}
total +=1;
}
println ("It took "+total+" flips to get 3 consecutive heads");
}

Related

cycle never reaching final value

This is my random unique numbers generator I try to create for my cards software. It generates numbers and write into array OK. I have problem with the loop here. when integer i reaches 29, it stops growing and code cycles infinitely and never reaches 30, which would stop the loop.
Without the if statement it works, but it won't fill the range needed.
fixed the code, now works OK, the initial value in array was the problem. now I ged needed 0-29 values
public partial class Form1 : Form
{
int[] rndCards = new int[30];
public Form1()
{
InitializeComponent();
richTextBox1.Text = #"random numbers";
}
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
rndCards = new int[30];
richTextBox1.Clear();
Random rnd = new Random();
while (i < 30)
{
int cardTest = rnd.Next(0, 30);
while (rndCards.Contains(cardTest))
{
cardTest++;
if (cardTest == 31)
{
cardTest = 1;
}
}
rndCards[i] = cardTest;
i++;
}
i = 0;
while (i < 30)
{
rndCards[i] = rndCards[i] -1;
richTextBox1.Text += rndCards[i] + ", ";
i++;
}
}
}
You problem lies in the simple fact that the array already contains the number 0 when you create it (because each item of an array is initialized to the default value for its member's type) That's why you should start your i from 1 and not zero.
int i = 1;
Alternative Simpler Approach:
You can do this as a simple random number generation:
Random rnd = new Random();
rndCards = Enumerable.Range(0, 30).OrderBy(x => rnd.Next()).ToArray();
foreach(var card in rndCards)
{
// do something
}
rnd.Next(0,30) would return a random number from 0-29.
From the documentation for Random.Next(Int32, Int32):
The Next(Int32, Int32) overload returns random integers that range from minValue to maxValue – 1. However, if maxValue equals minValue, the method returns minValue.
Use int cardText = rnd.Next(0, 31);, and this should solve your issue.
The upper bound is exclusive (C# Random.Next - never returns the upper bound?).
int cardTest = rnd.Next(0, 31);

c# Count up +1 when number is 6

i'm pretty new and i was wondering when if i press a butten a random number comes on but when that number is 2 there should be another textbox showing how many times it got 2.
without using if/else or switch
private void btnChoose_Click(object sender, EventArgs e)
{
double number2 = 0;
double When2 = 2;
Random number = new Random();
double chose = number.Next(1,7);
txtnumber.Text = chose.ToString();
txtnumber2.Text = something...
}
Solution: (it's not possible with the number 2 but it is with the number 6)
// global var
int number6 = 0;
private void btnChoose_Click(object sender, EventArgs e)
{
double When6 = 6;
Random number = new Random();
double chose = number.Next(1,7);
txtnumber.Text = chose.ToString();
number6 = Convert.toInt32(number6 + (chose/When6));
txtnumber6.Text = number6.ToString();
}
L.B's note: OP's comment at one of the deleted answer
it's a pretty anoying task and i just need to do this without the if/ese or switch
No array, no dictionary, no Linq, no built-in methods like Convert.ToIn32 etc. Only bit twiddling
Random number = new Random();
int TwosCount = 0;
private void btnChoose_Click(object sender, EventArgs e)
{
int chose = number.Next(1, 7);
TwosCount += ~((chose & 4) >> 2) & ((chose & 2) >> 1) & ~((chose & 1) >> 0);
txtnumber.Text = chose.ToString();
txtnumber2.Text = TwosCount.ToString();
}
PS: You can remove some unnecessary parentheses and write as:
~(chose & 4) >> 2 & (chose & 2) >> 1 & ~(chose & 1);
For a small range of random numbers such as this, (Random.Next(1,7) produces numbers from 1 to 6) you can use an array to keep track of how many times a number has come up. Make sure to declare this array inside of your main class, but outside of your button click method. Also, it doesn't look like you need to use floating point numbers for this job, so I've changed all the double variables to integers.
int[] numberCount = new int[6];
//if you really want to stay with doubles, then simply change the above line to this:
//double[] numberCount = new double[6];
private void btnChoose_Click(object sender, EventArgs e)
{
int number2 = 0;
//double When2 = 2; This line is not needed, so it's been commented out.
Random number = new Random();
int chose = number.Next(1,7);
numberCount[chose - 1]++; // Increment the amount of times we've seen this particular number
txtnumber.Text = chose.ToString();
txtnumber2.Text = numberCount[1].ToString(); // Display the amount of times we've seen the number 2
//Remember, array indexes are 0 based, so index 1 is actually the second number in the array, or number 2.
}
We can use this formula to find our index (Rnd -3)%2
when we subtract 3 from value, if its 2 or lower, it would get negative results as
1-3=-2 and -2%2=0
2-3=-1 and -1%2=-1
and other numbers results would be 0 or 1.
then we can add calculated value by one to start index from 0, now we have an array with three elements which the first element is number of occurrences of 2.
private readonly Random _random=new Random();
private readonly int [] numbers=new int[3];
private void button1_Click(object sender, EventArgs e)
{
var number = _random.Next(1,7);
var chose = number;
chose -= 3; //mod (2-3)=-1
chose %= 2;
chose++;
numbers[chose]++;
txtnumber.Text = number.ToString();
txtNumber2.Text = numbers[0].ToString();
}
Perhaps ;-)
double[] two = { 2 };
int count2 = 0;
private void btnChoose_Click(object sender, EventArgs e)
{
double chose = number.Next(1, 7);
txtnumber.Text = chose.ToString();
count2 = count2 + System.Convert.ToInt32(two.Contains(chose));
txtnumber2.Text = count2.ToString();
}
Random R = new Random();
void RUN()
{
int N = R.Next(2);
Action[] A = new Action[2];
A[0] = new Action(Act1);
A[1] = new Action(Act2);
A[N].Invoke();
}
private void Act2()
{
MessageBox.Show("Cancel");
}
private void Act1()
{
MessageBox.Show("OK");
}
this answer is without if/else/switch

Sort a collection of randomly generated numbers

I am creating a random number generator in c#
I generate the numbers as so
Random RandomClass = new Random();
Num1.text = RandomClass.Next(1,49).ToString();
Num2.text = RandomClass.Next(1,49).ToString();
Num3.text = RandomClass.Next(1,49).ToString();
Num4.text = RandomClass.Next(1,49).ToString();
Num5.text = RandomClass.Next(1,49).ToString();
Num6.text = RandomClass.Next(1,49).ToString();
The user clicks a button and the numbers are generated, what I want is for there to be a button which can sort the numbers, so for example smallest to lowest.
Could I turn the numbers generated into an array and call .ToArray and then sort from there? I am unsure how to group the random numbers together to then call a sorting method on them.
Just add the random numbers to a list and sort them.
Random RandomClass = new Random();
List<int> list = new List<int>();
for (int i = 0; i < 10; i++)
list.Add(RandomClass.Next(1, 49));
list.Sort();
// If you need to reverse it...
list.Reverse();
If you are comparing to a List<string> you will need to write a comparer.
Example:
private static int CompareValues(string x, string y)
{
if (x == null)
return y == null ? 0 : -1;
else
{
if (y == null)
return 1;
else
{
int left = Int32.Parse(x);
int right = Int32.Parse(y);
if (left > right)
return 1;
else if (left < right)
return -1;
else
return 0;
}
}
}
Then to use it, pass it as argument to the Sort() method. This will now be used as a custom compare to handle the integer values and sort them properly.
list.Sort(CompareValues);
If you store the random numbers in a list, you could sort (or manipulate them in a number of ways) easily using Linq. Assuming your method returns random integers:
var myRandomNumbers = new List<int>
{
RandomClass.Next(1,49),
RandomClass.Next(1,49)
};
var mySortedRandomNumbers = myRandomNumbers.OrderByDescending(x => x).ToList();
Of course, if you're always calling RandomClass.Next(1,49) you could optimize with a loop and use .Add() on the list.
Here's a solution that generates random numbers and saves them for later.
//fields
private readonly Random _random = new Random();
private readonly List<int> _randomNumbers = new List<int>();
public void SomeEvent(object sender, EventArgs e)
{
_randomNumbers.Clear();
Num1.text = GetRandom().First().ToString();
Num2.text = GetRandom().First().ToString();
Num3.text = GetRandom().First().ToString();
Num4.text = GetRandom().First().ToString();
Num5.text = GetRandom().First().ToString();
Num6.text = GetRandom().First().ToString();
}
public void SortRandomNumbers(object sender, EventArgs e)
{
var sortedRandoms = _randomNumbers;
sortedRandoms.Sort();
//do stuff with sortedRandoms
}
// Gets a random value and caches it
private IEnumerable<int> GetRandom()
{
while(true)
{
var value = _random.Next(1, 49);
_randomNumbers.Add(value);
yield return _randomNumbers.Last();
}
}
If you always have six fields Num1 - Num6, you could add their content to a List<int>, sort them by using .OrderBy() and fill them up again using the ordered list.
List<int> nums = new List<int>();
nums.Add(Convert.ToInt32(Num1.text));
.
.
nums.Add(Convert.ToInt32(Num6.text));
nums = nums.OrderBy(num => num).ToList(); //or OrderByDescending
Num1.text = nums[0];
.
.
Num6.text = nums[5];
Yes, you could use an Array:
RandomClass.Next(1,49).ToString();
ArrayList numbers = new ArrayList();
for (int i = 0; i < 10; i++)
numbers[i] = RandomClass.Next(1,49).ToString();
numbers.Sort();

Finding average of the numbers user's type into an array

Could someone please explain to me why my average keeps coming as 0 when I run my program? I have listed the entire code of my project on here and have literally never used arrays before. Also, is the name of this array mData? I tried reading in my book to determine what to look for in these items and have come up with nothing.
public partial class frmMain : Form
{
private const int mSize = 20;
private int[] mData = new int[mSize];
private int mIndex = 0;
private static void Main()
{
frmMain main = new frmMain();
Application.Run(main);
}
private frmMain()
{
InitializeComponent();
}
private void btnEnter_Click(object sender, EventArgs e)
{
int num;
num = int.Parse(txtInput.Text);
//store num in the array
mData[mIndex] = num;
mIndex = mIndex + 1;
//check for full array
if (mIndex == mSize)
{
//inform user that array is full
MessageBox.Show("The array is full.");
btnEnter.Enabled = false;
}
}
private void btnExit_Click(object sender, EventArgs e)
{
Close();
}
private void btnDisplay_Click(object sender, EventArgs e)
{
int n;
for (n = 0; n < mIndex; n++)
listBoxOutput.Items.Add(mData[n]);
}
private void btnAverage_Click(object sender, EventArgs e)
{
int sum = 0;
int average = 0;
if (mIndex == 0)
{
//inform user that array is empty
MessageBox.Show("The array is empty.");
}
//add up the values
for (int i = 0; i < mData.Length; i++)
{
sum += mData[i];
}
//divide by the number of values
average = sum / mSize;
listBoxOutput.Items.Add("The average of the array is: " + average);
}
}
One problem is that you are using ints. If the final value is a decimal less than 1, the int average will store 0. Changing average to a float will solve this. Also, you should not divide by mSize unless you know the entire array is filled. The user could insert one value, but it would be averaged with 19 0s.
since average, sum, and mSize are intergers, when you divide them, the result will be truncated.
average = sum / mSize;
so if sum/mSize is less than 1, average will always be equal to 0
to get average to have decimal points change the declaration to
double average = 0;
and the calculation to
average = (double)sum / (double)mSize;
Array has a built in property to calculate average which returns a decimal value as output. Example is below
int[] integer = new int[] { 1, 2, 3 };
Console.WriteLine(integer.Average().ToString());
Hope this helps.

word search puzzle game

I am trying to create a word search game. the problem is I am unable to insert words into a TableLayoutPanel. When I wrote this, I got a compile error that says "no overload for method 'placewords' takes '5' arguments.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Random r = new Random();
for (int a = 0; a < tableLayoutPanel1.ColumnCount; a++)
{
for (int b = 0; b < tableLayoutPanel1.RowCount; b++)
{
Label nl = new Label();
int x = r.Next(65, 90);
char c = (char)x;
nl.Text = c.ToString();
tableLayoutPanel1.Controls.Add(nl, a, b);
}
}
}
private void newGameToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Restart();
}
private void PlaceWords()
{
string[] words = { "byte", "char" };
Random rn = new Random();
foreach (string p in words)
{
String s = p.Trim();
bool placed = false;// continue trying to place the word in // the matrix until it fits
while (placed == false)// generate a new random row and column
{
int nRow = rn.Next(30);// generate a new random x & y direction vector
int nCol = rn.Next(30);// x direction: -1, 0, or 1
int nDirX = 0; // y direction -1, 0, or 1
int nDirY = 0; // (although direction can never be 0, 0, this is null)
while (nDirX == 0 && nDirY == 0)
{
nDirX = rn.Next(3) - 1;
nDirY = rn.Next(3) - 1;
}
placed =PlaceWords(s.ToUpper(),nRow,nCol,nDirX,nDirY);
}
}
}
Your PlaceWords method doesn't accept that many parameters, in fact, it accepts no parameters.
Further more, the way it looks, your PlaceWords is a recursive function that won't exit, leading to a stack overflow.
To fix this, you need to create a second PlaceWords function that accepts all 5 parameters, and does whatever PlaceWords does, and returns a boolean.
It looks like your nested for loops in Form1_Load should be placing random characters into tableLayoutPanel1. You then need to call PlaceWords() which will determine the location and direction to place each word in the words list. Near the end of PlaceWords you are calling PlaceWords(s.ToUpper(),nRow,nCol,nDirX,nDirY) which is supposed to actually put the word into tableLayoutPanel1. This second PlaceWords with 5 parameters should have a different name (I suggest PlaceString); it should not be trying to call the same Placewords method that it is in.
You need to then write the method PlaceString that will look like:
public bool PlaceString(string s, int nRow, int nCol, int nDirX, int nDirY)
{
/* whatever code you need to put the string into tableLayoutPanel1 */
}

Categories

Resources