Callback function to check the state of an integer - c#

I'm making a WP7-app for my programming class and I want to implement a callback function for checking the state of an integer and not calling the function for checking it explicitly. The integer iterates at the push of a button and when it reaches it's max input I would like to have a callback function checking this, but I'm not completely sure how to implement it.
private void Right_Button_Click(object sender, RoutedEventArgs e)
{
if (current_input <= MAX_INPUT)
{
user_input[current_input] = 3;
current_input++;
display_result();
}
}
#endregion
void display_result()
{
//will move alot of this to the a result page
DateTime time_end = DateTime.Now;
TimeSpan difference = time_end.Subtract(timer);
time_stamp = difference.ToString();
bool combination_error = true;
if (current_input == 4)
{
for (int i = 0; i < MAX_INPUT; i++)
{
if (user_input[i] != combination[i])
{
combination_error = false;
break;
}
}
if (combination_error)
{
MessageBox.Show("Correct combination The timer is " + time_stamp);
}
else
{
MessageBox.Show("Wrong combination");
}
}
}
It's after I increment current_input that I now explicitly call display result something I wish not to do and instead create a callback function for it.

You can't really put a callback function on an integer, however, you could expose your integer as a property and call a function from the property setter. Look at this example:
private int _myInteger = 0;
private int MyInteger {
get
{
return _myInteger;
}
set
{
_myInteger = value;
if (_myInteger <= MAX_INPUT)
MyCallBackFunction();
}
}
private void Right_Button_Click(object sender, RoutedEventArgs e)
{
MyInteger = MyInteger + 1;
// Do your other stuff here
}
private void MyCallBackFunction()
{
// This function executes when your integer is <= MAX_VALUE
// Do Whatever here
display_result();
}
What this is doing is exposing your integer through a private property. As long as you set the property through the setter (e.g. use the MyInteger = MyInteger + 1; syntax), you can have your setter check the condition and execute your call back function.

Related

Using a generic method in a C# class

Here is my current code:
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Random random = new Random();
public int[] randomInt = new int[20];
public double[] randomDouble = new double[20];
public string searchKey;
public int intOrDouble; // 0 if int, 1 if double
public static int Search<T>(T[] inputArray, T key) where T : IComparable<T>
{
for (int i = 0; i < 20; i++)
{
if (inputArray[i].CompareTo(key) == 0)
{
return i;
}
}
return -1;
}
public Form1()
{
InitializeComponent();
}
private void randomIntGeneration_Click(object sender, EventArgs e)
{
randomNumbersTextBox.Clear(); // empty the textbox
intOrDouble = 0; // this is for knowing which parameter to send to search method
// generate 20 random integers and display them in the textbox
for (int i = 0; i < 20; ++i)
{
randomInt[i] = random.Next(0, 100);
randomNumbersTextBox.Text += randomInt[i].ToString() + " ";
}
}
private void randomDoubleGenerator_Click(object sender, EventArgs e)
{
randomNumbersTextBox.Clear(); // empty the textbox
intOrDouble = 1; // this is for knowing which parameter to send to search method
// generate 20 random doubles and display them in the textbox
for (int i = 0; i < 20; ++i)
{
randomDouble[i] = random.NextDouble() + random.Next(0, 100);
randomNumbersTextBox.Text += randomDouble[i].ToString() + " ";
}
}
private void searchArrayButton_Click(object sender, EventArgs e)
{
searchKey = searchKeyTextBox.Text;
if(intOrDouble == 0) // int array passed
{
resultsTextBox.Text = Search(randomInt, searchKey).ToString();
}
else
{
resultsTextBox.Text = Search(randomDouble, searchKey).ToString();
}
}
}
}
What i am trying to do is use this generic method. The GUI allows the user to generate a random array of either ints or doubles. I then want to use the Search method in the searchArrayButton_Click control to display whether or not the "searchKey" value entered is in the array. The error I am getting is "The type arguments for method 'Form1.Search(T[], T)' cannot be inferred from the usage. Try specifying the type arguments explicitly." They appear toward the bottom of the code when I try to call Search twice in the searchArrayButton_Click control.
You're trying to search an array of int or double values for a string. As a result, your call to Search has two arguments with two different types. That doesn't match the function signature.
You need to convert whatever is in that textbox into the value you are searching for, either an int or a double.
if(intOrDouble == 0) // int array passed
{
resultsTextBox.Text = Search(randomInt, int.Parse(searchKey)).ToString();
}
else
{
resultsTextBox.Text = Search(randomDouble, double.Parse(searchKey)).ToString();
}

Min and max button and label

I'm trying to build a exam grader using C#. I'm new to this and don't know very much. What code would I use to add min and max buttons and to add a label stating whether it's a min or max?
private void btnAdd_Click(object sender, EventArgs e)
{
int points;
try
{
points = int.Parse(txtPoints.Text);
lstPoints.Items.Add(points);
txtPoints.Clear();
txtPoints.Focus();
if (lstPoints.Items.Count == 12)
{
txtPoints.Enabled = false;
btnAdd.Enabled = false;
}
if (lblResult.Text != "")
{
lblResult.Text = "";
}
}
catch
{
MessageBox.Show("Please enter only whole numbers");
txtPoints.Clear();
txtPoints.Focus();
}
}
private void btnAvg_Click(object sender, EventArgs e)
{
double total = 0;
for (int i = 0; i < lstPoints.Items.Count; i++)
{
total += (int)lstPoints.Items[i];
}
total /= lstPoints.Items.Count;
lblResult.Text = total.ToString();
}
private void btnClear_Click(object sender, EventArgs e)
{
lstPoints.Items.Clear();
txtPoints.Enabled = true;
btnAdd.Enabled = true;
}
}
}
hope this works
private void getMax()
{
int max=0;
for (int i = 0; i < lstPoints.Items.Count; i++)
{
if(max<(int)lstPoints.Items[i])
{
max=(int)lstPoints.Items[i];
}
}
lblResult.Text = max.ToString();
}
}
private void getMin()
{
int min=(int)lstPoints.Items[0];
for (int i = 1; i < lstPoints.Items.Count; i++)
{
if(min>(int)lstPoints.Items[i])
{
min=(int)lstPoints.Items[i];
}
}
lblResult.Text = min.ToString();
}
}
There are two possiblities as I see:
1) When you are writing this:
lstPoints.Items.Add(points);
Instead of adding to List(Of Integer) use SortedList. So the
list will always have the sorted result sets.
2) Use Array.Sort() to sort the records.
Once you have sorted records the first one is the minimum and the last one is the maximum (Assuming sorted in ascending order).
Take out two buttons and placed on the form, set Text Property from property window to Min and Max respectively and in event handler handle the Click event and pick the relevant resultset from lstPoints array.
Hope it helps!

Call procedure within function

Trying to call the procedure cycles() from within my function fibI, but the error is:
An object reference is required for the non-static field, method, or
property array_calculator.Fibonacci_panel.cycles()'
Heres the procedure
public void cycles()
{
k++;
}
and the function
public static double fibI(double input, int k)
{
if (input == 1 || input == 2)
{
return 1;
}
else
{
double fib1 = 0;
double fib2 = 1;
double fibResult = 0;
for(double i = 1; i < input; i++ )
{
fibResult = fib1 + fib2;
fib1 = fib2;
fib2 = fibResult;
cycles();
}
return fibResult; ;
}
Your "procedure" is not static. To repair you code just change:
public static void cycles() { k++; }
Moreover there isn't a "procedure" in C#. It is a normal function.

Please i want to know what the differences between these two delegates are?

I am trying to use delegate to return combox selected index in c# form. However, when i use the method below it works.
delegate void dttypeDelegate();
object searchType = Invoke(new dttypeDelegate(() =>
{
return dbtype.SelectedIndex;
}));
The above method return the combobox selected index to an object searchtype which i m able to retrieve in a form of string. However, the method.
delegate int dttypeDelegate();
private int searchType()
{
int i = 0;
if (dbtype.InvokeRequired)
{
dttypeDelegate dt = new dttypeDelegate(searchType);
this.Invoke(dt);
}
else
{
i = dbtype.SelectedIndex;
}
i = dbtype.SelectedIndex;
return i;
}
Throws an exception on that dbtype.SelectedIndex; is accessed from the thread other than the method it was made.PLs i wan to know why the exception ? what are the different between the two?
private int searchType()
{
int i = 0;
if (dbtype.InvokeRequired)
{
dttypeDelegate dt = new dttypeDelegate(searchType);
this.Invoke(dt); // <--- marshal to UI thread
}
else
{
i = dbtype.SelectedIndex;
}
i = dbtype.SelectedIndex; // <--- now we're back on the non-UI thread.
return i;
}
You need to exit the method after the Invoke.
Thank you all for the answers. I saw a similar delegate here that solve my problem . i just need to pass this.Invoke(dt); to i first or just return it as a return value.
private int searchType()
{
int i = 0;
if (dbtype.InvokeRequired)
{
dttypeDelegate dt = new dttypeDelegate(searchType);
i = (int)this.Invoke(dt);
return i;
}
else
{
return i = dbtype.SelectedIndex;
}
}
I saw this in the here

Global array not being accessed correctly

Below is my current code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public int[] trialArray = new int[10];
public int trialCounter = -1;
private void button1_Click(object sender, EventArgs e)
{
bool button1Click = true;
if (button1Click == true)
{
ITIpanel.Visible = true;
for (int i = 0; i < trialArray.Length; i++) { trialArray[i] = -1; } // Set default value through array
int counter = 0;
Random rnd = new Random();
while (counter < 10 / 2)
{ // Red trials, fill half array
int index = rnd.Next(0, 10 - 1);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
while (counter < 10)
{
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}
}
}
private void ITIpanel_Paint(object sender, PaintEventArgs e)
{
if (ITIpanel.Visible == true)
{
trialCounter += 1;
timer1.Enabled = true;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
ITIpanel.Visible = false;
timer1.Enabled = false;
if (trialArray[trialCounter] == 1) { redstimPanel.Visible = true; }
else { bluestimPanel.Visible = true;}
if (trialCounter == 9) { Application.Exit(); }
}
public int counter = 0;
public event EventHandler Clicked5TimesEvent;
private void OnClicked5TimesEvent()
{ if (Clicked5TimesEvent != null) { Clicked5TimesEvent(this, EventArgs.Empty); } }
private void bluestimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
private void redstimPanel_MouseDown(object sender, EventArgs e)
{
//FR requirement
counter++; if (counter % 5 == 0) { redstimPanel.Visible = false; ITIpanel.Visible = true; }
}
}
}
As you can see, I am attempting to make a global array with 10 items. On the button click the 10 items are supposed to be altered such that half contain the value 1 and the other half contain the value 2.
Then, on the timer tick, depending on the value in the trialCounter, which determines the part of the array to be accessed, it should display either the redstimPanel or the bluestimPanel.
Therefore, if the 'trialCounter' is equal to 8, and 8 in the TrialArray is equal 1, the 'redstimPanel' should become Visible. Alternatively, if 8 in the 'TrialArray' is equal to 2, the 'bluestimPanel' should become Visible.
This, however, is not working as I would like it to. Thus, there are clearly some issues with my code. Do you all have any suggestions?
You never reset counter, or have the second loop (the one setting the 2s) be the full array.
There is also an error with the random number, rnd.Next(a,b) a - lower bound (inclusive), b - upper bound (exclusive). So it should be rnd.Next(0,10); so you have a chance of populating the last array position.
while (counter < 10 / 2) { // Red trials, fill half array
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 1; ++counter; } //if unchanged value, change it
}
//Counter on the first loop here is already 5 (it exited the previous loop)
//So allow it to get to 10, and populate the FULL array.
while (counter < 10) {
int index = rnd.Next(0, 10);
if (trialArray[index] == -1) { trialArray[index] = 2; ++counter; }
}
Allow me to give you some tips and some explanations regarding your code:
First of all, you probably wanted that local button1Click variable to know later on whether the button has been clicked or not. For that to work, you should place it outside that function, otherwise it's never going to be used, and will be true with every button click, something like this:
bool button1Click = false;
private void button1_Click(object sender, EventArgs e)
{
if (!button1Click)
{
When you have a condition, you want the code to decide, whether an expression is true or false you may omit the part "== true" because it doesn't add anything new.
You have two whiles. Your idea was to run the counter until 5, with the first piece of code, and then from 5 to 10 the second piece of code. Now let me try to explain what is actually going on. The counter will go on until 5 filling 1s at random indices. Then at 5, the expression in the while will become false and it breaks out from the loop. Since the second while has the very same expression, it simply avoids it and goes on. One of the many solutions would be to have an if in the loop like this:
while (counter < 10)
{
if (counter<5)
{
// fill red
}
else
{
// fill blue
}
}
The way you fill up the values in your array. Have you thought about what's going to happen when the same index will be generated several times? It means it'll overwrite the previous value while certain index will remain -1.

Categories

Resources