I'm needing to create random numbers based on the number of random numbers needed by a user.
The user can then save those random numbers to a file when the save to file button is clicked.
After that, the program allows the user to open the same file, but this time, the file opened needs to display how many random numbers within a specific range were created.
The ranges are: (0-19, 20-39, 40-59, 60-79, and 80-99).
So far I'm able to create one random number and list the same number over the number of times entered by the user, but unfortunately:
The random numbers created need to all be random through the number of iterations created by the user.
I don't know how to display the numbers within their respective range.
I can't display the numbers properly.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void RandNumbtextBox_TextChanged(object sender, EventArgs e)
{
}
private void saveFileButton_Click(object sender, EventArgs e)
{
double randomNumber = double.Parse(RandNumbtextBox.Text);
Random r = new Random();//random number object
int random = r.Next(1, 10);// random number 1
if (saveFileDialog.ShowDialog()== DialogResult.OK)
{
StreamWriter outputFile;
outputFile = File.CreateText(saveFileDialog.FileName + ".txt");
for(int i = 0; i < randomNumber; i++)
{
outputFile.WriteLine(random.ToString());
}
outputFile.Close();
}
else
{
MessageBox.Show("op cancelled");
}
}
private void openFileButton_Click(object sender, EventArgs e)
{
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
StreamReader inputFile;
inputFile = File.OpenText(openFileDialog.FileName);
int sum = 0;
while (!inputFile.EndOfStream)
{
sum += int.Parse(inputFile.ReadLine());
}
inputFile.Close();
MessageBox.Show(sum.ToString());
}
else
{
MessageBox.Show("op cancelled");
}
}
}
Thanks to John I was able to figure out the first issue of the question. Generating the random number issue and write them to file.
I'm still unable to:
*Display the numbers within their respective range.
I can't display the numbers properly.
OP, you are assigning the random number once:
int random = r.Next(1, 10);// random number 1
And then writing it out randomNumber times:
for(int i = 0; i < randomNumber; i++)
{
outputFile.WriteLine(random.ToString());
}
I think your code needs to read:
for(int i = 0; i < randomNumber; i++)
{
outputFile.WriteLine(r.Next(1, 10).ToString());
}
As for counting numbers in ranges: A simple approach might be to create "count" variables for each range, and implement branching logic to increment the correct one depending on the number you're looking at. A more dynamic approach may involve a dictionary, or an array of classes which contain the range and a count value.
Related
I want to check if there is same value in the array or not as I mentioned in the title. And if there is, I want to pass that value and check another random value to add to listbox.
In my form, there is 2 textBox, 1 listbox and 1 button. When button is clicked, listbox has to show random numbers up to sum of textbox1 and textbox2. For instance;
5 entered from textbox1 and 10 entered from textbox2. Sum is of course 15 and listbox has to show 15 random numbers but those numbers have to be different from each other.
I wrote something like that and used Contains method to check if there is same value or not. But the program froze and didn't give any error.
int a, b;
Random rnd = new Random();
int[] array;
private void button1_Click(object sender, EventArgs e)
{
a = Convert.ToInt32(textBox1.Text);
b = Convert.ToInt32(textBox2.Text);
int c = a + b;
array = new int[c];
for (int i = 0; i < array.Length; i++)
{
int number = rnd.Next(c);
foreach(int numbers in array)
{
if (array.Contains(numbers))
{
i--;
}
else
{
array[i] = number;
listBox1.Items.Add(array[i]);
}
}
}
I also did it without foreach(Only Contains part I mean). Also didn't work. I wrote in "else";
array[i] += number;
it also didn't work.
I would be very appreciated if you help me. Thanks in advance.
instead of a for loop, use a while loop:
int = 0;
while(i<c)
{
int random rnd.Next(c);
if(!array.Contains(random))
array[i++] = random;
}
you may also create a list of numbers from 1-15 and then shuffle them (as your random function will create only random numbers from 1-15 just random):
array = Enumberable.Range(0,c).OrderBy(x => rnd.Next()).ToArray();
The above code is much faster, because imagine that we have generated 14 random numbers and only one number (5 for instance) left, it has to go through loop several times so that finally random number that is generated equals to 5, but in the above code there is no need to check that, we just have all numbers and then we shuffle it.
You can try to use do...while instead of for loop
Random.Next get the value from 0 to c - 1, so rnd.Next(c + 1); need to add 1 otherwise, the loop will not be stopped.
var array = new int[c];
int number;
for (int i = 0; i < array.Length; i++)
{
do
{
number = rnd.Next(c + 1);
} while (array.Contains(number));
array[i] = number;
listBox1.Items.Add(array[i]);
}
You basically need to shuffle your data. Create a collection with all values:
var temp = Enumerable.Range(0, c);
Now order it by random
temp = temp.OrderBy(_ => rnd.Next());
Now you can add temp to your listBox
Or, as single line:
listBox1.Items.AddRange(Enumerable.Range(0, c).OrderBy(_ => rnd.Next()));
private void btn_Save_Click(object sender, EventArgs e)
{
// Declare int variable.
int randomNumber = 0;
// Declare a StreamWriter variable.
StreamWriter outputFile;
// Get the number of random integers to hold in file.
int number = int.Parse(txt_Number.Text);
if (saveFile.ShowDialog() == DialogResult.OK)
{
// Create the selected file.
outputFile = File.CreateText(saveFile.FileName);
// Create a Random Object.
Random Rand = new Random();
for (int count = 0; count < number; count++)
{
// Get random integers and assign them to randomNumber.
randomNumber = Rand.Next(1, 101);
// Write data to the file.
outputFile.WriteLine(randomNumber);
// Close the file.
outputFile.Close();
MessageBox.Show("File saved in path:" + saveFile.FileName);
}
}
else
{
// Display an error message.
MessageBox.Show("Operation Cancelled");
}
}
private void btn_Clear_Click(object sender, EventArgs e)
{
// Clear the TextBox.
txt_Number.Text = "";
}
private void btn_Exit_Click(object sender, EventArgs e)
{
// Close the form.
this.Close();
}
}
The question is: Create a program that writes a series of random numbers to a file. Each random number should be in the range of 1 through 100. The application should let the user specify how many random numbers the file will hold.
The code is working but i' having problems with the output writeline.
Each time i'm running the program, it says exception unhandled and cannot write to a Closed TextWriter.
Also instead of saving multiple random numbers, it is saving only one.
Any help concerning these 2 problems would be great.
Your error is in the for loop here:
for (int count = 0; count < number; count++)
{
// Get random integers and assign them to randomNumber.
randomNumber = Rand.Next(1, 101);
// Write data to the file.
outputFile.WriteLine(randomNumber);
// Close the file.
outputFile.Close();
MessageBox.Show("File saved in path:" + saveFile.FileName);
}
You close the file before iterating through all the numbers. Thus, you cannot write past the first number. The close function should be outside the for loop like so:
for (int count = 0; count < number; count++)
{
// Get random integers and assign them to randomNumber.
randomNumber = Rand.Next(1, 101);
// Write data to the file.
outputFile.WriteLine(randomNumber);
MessageBox.Show("File saved in path:" + saveFile.FileName);
}
// Close the file outside for loop
outputFile.Close();
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);
I am practicing the bubble sort algorithm in Windows Forms. I have gotten my program to the point where the algorithm works, and I can generate numbers in a listbox from 1-100 in non-numerical order, and then run the bubble sort algorithm to sort the numbers. The problem I'm having is that I don't want any duplicate numbers to be generating in the listbox. Basically, I have a radio button that produces 100 integers in the listbox when clicked. Then I have a "sort" button that will sort through those numbers in the listbox. I am currently using arrays to do this, as an array is easiest to use when writing the bubble sort algorithm and for creating random numbers in the listbox (that's why I'm not creating a new list and attempting to shuffle it that way). If anyone has any suggestions as to what I could do to prevent duplicates, I'd greatly appreciate it. Here is an excerpt of my code below.
int[] array;
int smallMaxSize = 101;
#region Sort Button Click
private void button1_Click(object sender, EventArgs e)//Bubblesort Code
{
bubbleSortAlgorithm(smallMaxSize);
}
#endregion
#region Swap Numbers
private void swap(int one, int two)//Swaps larger number for smaller number
{
int temp = array[one];
array[one] = array[two];
array[two] = temp;
}
#endregion
#region Bubble Sort Algorithm
private void bubbleSortAlgorithm(int Size)
{
int Out;
int In;
for (Out = Size - 1; Out > 1; Out--)
{
for (In = 0; In < Out; In++)
{
if (array[In] > array[In + 1])
{
swap(In, In + 1);
Numbers.Items.Clear();
for (int i = 0; i < Size; i++)
{
Numbers.Items.Add(array[i]);
}
}
}
}
}
#endregion
#region Small Max: 100
private void radioButton1_CheckedChanged(object sender, EventArgs e)//Max 100 button
{
Numbers.Items.Clear();
array = new int[smallMaxSize];
Random numGenerator = new Random();
numGenerator.Next(smallMaxSize);
for (int i = 0; i < 101; i++)//Generates 100 random numbers from 1-100
{
array[i] = numGenerator.Next(smallMaxSize);
Numbers.Items.Add(array[i]);
}
}
#endregion
When you need to generate 100 random numbers from 1 to 100, inclusive, with no duplicates, actually generating them with numGenerator.Next(smallMaxSize) and checking for duplicates is very inefficient. A better approach is to fill the array with the 100 numbers that you want, in sorted order, and then apply a shuffle algorithm to the list.
This Q&A explains how to shuffle a list using Fisher-Yates algorithm.
This question already has answers here:
Random number generator in C# - unique values
(5 answers)
Closed 9 years ago.
I'm creating a bingo game and I'm using Random to generate random numbers in an int array but my problem here is that sometimes a number is used again in an index. How can I make the numbers in index unique?
Here is my work:
namespace Bingo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Random randNum1 = new Random();
int[] random1 = new int[5];
int qwe = 0;
int i = 0;
private void button1_Click(object sender, EventArgs e)
{
Class1 class1 = new Class1();
class1.checker(this);
if (label1.Text == label2.Text || label3.Text == label4.Text) {
label2.Text = randNum1.Next(1, 15).ToString();
label4.Text = randNum1.Next(1, 15).ToString();
}
if (label5.Text == label1.Text || label5.Text == label2.Text) {
label5.Text = randNum1.Next(1, 15).ToString();
}
}
private void Form1_Load(object sender, EventArgs e)
{
Class1 class1 = new Class1();
class1.SetTwo(this);
for (int i = 0; i < random1.Length; i++)
{
random1[i] = randNum1.Next(1, 15);
label1.Text = random1[0].ToString();
label2.Text = random1[1].ToString();
label3.Text = random1[2].ToString();
label4.Text = random1[3].ToString();
label5.Text = random1[4].ToString();
}
}
}
The problem with looping until you found an unused one is that as the game progresses, you'll take longer and longer to find a valid number. It's theoretically possible that your loop will never end (infinitessimally likely, but still...)
The easiest thing to do is what happens in a real Bingo game. Start from a limited set, and actually remove the item from the set each time you draw. Fill a List or any other dynamic indexed container with your initial possibilities, randomly choose an index from 0 to the size of the list, and then remove the selection out of the list.
This will guarantee that every selection produces a unique result, with no looping.
I figured an illustration of Scott Mermelstein's answer may help:
List<int> AvailableNumbers;
Random random;
private void Form1_Load(object sender, EventArgs e)
{
//Create a list of numbers, 1-14
AvailableNumbers = Enumerable.Range(1, 14).ToList();
random = new Random();
label1.Text = GetNextNumber().ToString();
label2.Text = GetNextNumber().ToString();
label3.Text = GetNextNumber().ToString();
label4.Text = GetNextNumber().ToString();
label5.Text = GetNextNumber().ToString();
}
private int GetNextNumber()
{
//Get a random index within the bounds of AvailableNumbers
var nextIndex = random.Next(0, AvailableNumbers.Count);
var nextNumber = AvailableNumbers[nextIndex];
AvailableNumbers.RemoveAt(nextIndex);
return nextNumber;
}
Another approach is to shuffle the sorted list of numbers:
var numbers = Enumerable.Range(1, 15).OrderBy(i => Guid.NewGuid()).ToArray();
How does this work?
start with a list of integers (Enumerable.Range(1, 15) => [1, 2, 3, ..., 15])
reorder them (OrderBy)
with a "random" index Guid.NewGuid()
Obviously, this will only work, if Guid.NewGuid() doesn't produce consecutive GUIDs, but, I think the default doesn't, since that was a security issue with the first implementations of the GUID algorithm.
(I got the shuffling with GUIDs tip from here:
Randomize a List<T>)
You can use other, more efficient methods to shuffle the "deck", but for Bingo style applications, this should work just fine.
Another idea:
var rand = new Random();
var numbers = Enumerable.Range(1, 15).OrderBy(i => rand.Next()).ToArray();
Since the elements in the starting list are unique, the result is guaranteed to reproduce that property.
everytime you grab a new number, just surround it with this :
int num;
do
{
num = randNum1.Next(1, 15);
}
while(random1.Contains(num))
random1[i] = num;
to guarantee it is unique