Logical error of random value - c#

i created a win-form with an ability to generate a number with 3 labels(label1,label2,label4) and a textbox that will be storage and then validate its value when ever the button is pressed. my problem is that the label4 didn't raise its own value when ever i answer it correctly.
with this code
int num = 0;
string temp;
if (textBox1.Text == ans.ToString())
{
num++;
temp = "Correct Answers " + num;
int a = rr.Next(4), b = rr.Next(4);
ans = a + b;
label1.Text = a.ToString();
label2.Text = b.ToString();
label4.Text = temp;
textBox1.Focus();
textBox1.SelectAll();
}

Does label4 never increase its own value, or does it never increase it more than the first time? Because the latter of those two options is exactly what you're doing. Look at the steps in your logic:
int num = 0;
string temp;
//...
num++;
temp = "Correct Answers " + num;
//...
label4.Text = temp;
No matter how many times you answer correctly, label4 can only ever display:
"Correct Answers 1"
Because you always initialize num to 0, increment it to 1, and display it. Where do you track how many answers have been given in total?
You'll need some integer value in a higher scope to track that. Where you place it depends on the lifespans of your objects. For example, if the object in which this logic exists persists across multiple answers (that is, if the same instance is always in memory and it's not destroyed and re-created), then you can add a class-level member to hold that value. Something like this:
private int TotalCorrectAnswers { get; set; }
Then your code would use that value instead of instantiating a new one each time:
string temp;
//...
TotalCorrectAnswers++;
temp = "Correct Answers " + TotalCorrectAnswers;
//...
label4.Text = temp;
Other options could include storing the value in a static field to persist across object life cycles, a database to persist across application life cycles, etc. It depends on how your application is structured.

So when you provide an answer to the math problem, the highest your Label4 that indicates correct answers counts is 1? You aren't by chance defining the variable num within your click event handler are you? In this case every time you got an answer correct it would increment num from zero to one, incorrect would show no change, but then your next correct answer would again increment from zero to one.

Related

How to make this code more functional or 'prettier'

I've been working on a project where I need on a button press that this line gets executed.
if (listView1.SelectedItems[0].SubItems[3].Text == "0") //Checks to see Value
{
listView1.SelectedItems[0].SubItems[3].Text = "1";// If Value is Greater, Increase and Change ListView
questionNumberLabel.Text = listView1.SelectedItems[0].SubItems[3].Text;// Increase and Change Label
}
Now I have this repeated about 10 times with each value increasing by one. But I know that this is ugly, and dysfunctional. As well as conflates the file size. I've tried a few things. Primarily this method.
if (listView1.SelectedItems[0].SubItems[3].Text == "0")
{
for (var i = 1; i < 100;)
{
if (!Int32.TryParse(listView1.SelectedItems[0].SubItems[3].Text, out i))
{
i = 0;
}
i++;
listView1.SelectedItems[0].SubItems[3].Text = i.ToString();
Console.WriteLine(i);
}
}
But instead of just adding one, it does the 100 instances and ends. The reason this is becoming a pain in the *** is because the
listView1.SelectedItems[0].SubItems[3].Text
is just that - it's a string, not an int. That's why I parsed it and tried to run it like that. But it still isn't having the out come I want.
I've also tried this
string listViewItemToChange = listView1.SelectedItems[0].SubItems[3].Text;
Then parsing the string, to make it prettier. It worked like it did before, but still hasn't given me the outcome I want. Which to reiterate is, I'm wanting the String taken from the list view to be changed into an int, used in the for loop, add 1, then restring it and output it on my listView.
Please help :(
You say you want the text from a listview subitem converted to an int which is then used in a loop
so - first your creating your loop variable, i, then in your loop you're assigning to it potentially 3 different values 2 of which are negated by the, i++. None of it makes sense and you shouldn't be manipulating your loop variable like that (unless understand what you're doing).
if you move statements around a little..
int itemsToCheck = 10; // "Now I have this repeated about 10 times "
for (var item = 0; item < itemsToCheck; item++)
{
int i;
if (!Int32.TryParse(listView1.SelectedItems[item].SubItems[3].Text, out i))
{
i = 0;
}
i++;
listView1.SelectedItems[item].SubItems[3].Text = i.ToString();
Console.WriteLine(i);
}
Something along those lines is what you're looking for. I haven't changed what your code does with i, just added a loop count itemsToCheck and used a different loop variable so your loop variable and parsed value are not one in the same which will likely be buggy.
Maybe this give you an idea. You can start using this syntax from C# 7.0
var s = listView1.SelectedItems[0].SubItems[3].Text;
var isNumeric = int.TryParse(s, out int n);
if(isNumeric is true && n > 0){
questionNumberLabel.Text = s;
}
to shortcut more
var s = listView1.SelectedItems[0].SubItems[3].Text;
if(int.TryParse(s, out int n) && n > 0){
questionNumberLabel.Text = s;
}

using a textbox to input the data in the scores textbox

Here is the right example
Need to use int data types.
SO, I am able to enter a number and but I get duplicate of a just one number.
Here is what I get on my code:
//create a string for the name
string name = txtName.Text;
// create a int for the number
// have those now have to get three amounts
// for each name then store that
// make a size three array
//innt to put the array in the for loop
int[] x = new int[3];
for (int i = 0; i < x.Length; i++)
{
//txtScore.Text
//txtStoreScores.Text
int covert = Int32.Parse(txtScore.Text);
x[i] = covert;
txtStoreScores.AppendText(x[i].ToString());
// ok I just need one number
// and split them by each number
}
Honestly, though you have selected an answer this feedback may be beneficial to future solutions. Your button once triggered should fire an event, inside that could you want to ensure you properly sanitize user input. Assume the user will cause an error, because the amount of variables they can input are infinite.
protected void btnAddScore_Click(object sender, EventArgs e)
{
if(float.TryParse(txtGrade.Text, out grade) && grade >= 0)
txtScores.Text += $"{grade}, ";
}
That simple conditional will sanitize, by ensuring that the user has entered a valid numeric and the score is higher than zero. Especially since a negative number would be unlikely. The primary point, your code should reflect the usage. Your code should account for those anomalies and variances that may occur.
Another nifty notion, you are outputting directly based on input. When you save that information, you would need to parse the data. So realize that you may need to something along these lines:
var scores = txtScores.Text.Split(','); // An array.
txtScores.Text = String.Join(",", scores); // Converts array into single string
The problem will increase in complexity over time, so be aware of that. Hopefully this was helpful. As for your math, if you do the following it would calculate:
var sum = txtScores.Text.Split(", ").Sum(grade => (float)grade);
The above makes a potentially flawed assumption, that all would cast to a float without an issue. These are items you need to think about. If you do not cast then your sum would be reflected by the length of your string not the values.
if i understand this right!!! you want to append the number from txtScore to txtStoreScores each time you click Add Scores btn!!!!
in this case you don't need a loop, simply put this in Add Scores btn event handler
txtStoreScores.Text += txtScore.Text + " ";
you reaaaaaly need to give more details and a clear question. Good luck!

How to sum only one textbox value and show result in label in c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
The question could be duplicate but my problem is totally different.
I have a one textbox and one label.
Example: label text is already exist with number like 450 Now I want to add number in textbox and the textbox value should be sum in 450 + 30 = 480 where 30 is textbox value.
what I have tried:
lbl_TotalAmount.Text = lbl_TotalAmount.Text + txt_DeliveryCharges.Text;
The above Result is: 45030
Another Code I Have tried:
double total = Convert.ToDouble(lbl_TotalAmount.Text);
double charges = Convert.ToDouble(txt_DeliveryCharges.Text);
double sum = total + charges;
lbl_TotalAmount.Text = String.Format(sum.ToString("0.00"));
The above code is going to sum every value that I put in the textbox and also when I remove one word the number is sum every time.
Please give me best solution I tried many solution to solve this but unable to do this.
Sorry for bad English.
The above code is going to sum every value that I put in the textbox and also when I remove one word the number is sum every time.
That's most likely because you're calling your code inside the TextChanged or the KeyPress events of the textbox; this means that every time you modify anything in your textbox, your code will fire and make the sum.
Instead, add a button and put your code inside its Click event, or if you want the sum to respond to every keypress while respecting your original value, save your value in a variable and use it to calculate the sum.
'Declare a variable at form level
Dim originalValue as Double
'Code where you put your value in a label, put it also in a variable
lbl_TotalAmount.text = 450
originalValue = 450
'Modify your code to use the original value instead of the label
double charges = Convert.ToDouble(txt_DeliveryCharges.Text);
double sum = originalValue + charges;
lbl_TotalAmount.Text = String.Format(sum.ToString("0.00"));
Your strings need to be converted (parsed) to doubles (since they are representing monetary values), but you need to be sure that you're not trying to parse something that can't be converted. TryParse() evaluates to true (or false if the parse fails), so you can avoid a possible exception.
Additionally, you've stated in comments that you want this to update as the text box is updated, so you'll need a variable that is out of scope to keep the total separated from the calculation. I'm going to work from the assumption that this is a shopping cart, or something like that. In that case, a List<> would be an obvious way to store the values of the items in the cart.
Try this:
using System;
using System.Collections.Generic; //required for List<>
namespace WidowsFormsApplication
{
public class ShoppingCart
{
List<double> shoppingCart = new List<double>();
protected void AddItemToCart()
{
shoppingCart.Add(450);
}
protected void UpdateShoppingCart()
{
double total = 0;
foreach (double item in shoppingCart) //calculate total of shoppingCart
{
total += item;
}
if (Double.TryParse(txt_DeliveryCharges.Text, out double charges))
{
total += charges; //add charges without altering shoppingCart
lbl_TotalAmount.Text = String.Format("{0:0.00}", total);
}
}
}
}
lbl_TotalAmount.Text = lbl_TotalAmount.Text + txt_DeliveryCharges.Text;
lbl_TotalAmount.Text and txt_DeliveryCharges.Text are text fields. You cannot do arithmetic on text fields. You have to convert to number, do the arithmetic then convert back
var charge = Int32.Parse(txt_DeliveryCharges.Text);
var total = Int32.Parse(lbl_TotalAmount.Text);
var newTotal = charge + total;
lbl_TotalAmount.Text = newTotal.ToString();
what you are doing is string concatenation
Not a sum of two numbers, You have to convert your strings to int first
here is how you can do that
int x = 0, y = 0;
if (Int32.TryParse(lbl_TotalAmount.Text out x) && Int32.TryParse(txt_DeliveryCharges.Text, out y))
{
// you know that the parsing attempt
// was successful
lbl_TotalAmount.Text = x + y;
}
yourlabel.Text = ""+ (Int32.Parse(yourlabel.Text)+Int.Parse(your textbox.Text));
or
yourlabel.Text = ""+(Double.Parse(yourlabel.Text)+Double.Parse(yourtextbox.Text));
are you using a double? only need that for decimal numbers that are super precise. whole numbers, use int... if you're using it to do money you want to use Decimal, but it depends on the situation.

Comparing a text box's input to a variable

My program requires users to input answers into a text box to randomly generated questions. The questions have calculated answers which are stored in variables. Comparing the text box's input with that variable doesn't work properly, hence why I'm here.
enum elements { lithium, beryllium, sodium, magnesium };
public void Moles()
{
string elementName;
int elementsLength = Enum.GetNames(typeof(elements)).Length;
double moles, mass, roundedMoles, Mr = 0;
Random random = new Random();
elementName = (Enum.GetNames(typeof(elements))[random.Next(0, elementsLength)]);
mass = random.Next(1, 100);
switch (elementName)
{
case "lithium":
Mr = 7;
break;
case "beryllium":
Mr = 9;
break;
case "sodium":
Mr = 23;
break;
case "magnesium":
Mr = 24;
break;
}
moles = mass / Mr;
roundedMoles = Math.Round(moles);
label1.Text = ("How many moles in " + mass + "g" + " of " + elementName + "?");
string input = textBox1.Text.ToString();
if (input == roundedMoles.ToString())
{
MessageBox.Show("Good");
textBox1.Clear();
}
else
{
MessageBox.Show("Bad");
textBox1.Clear();
}
private void button1_Click(object sender, EventArgs e)
{
Moles();
}
As you can see, the program will calculate a number of moles and round it to the nearest whole number. It's then stored in a variable, 'roundedMoles' - this variable is what's compared with the text box's input.
However, the message box will randomly show 'Good' or 'Bad' regardless of whether the input is correct or not. Bear in mind that this code works fine in a console application, so I don't know whether it's something I'm doing wrong or if it just doesn't want to work.
Sorry if this code isn't of a high standard. I'm not that good at programming.
You have two problems.
Don't compare strings as numbers
When comparing numeric values, never compare string to string. Always convert to a numeric variable. Otherwise, "0.00" will not equal "0" and "1234 " (with a space at the end) won't equal "1234" (with no space). Also, you will run into serious trouble if you're working with a culture that uses , as the decimal point.
So, instead of this:
string input = textBox1.Text.ToString();
if (input == roundedMoles.ToString())
{
MessageBox.Show("Good");
textBox1.Clear();
Use something like this:
string input = textBox1.Text;
double inputAsDouble;
bool ok = double.tryParse(out inputAsDouble);
if (!ok)
{
MessageBox.Show("Please enter a numeric value.");
return;
}
if (inputAsDouble == roundedMoles)
{
MessageBox.Show("Good");
textBox1.Clear();
Don't compare floating point values as exact
When comparing floating point values, don't use ==. Instead, compute the difference and make sure it is below a certain tolerance. You have to do this because floating point variables are only approximations.
So instead of
if (inputAsDouble == roundedMoles)
use
const double Tolerance = 0.00001;
if (inputAsDouble - roundedMoles < Tolerance)
Ok so here is the answer...
The reason the console works is that you write to the console to ask the question. You then do console.Readline() this captures the input of the answer after they have seen the question.
On the forms version. You set the label to the question and immediately capture the text box value. The user has not had a chance to enter the answer, or its still the answer from the last time (hence why it randomly goes from "Good" to "Bad" because sometimes the answer is the same).
One simple way is make your variables at the top of the Moles() method, class variables on the form and then have 2 buttons with 2 methods one that gets the questions and sets your answer variables and then a second button then the user can press when they've entered their answer.
Check out this code paste https://www.pastebucket.com/564406
(You'll need button2 added to your form for this to work obviously)
edit: I've done a quick cut and paste of code there. You shouldn't just copy this and use it. Look what I've done and apply it properly and try and understand why it works
It seems that you might have a culture related problem down there. Always be careful when comparing Double values converted to String. The framework might be converting '1,5' to '1.5' depending on your regional settings.
The first thing I would recomend you is not to compare as String but do it as Double. And if you do that, ensure that you will replace dots with comma or other way.
if (Convert.ToDouble(input) == roundedMoles)
{
MessageBox.Show("Good");
textBox1.Clear();
}
else
{
MessageBox.Show("Bad");
textBox1.Clear();
}

C# getting first digit of int in custom class

I am trying to build a help function in my guess the number game, whereby the user gets the first digit of the number he/she has to guess. So if the generated number is 550, he will get the 5.
I have tried a lot of things, maybe one of you has an idea what is wrong?
public partial class Class3
{
public Class3()
{
double test = Convert.ToDouble(globalVariableNumber.number);
while (test > 10)
{
double firstDigit = test / 10;
test = Math.Round(test);
globalVariableNumber.helpMe = Convert.ToString(firstDigit);
}
}
}
Under the helpButton clicked I have:
private void helpButton_Click(object sender, EventArgs e)
{
label3.Text = globalVariableNumber.helpMe;
label3.AutoSize = true;
That is my latest try, I putted all of this in a custom class. In the main I putted the code to show what is in the helpMe string.
If you need more code please tell me
Why not ToString the number and use Substring to get the first character?
var number = 550;
var result = number.ToString().Substring(0, 1);
If for some reason you dont want to use string manipulation you could do this mathematically like this
var number = 550;
var result = Math.Floor(number / Math.Pow(10, Math.Floor(Math.Log10(number))));
What's wrong - you have an infinite while loop there. Math.Round(test) will leave the value of test unchanged after the first iteration.
You may have intended to use firstDigit as the variable controlling the loop.
Anyway, as suggested by others, you can set helpMe to the first digit by converting to a string and using the first character.
As an aside, you should consider supplying the number as a parameter and returning the helpMe string from the method. Your current approach is a little brittle.
The problem with your code is that you are doing the division and storing that in a separate variable, then you round the original value. That means that the original value only changes in the first iteration of the loop (and is only rounded, not divided), and unless that happens to make the loop condition false (i.e. for values between 10 and 10.5), the loop will never end.
Changes:
Use an int intead of a double, that gets you away from a whole bunch of potential precision problems.
Use the >= operator rather than >. If you get the value 10 then you want the loop to go on for another iteration to get a single digit.
You would use Math.Floor instead of Math.Round as you don't want the first digit to be rounded up, i.e. getting the first digit for 460 as 5. However, if you are using an integer then the division truncates the result, so there is no need to do any rounding at all.
Divide the value and store it back into the same variable.
Use the value after the loop, there is no point in updating it while you still have multiple digits in the variable.
Code:
int test = (int)globalVariableNumber.number;
while (test >= 10) {
test = test / 10;
}
globalVariableNumber.helpMe = test.ToString();
By using Math.Round(), in your example, you're rounding 5.5 to 6 (it's the even integer per the documentation). Use Math.Floor instead, this will drop the decimal point but give you the number you're expecting for this test.
i.e.
double test = Convert.ToDouble(globalVariableNumber.number);
while (test > 10)
{
test = Math.Floor(test / 10);
globalVariableNumber.helpMe = Convert.ToString(firstDigit);
}
Like #Sam Greenhalgh mentions, though, returning the first character of the number as a string will be cleaner, quicker and easier.
globalVariableNumber.helpMe = test >= 10
? test.ToString().SubString(0, 1)
: "Hint not possible, number is less than ten"
This assumes that helpMe is a string.
Per our discussion in the comments, you'd be better off doing it like this:
private void helpButton_Click(object sender, EventArgs e)
{
label3.Text = GetHelpText();
label3.AutoSize = true;
}
// Always good practice to name a method that returns something Get...
// Also good practice to give it a descriptive name.
private string GetHelpText()
{
return test >= 10 // The ?: operator just means if the first part is true...
? test.ToString().SubString(0, 1) // use this, otherwise...
: "Hint not possible, number is less than ten" // use this.
}

Categories

Resources