Generate random number with quantity - c#

I have questions how can I set the quantity of numbers in the result box based on the selected value in dropdown
This is my code
if (!string.IsNullOrEmpty(TextBox1.Text) && !string.IsNullOrEmpty(TextBox2.Text))
{
string totalListNumber = "";
for (double x = Convert.ToDouble(TextBox1.Text); x <= Convert.ToDouble(TextBox2.Text); x++)
{
totalListNumber += x + "\n";
}
TextBox3.Text = totalListNumber;
}

Firstly you need to create a random number between your two values.
System.Random roll = new Random();
int nextRandom = roll.Next(minValue, maxValue);
Your combo box has an event called SelectedIndexChanged that will trigger when the user changes your combo selection.
In your SelectedIndexChanged code you should then put something like:
private void cmbQuantities_SelectedIndexChanged(object sender, EventArgs e)
{
System.Random roll = new Random();
int nextRandom;
// turn the two textBoxes into two doubles minValue and maxValue
if ((double.TryParse(TextBox1.Text, out double minValue) == false) || (double.TryParse(TextBox2.Text, out double maxValue) == false)) return;
// get the number of items to display or exit if it is not a valid number (return)
if (int.TryParse(cmbQuantities.Text, out int randomsToDisplay) == false) return;
string totalListNumber = String.Empty;
for(int i = 0; i < randomsToDisplay; i++)
{
nextRandom = roll.Next(minValue, maxValue);
totalListNumber += nextRandom.ToString() + "\n";
}
TextBox3.Text = totalListNumber;
}
There are a lot of other boosts you should do (such as using a listView etc), but this will get you what you want.
You should also try looking at using a datasource for the comboBoxQuantity that has an int value and string description so that selecting the combo item gets you the quantity value as an int automatically (or even just use a textbox!)
Avoiding duplicate numbers
As the Random class will produce duplicate numbers you will need to store your random rolls in a list and then check the list every time a new number is rolled.
The HashSet class allows fast lookups by a key (your random number in this case).
So:
private void cmbQuantities_SelectedIndexChanged(object sender, EventArgs e)
{
System.Random roll = new Random();
int nextRandom;
HashSet<int> rolledRandoms = new HashSet<int>();
// turn the two textBoxes into two doubles minValue and maxValue
if ((double.TryParse(TextBox1.Text, out double minValue) == false) || (double.TryParse(TextBox2.Text, out double maxValue) == false)) return;
// get the number of items to display or exit if it is not a valid number (return)
if (int.TryParse(cmbQuantities.Text, out int randomsToDisplay) == false) return;
string totalListNumber = String.Empty;
for(int i = 0; i < randomsToDisplay; i++)
{
nextRandom = roll.Next(minValue, maxValue);
// keep rolling until the nextRandom value is not in the rolledRandoms list
while (rolledRandoms.ContainsKey(nextRandom))
nextRandom = roll.Next(minValue, maxValue);
rolledRandoms.Add(nextRandom);
totalListNumber += nextRandom.ToString() + "\n";
}
TextBox3.Text = totalListNumber;
}

Related

My partial array keeps adding the empty data C#

I'm new to C# and we need to create an array that can hold 100 scores. But it needs to also accept something smaller (txt file with numbers between 0-100). My issue is that even tho I add a txt file that has 50 scores, it will think there is another 50 'blank scores' and it will count those as 0. So when my code does the average, total, and lowest score, it will mess it up. My textbook isn't being very help with the answer.
private double Total(double[] iArray)
{
double total = 0;
total = iArray.Length;
return total;
}
//Average test score
private double Average(double[] iArray)
{
double total = 0;
double average;
for (int index = 0; index < iArray.Length; index++)
{
total += iArray[index];//look into later
}
average = (double)total / iArray.Length;
return average;
} //done
//for hightest test score
private double Highest(double[] iArray)
{
double highest = iArray[0];
for (int index = 1; index < iArray.Length; index++)
{
if (iArray[index] > highest)
{
highest = iArray[index];
}
}
return highest;
} //done
private double Lowest(double[] iArray)
{
double lowest = iArray[0];
for (int index = 1; index < iArray.Length; index++)
{
if (iArray[index] < lowest)
{
lowest = iArray[index];
}
}
return lowest;
}//done
private void addFileButton_Click(object sender, EventArgs e)
{
try
{
const int SIZE = 100; //number of test
double[] scores = new Double[SIZE]; //array of the test scores
int index = 0; //loop counter
int count = 0;
double highestScore;
double lowestScore;
double averageScore;
double totalScore;
//Asking user to open a file
StreamReader inputFile;
if (openFile.ShowDialog() == DialogResult.OK)
{
inputFile = File.OpenText(openFile.FileName);
while (!inputFile.EndOfStream && count < scores.Length)//switching index to count
{
scores[count] = int.Parse(inputFile.ReadLine());
count++;
}
inputFile.Close();
}
else
{
MessageBox.Show("Operation Canceled.");
}
//Display test scores
for (index = 0; index < count; index++)
{
scoreListBox.Items.Add(scores[index].ToString());
}
//grabbing information
highestScore = Highest(scores);
lowestScore = Lowest(scores);
averageScore = Average(scores);
totalScore = Total(scores);
//display values
highesScoreLabel.Text = highestScore.ToString();
lowestScoreLabel.Text = lowestScore.ToString();
averageTestScoreLabel.Text = averageScore.ToString();
totalTestScoresLabel.Text = totalScore.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
You might just have to use Array.Resize then:
while (!inputFile.EndOfStream && scores.Count <= SIZE)
{
scores[count] = int.Parse(inputFile.ReadLine());
count++;
}
Array.Resize(scores, --count);
See if that works.
This was suggested before the OP's comment clarifying the should specifically use an array:
What if you used a List<double> when collecting the scores, then .ToArray() before you pass it into your other methods?
const int SIZE = 100;
List<double> scores = new List<double>();
[...]
if (openFile.ShowDialog() == DialogResult.OK)
{
inputFile = File.OpenText(openFile.FileName);
while (!inputFile.EndOfStream && scores.Count <= SIZE)
{
scores.Add(int.Parse(inputFile.ReadLine()));
count++;
}
[...]
var arrScores = scores.ToArray();
//grabbing information
highestScore = Highest(arrScores);
lowestScore = Lowest(arrScores);
averageScore = Average(arrScores);
totalScore = Total(arrScores);
Notice that the while loop has the condition changed for scores.Count <= SIZE to still only allow up to 100 scores.
Instead of constructing the Array yourself and implementing all these methods, I suggest, you read up in LINQ. LINQ stands for Language INtegrated Query and is essentially a bunch of extension methods on IEnumerable<T> that provide all of the functionality you need here.
I rewrote your event handler to use LINQ and it became much simpler.
private void addFileButton_Click(object sender, EventArgs e)
{
try
{
// Easier to follow if we just exit early
if (openFile.ShowDialog() != DialogResult.OK)
{
MessageBox.Show("Operation Canceled.");
return;
}
var scores = File.ReadAllLines(openFile.FileName)
// Always use TryParse to avoid exceptions
.Select(l => int.TryParse(l, out var score) ? score : -1)
// Filter out everything that is no valid score
.Where(s => s >= 0)
// You could also use ToList() here for a possible minimal performance gain and the possibility to add items later.
.ToArray();
// Display test scores
// We are using foreach instead of for here because we do not care about indexes. We simply want to add each item.
// We also do not need to add the ToString(), just adding an int is fine.
foreach (var score in scores)
scoreListBox.Items.Add(score);
// grabbing information
// We use LINQ methods here. Microsoft was nice enough di implement a bunch of often used methods on collections for us.
var highestScore = scores.Max();
var lowestScore = scores.Min();
var averageScore = scores.Average();
var totalScore = scores.Sum();
//display values
highesScoreLabel.Text = highestScore.ToString();
lowestScoreLabel.Text = lowestScore.ToString();
averageTestScoreLabel.Text = averageScore.ToString();
totalTestScoresLabel.Text = totalScore.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Subtracting items from a text file

When the first option is selected in a combo box I wish for my program to subtract consecutive strings from the one before.
Eg. The second value from the first,the third from the second, the fourth from the third and so on to the limit of 40.
I tried this but it just reads the actual list with no calculation
private void comboBoxOptions_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBoxOptions.SelectedIndex == 0)
{
string population = #"U:\My Documents\4.Bus App\Assignment 5\irishPopulation.txt";
const int SIZE = 40;
int[] numbers2 = new int[SIZE];
int index = 0;
StreamReader inputFile = new StreamReader(population);
while (index < numbers2.Length && !inputFile.EndOfStream)
{
numbers2[index] = int.Parse(inputFile.ReadLine());
index++;
}
textBoxAnswer.Text = File.ReadAllText(#"U:\My Documents\4.Bus App\Assignment 5\irishPopulation.txt"); //Puts file in textbox
textBoxAnswer.ScrollBars = ScrollBars.Vertical; //Gives text a scroll bar
inputFile.Close();
}

Populate datagridview (Rows) with an array of doubles

I'm clueless on how to populate my datagridview with lap numbers as rows and lap times as columns. I would greatly appreciate any advice. Here is my code for the race laps and times array:
public double[] LapTimes_Method(int NumLaps, double LapTime)
{
double[] raceLapArray = new double[NumLaps];
for (int x = 0; x < NumLaps; x++)
{
Random Random_Numbers = new Random(DateTime.Now.Millisecond);
double RandomLapNumber;
RandomLapNumber = Random_Numbers.Next(98, 102) / 100;
double RandomTime;
RandomTime = LapTime * RandomLapNumber;
raceLapArray[x] = RandomTime;
}
return raceLapArray;
}
I apologize for the confusion. Here's the code where I attempted to populate the datagridview rows with different lap numbers:
private void dgd_Simulation_Results_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
Simulation_Calculations Name2;
Name2 = new Simulation_Calculations();
int input;
bool isInt = int.TryParse(text_S_NumLaps.Text, out input);
double input2;
bool isDouble = double.TryParse(text_S_Lap_Time.Text, out input2);
double[] raceLapArray;
if (isInt == true && isDouble == true)
{
raceLapArray = Name2.LapTimes_Method(input, input2);
dgd_Simulation_Results.Rows[e.RowIndex].Cells[input].Value = "Lap" + input;
}
DataGridColumnStyle.Equals(input, input2);
}
To populate a datagridview, in general use:
for(your condition)
{
datagridviewName.Rows.Add(column1 value, column2 value, column3 value... etc);
}
In your case, the For loop condition statement would parse through your array.
For the column values, you would place in the index value that you wanted to output in the appropriate dgv column. (array[0], array[1], etc...)

Converting strings to int in C#

im pretty new to C# and i want to make a cardgame. What i have is a list of cards (strings) with names like c6, s3, h11, d13 where the character represents the colour and the number represents the value. When pressing a button the program takes a random string from the list and displays it in a textbox. From there the point of the game is to guess if the next random card will have a higher value or a lower value then the previous card.
What i want to do is to take the string from the textbox and turn it into a int so that i can compare the value of the previous card with the new one. Only problem is how do i get rid of the c in c6 so i can convert it by using parse.
This is my code.
public partial class MainWindow : Window
{
static Random rndmlist = new Random();
Random rndm = new Random();
List<string> deck = new List<string>();
int score = 0;
public MainWindow()
{
InitializeComponent();
}
private void test_Click(object sender, RoutedEventArgs e)
{
//disregard this
foreach (string j in deck)
{
testbox.Text += j + ", ";
}
}
private void btnstart_Click(object sender, RoutedEventArgs e)
{
//this is where i add all the cards to the list
for (int i = 1; i <= 13;)
{
deck.Add("c" + i);
i++;
}
for (int i = 1; i <= 13; )
{
deck.Add("s" + i);
i++;
}
for (int i = 1; i <= 13; )
{
deck.Add("h" + i);
i++;
}
for (int i = 1; i <= 13; )
{
deck.Add("d" + i);
i++;
}
}
private void btnbegin_Click(object sender, RoutedEventArgs e)
{
//this is where i take a random card from the list and display it in textBox2
int r = rndmlist.Next(deck.Count);
textBox2.Text = ((string)deck[r]);
//disregard this
testbox.Text += ((string)deck[r]) + ", ";
deck.Remove((string)deck[r]);
}
private void btnhigh_Click(object sender, RoutedEventArgs e)
{
//this is where i want to compare the cards.
}
}
Thank you in advance for reading this. (:
I'd better create a class Card, which represents a card, with 2 properties: Color and Number and implemented method Card.ParseFromString()
Try this,
string SubString = MyString.Substring(1);
But take care if the string is empty, it is an error case.
Assuming there will always be one (and only one) character before the number, you can simply do this:
string numberAsString = "c2".Substring(1);
And to make that an int:
int number = Int32.Parse(numberAsString);
You can use Regex to replace all alpha characters eg
string result = Regex.Replace(myString, #"[a-zA-Z\s]+", string.Empty);
string str = "c12";
var noChars = str.SubString(1); // take a new string from index 1
var number = Int32.Parse(noChars);

How to display array elements, if the number of elements is a variable

I'm making a calculator in GUI, and I need some help.
When I enter some data in a text box, I need to store it in an array. This is how I thought of it.
int numOfPackages;//used to get user input
private void button3_Click(object sender, EventArgs e)
{
int[] weight = new int[numOfPackages];
for(int i = 0; i < numOfPackages; i++)
{
weight[i] = Convert.ToInt32(weightBox.Text);
}
foreach (int i in weight)
totalCostLabel.Text = "" + weight[i];
}
And when I try to display the elements, it gives me the indexOutOfRange exception.
So, how do I display the elements of that array?
Thanks in advance.
This line
foreach (int i in weight)
totalCostLabel.Text = "" + weight[i];
should be
foreach (int w in weight)
totalCostLabel.Text = "" + w;
Your current code iterates the array of weights, and tries to use the weight as an index into the array of weights, causing an index out of range exception.
Another problem is with the first loop: you are setting all values of weight to the same number:
weight[i] = Convert.ToInt32(weightBox.Text); // That's the same for all i-s
If weights are to be different, they should come from different weight boxes, or the string from a single weightBox should be processed in such a way as to produce multiple numbers (for example, by using string.Split).
You have multiple problems here. First is this:
foreach (int i in weight)
totalCostLabel.Text = "" + weight[i];
This is iterating the weight array and using each value in that array. You then use that value as an index. Take the following example:
weight[0] = 0
weight[1] = 1
weight[2] = 15
In your code, the first two entries will work because there is an index of 0 and an index of 1. But when it gets to the last entry, it looks for an index of 15. You can fix this two ways, the first is to use a regular for loop:
for(int i=0; i < weight.Length; i++)
{
totalCostLabel.Text += weight[i];
}
This brings the second mistake. You aren't appending anything to your totalCostLabel in your code, you are just replacing the value. This will append all the values of weight together as one.
Another way to do this is to use the foreach loop:
foreach(int i in weight)
{
totalCostLabel.Text += i;
}
This is the same as above but you don't have to worry about indexing.
Bottom line, even after you fix your loop, you will probably need to fix the way that the label takes the text otherwise you won't get your desired result.
Maybe you wanted something more like?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
btnAdd.Enabled = false;
}
int[] weight;
int entriesMade;
int numOfPackages;
private void btnReset_Click(object sender, EventArgs e)
{
if (int.TryParse(numEntriesBox.Text, out numOfPackages))
{
weight = new int[numOfPackages];
entriesMade = 0;
btnReset.Enabled = false;
btnAdd.Enabled = true;
totalCostLabel.Text = "";
}
else
{
MessageBox.Show("Invalid Number of Entries");
}
}
private void btnAdd_Click(object sender, EventArgs e)
{
int value;
if (int.TryParse(weightBox.Text, out value))
{
weight[entriesMade] = value;
weightBox.Clear();
totalCostLabel.Text = "";
int total = 0;
for (int i = 0; i <= entriesMade; i++)
{
total = total + weight[i];
if (i == 0)
{
totalCostLabel.Text = weight[i].ToString();
}
else
{
totalCostLabel.Text += " + " + weight[i].ToString();
}
}
totalCostLabel.Text += " = " + total.ToString();
entriesMade++;
if (entriesMade == numOfPackages)
{
btnAdd.Enabled = false;
btnReset.Enabled = true;
MessageBox.Show("Done!");
}
}
else
{
MessageBox.Show("Invalid Weight");
}
}
}

Categories

Resources