Pass array number of object to event handler - c#

I have an array of PictureBoxes.
for(int i = 0; i<10; i++)
{
this.elevatorDoors[i] = new System.Windows.Forms.PictureBox();
}
I would like to pass to the click event of one object,the array number that the particular object has.
this.elevatorDoors[i].Click +=
new System.EventHandler((sender,e)=>this.elevatorDoor_Click(sender,e, i));
But all I get when the event fires up is the number 10. I would like to get for example the number 4 when I click on the 4th PictureBox.

var tempValue = i;
this.elevatorDoors[i].Click +=
new System.EventHandler((sender,e)=> this.elevatorDoor_Click(sender,e, tempValue));
This will fix it. So you must pretty much ensure that when you are Invoking the event you are taking the current value of your loop iteration. After leaving the loop the value will always equal to last value. So you introduce tempValue which stores the current iteration.

I am assuming that this is more like a local scope problem. Just create a new function where you assign the clickhandler
private void AssignCallback(PictureBox pb, int index) {
pb.Click += new System.EventHandler((sender,e)=>this.elevatorDoor_Click(sender,e, index));
}
An alternative method would be to use the Tag property on the picturebox and read the value of the tag in your callback like so
this.elevatorDoors[i].Tag = i;
this.elevatorDoors[i].Click +=
new System.EventHandler((sender,e)=>this.elevatorDoor_Click(sender,e, Convert.ToInt32(((Control)i).Tag))-;

Related

Unity C# Cycling some texts without repeating them

I've a line in the bottom part of the main screen of the game, that every time the scene is loaded, it shows a different tip (how to play, how to change music...).
The question is that I'm using Random.Range for that but, honestly, I'll prefer a way where all tips are showed, one by one in a random way, but without repeating any of them.
My code is as follows:
int randNum;
void Start () {
randNum = Random.Range(0,5);
}
void Update () {
switch (randNum)
{
case 0:
// blah, blah, blah...
case 1...
How can I achieve what I want?
Thans for yout timeeee :)
You can remove the switch statement and store each message in a list.
var tips = new List<string>();
tips.Add("The clouds are white");
...
Then you can randomize the elements in the list (more on that here) and show tips one by one. All you need is to keep track of the index. Example:
// This needs to be a field.
int index = 0;
void ShowTip()
{
// TODO: make sure index is not equal or greater than tips.Count
tip = tips[index];
index++;
// Display the tip
}
What you can do is to shuffle your list of tip. The Fisher-Yates shuffle is one of the most common.
static Random _random = new Random();
static void Shuffle<T>(T[] array)
{
int n = array.Length;
for (int i = 0; i < n; i++)
{
// Use Next on random instance with an argument.
// ... The argument is an exclusive bound.
// So we will not go past the end of the array.
int r = i + _random.Next(n - i);
T t = array[r];
array[r] = array[i];
array[i] = t;
}
}
public static void Main()
{
string[] array = { "tip 1", "tip 2", "tip 3" };
Shuffle(array);
foreach (string value in array)
{
Console.WriteLine(value);
}
}
output
net
dot
perls
source
Suppose your messages are stored in a list of string declared at the global level together with your random class and with an additional List of strings initially empty
List<string> needToDisplayMessages = new List<string>();
List<string> base_messages = new List<string>{"message1","message2","message3","message4","message5"};
Random rnd = new Random();
In your update method check if the list of messages to be displayed is empty and if yes copy the messages from the list with the predefined message. Now use the random instance to choose the index of the message to display and get it from the dynamic list. Finally remove the message from the list of message still to be displayed.
void Update () {
// We refill the list if it is empty
if(needToDisplayMessages.Count == 0)
needToDisplayMessages.AddRange(base_messages);
// Choose a random number topped by the count of messages still to be displayed
int index = rnd.Next(0, needToDisplayMessages.Count);
string message = needToDisplayMessages[index];
..... display the message someway .....
// Remove the message from the list
needToDisplayMessages.RemoveAt(index);
}
Of course, if you want to display the messages in sequential order there is no need of this but (as already explained) just an index. But if you want to randomly choose the message until you have shown all of them and then restart the cycle, perhaps this approach is not too much complex.

How do i make this button's event handler to add multiple values into an array?

My program allows the user to input values of hours and minutes into an array of predefined length.
I want to have this button called add for a form I'm creating to allow multiple inputs from the user until the array is fully inhabited. Then when it's done, to call a sortArray() method They way it is now it only allows one input then it throws an exception. How do I go about this?
private void addButton_Click(object sender, EventArgs e)
{
int index = 0;
try
{
while (index <= array.Length)
{
minutes = Int32.Parse(minutesTextBox.Text);
hours = Int32.Parse(hoursTextBox.Text);
MessageBox.Show("You have successfully entered a time!");
array[index] = new RandomClass.Time(hours, minutes);
index = index + 1;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.GetType().FullName);
MessageBox.Show("Please only input integer numbers. Start again from the beginning");
hoursTextBox.Text = null;
minutesTextBox.Text = null;
array = null;
arrayLength = null;
}
MessageBox.Show("Please choose what order you want arrange the sort!");
FileA.RandomClass.sortArray(array);
}
You haven't shown how large the array is, but this line:
while (index <= array.Length)
will cause a problem when you get to the end of your array because the indices of an array go from zero to one less than the length of the array.
So you need to change this line to either:
while (index < array.Length)
It might safer to loop like this:
foreach (ver element in array)
{
// do stuff
element = new RandomClass.Time(hours, minutes);
}
as this way there is no way you can loop beyond the end of the array.
Dont use this line. You will get IndexOutOfRangeException exception where index will be equal to array length.
while (index <= array.Length)
You should use like this.
while (index < array.Length)
One more this, you can use int.TryParse to get rid of exception id text is null or emptry.
I am basing my answer on the assumption that the add button has to be clicked for every new value of hours and minutes.
Currently I see the following problems in your code
int index = 0;
You are setting the index to zero every time the add button is clicked, due to this array values are overwritten on every click of the add button. Initialize index at a more appropriate place in your code.
while (index <= array.Length)
Let's assume the array is of length 5 and the value of index=5, then this line will cause an error as arrays are zero indexed in c#
minutes = Int32.Parse(minutesTextBox.Text);
Int32.Parse method returns a bool, which represents whether the conversion succeeded or not. A more appropriate way to use int32.Parse would be
Int32.Parse(minutesTextBox.Text, out minutes);
Now, since the new values are added per Add button click you can change the while to if and else. i.e.,
if(index < array.Length)
//Parse, add to array and increment the index
else
//Reset index (if required) and Call the sortArray() method.

Custom Queue Class Iteration and Data Retrieval C#

So I'm working in Visual Studio 2015 with a few custom classes. One of which is called MinPriorityQueue, and it is a priority queue that, in this situation, allows me to retrieve the object of MinimumPriority in the queue via a property MinimumPriority. There is also a method called RemoveMinimumPriority, which is self-explanatory.
I am not allowed to modify this method, it was pre-made for us for this assignment, otherwise I would have already found a simple solution.
My program is meant to compare two text files, and return a value based off a certain equation which isn't important as far as this post goes. The problem I am having is within my UserInterface code. Here is my click event for the 'Analyze' button on my GUI.
private void uxAnalyze_Click(object sender, EventArgs e)
{
Dictionary<string, StoreWord> dictionary = new Dictionary<string, StoreWord>();
const int _numFiles = 2;
MinPriorityQueue<float, StoreInfo> minQueue = new MinPriorityQueue<float, StoreInfo>();
int numWords1 = 0;
int numWords2 = 0;
//Process Both Input Files
using (StreamReader sr = new StreamReader(uxTextBox1.Text))
{
for (int i = 0; i < _numFiles; i++)
{
if (i == 0)
{
dictionary = ReadFile(dictionary, uxTextBox1.Text, i, out numWords1);
}
if (i == 1)
{
dictionary = ReadFile(dictionary, uxTextBox2.Text, i, out numWords2);
}
}
}
int[] numWords = new int[2];
numWords[0] = numWords1;
numWords[1] = numWords2;
//Get 50 Words with Highest Combined Frequencies
foreach(var entry in dictionary.Values)
{
StoreInfo freq = new StoreInfo(entry, numWords);
minQueue.Add(freq, Convert.ToSingle(entry[0] + entry[1]));
if(minQueue.Count > 50)
{
minQueue.RemoveMinimumPriority();
}
}
//Compute and Display the Difference Measure
float diffMeasure = 0;
float temp = 0;
foreach( x in minQueue)
for (int i = 0; i < minQueue.Count; i++)
{
temp += minQueue.????; //This is where my problem stems
}
diffMeasure = (float)(100 * Math.Sqrt(temp));
}
A few lines from the end you will see a comment showing where my problem is located. The MinPriorityQueue (minQueue) has two parameters, a Priority, and a Value, where the Priority is a Float, and the Value is another class called StoreInfo. This class has an Indexer, which will return information from a different file depending on what the index is. In this case, there are only two files. For example: StoreInfo[i] returns the frequency of a word in the ith text file.
Ideally, my code would look like this:
for (int i = 0; i < minQueue.Count; i++)
{
temp += (minQueue.minimumValue[0] - minQueue.minimumValue[1])*(minQueue.minimumValue[0] - minQueue.minimumValue[1]);
}
diffMeasure = (float)(100 * Math.Sqrt(temp));
Problem is, that would require a minimumValue property, which I don't have access to. All I have is minimumPriority.
As far as I can see, there is no other way for me to get the Values that I need in order to get the frequencies that I need to get from the indexer and put into the equation.
Help is much appreciated.
Alright guys, I've been thinking at this for far too long, and it doesn't seem like anyone else sees another solution either.
At this point, I'm just going to go with the logical solution and add another property into the MinPriorityQueue class, even though it is against my professor's wishes.
Thank you all anyway.

Simulating snowfall in Windows Forms C#

I'm quite new in C# and I want to creating something like falling snow (dots) in C# using Windows Forms.
I was already able to create the snowflakes at the top of the screen (I want to create new dot every 0,1s, at random x-position of Form and write down every snowflake's position into the List(Point) and with every Tick of timer (0,1s) I want the snowflake to change its position by 3px down and 1-3px right)
But I have the problem with refreshing the snowflakes positions. I don't know how to acces each snowflake in the List to Randomize its new position.
I tried foreach, but it gives me error, that says I cannot change variable in foreach.
Example:
foreach (var snowflake in snowflakeList)
{
snowflake.Y += 3;
snowflake.X += moveRandom.Next(1, 4);
}
Can anyone please tell me how can I divide List(Point) of snowflakes into invdividual snowflakes, so I could change position of every single dot separately?
Thank you :-)
The simplest way is just to use the index of the collection:
for (int i = 0; i < snowflakeList.Count; i++)
{
var snowflake = snowflakeList[i];
snowflake.Y += 3;
snowflake.X += moveRandom.Next(1, 4);
snowflakeList[i] = snowflake;
}
As Andrews answer use a for loop, but as the list is of Points (a value type) you would need to reference the Point in the list directly rather than make a copy of it:
for (int i = 0; i < snowflakeList.Count; i++)
{
snowflakeList[i].Y += 3;
snowflakeList[i].X += moveRandom.Next(1, 4);
}

Dynamic UI, Loop

I created a dynamic UI that shows each module that the user has added to their selection and all the assessments for that module underneath the module name,
All data is saved in array lists - including objects as textBoxes and labels.
Here's what it looks like:
http://www.4shared.com/photo/fullsize/Ja3jHpRJ/screen1.html
Then the user should enter their marks for each assessments
And the Calculate button should calculate their overall mark for each module
At this stage I am just adding the marks together.
The program works fine when there's only one module added, but when there are more modules it seems to think that a TextBox is empty, even though i fill them all with numbers.
here is my code
private void calculateButton_Click(object sender, EventArgs e)
{
int modLength = dat.ModuleTitle.Count;
int modAsses = 0;
int loopCount = 0;
for (int i = 0; i < modLength; i++)
{
int total = 0;
if ((textboxComputer[loopCount] as TextBox).Text == "")
{
Console.WriteLine("!!!!!");
}
else
{
modAsses = int.Parse(dat.ModuleAssessNum[i].ToString());
for (int y = 0; y < modAsses; y++)
{
total = total + int.Parse((textboxComputer[loopCount] as TextBox).Text.ToString());
loopCount = loopCount + 1;
}
Console.WriteLine(total);
}
}
}
When i add two or more modules it displays the "!!!!!" message, but calculates the mark for the first module added.
here's some output
http://www.4shared.com/photo/fullsize/PlY29BMQ/screen2.html
You need to make sure that the code that creates the extra dynamic elements on screen is being called as part of the page load, so that then the viewstate is inserted back into the elements and can be read back out by your code.
there is something wrong with your code, probably a lot wrong(except the names of your variables).
Take a look at your loopCount variable - you will only conditionally change it in your loop but you always use it at the start of the loop(where you do textboxComputer[loopCount]).
So what's the expected behavior of that? The first time you get in to the loop if you go to your 'else' part you may print the total as you say but you also change the loopCount variable, once you get to the Console.WriteLine("!!!!!"); you never change it again - so your iterations will behave the same.

Categories

Resources