c# scoping issue, simple fix i'm sure - c#

So I have the following code, and It works nearly flawlessly, except for the fact that no matter what I do I cannot get the parts that are like: for (int.parse(txtGuess.Text) == numbGen) it will not recognize 'numbGen' no matter where I place it in the code. I cannot place it inside the button click function because I don't want the number to change, unless they've gotten it correct or re-opened the form.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class rndNum : Form
{
public rndNum()
{
}
private void rndNum_Load(object sender, EventArgs e)
{
int numbGen = RandMake(0, 100);
}
private void txtGuess_TextChanged(object sender, EventArgs e)
{
}
private void btnEval_Click(object sender, EventArgs e)
{
int guesses = 0;
while (txtGuess.Text != "")
{
if (int.Parse(txtGuess.Text) == numbGen)
{
MessageBox.Show("You got it!", "Congratulations!");
break;
}
else if (int.Parse(txtGuess.Text) > numbGen)
{
MessageBox.Show("Sorry, but you're too high. The number was " + numbGen + "!", "Please try again.");
txtGuess.Clear();
txtGuess.Focus();
guesses++;
break;
}
else if (int.Parse(txtGuess.Text) < numbGen)
{
MessageBox.Show("Sorry, but you're too low. The number was " + numbGen + "!", "Please try again.");
txtGuess.Clear();
txtGuess.Focus();
guesses++;
break;
}
}
}
private static int RandMake(int min, int max)
{
Random mkRnd = new Random();
return mkRnd.Next(min, max);
}
}
}

numbGen must be a class member.
Change
private void rndNum_Load(object sender, EventArgs e)
{
int numbGen = RandMake(0, 100);
}
to
private int numbGen;
private void rndNum_Load(object sender, EventArgs e)
{
numbGen = RandMake(0, 100);
}
actually you don't need to put the initialization in Form.Load, you can initialize a class member directly.
public partial class rndNum : Form
{
private int numbGen = RandMake(0, 100);
public rndNum()
{
}
and to further refine: if you want to make sure the values is not changed you can make it readonly
public partial class rndNum : Form
{
private readonly int numbGen = RandMake(0, 100);
public rndNum()
{
}

int numbGen;
private void rndNum_Load(object sender, EventArgs e)
{
numbGen = RandMake(0, 100);
}
try this!!!

The others already commented on the scoping issue you noticed. But your RandMake method is flawed too. You should not create an instance of Random for each number, but reuse the instance.
The problem here is that new Random() uses the time as seed, and the time only changes every few milliseconds. This means that if you call RandMake several times within that time interval you will get the same "random" number.
This doesn't seem to be a immediate problem because you only call it once, but you should be aware of this in the future.

When you put numbGen's declaration on the inside of a method, the number only exist in that functions scope. You have to place it outside like this:
int numbGen;
private void rndNum_Load(object sender, EventArgs e)
{
numbGen = RandMake(0, 100);
}

Related

Need help pulling an int from an array in c#

namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
int[] codes = { 39835, 72835, 49162, 29585, 12653, 87350, 74783};
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{}
private void label4_Click(object sender, EventArgs e)
{}
private void btnRandom_Click(object sender, EventArgs e)
{
Random mRandom = new Random();
int randcode = mRandom.Next(0, codes.Length - 1);
}
}
}
I want to pull a random code from the array by clicking "btnRandom" and compare it to a string but "int randcode" always comes up as an error when i try it.
private void button1_Click(object sender, EventArgs e)
{
if (txtCode.Text == randcode) ;
{
MessageBox.Show("working");
}
}
Trying to get it to work like this.
You have a few problems:
Your codes array contains integers. Your textbox contains a string.
You are not actually accessing the array when you do the compare - you're comparing an integer index to a string.
You have a semicolon after your if statement that shouldn't be there.
randcode is not defined at the class level, so you can't access it from a different function than the one it was declared in.
In short, you want something like this:
int randcode;
private void btnRandom_Click(object sender, EventArgs e)
{
Random mRandom = new Random();
randcode = mRandom.Next(0, codes.Length - 1);
}
private void button1_Click(object sender, EventArgs e)
{
if (txtCode.Text == codes[randcode].ToString())
{
MessageBox.Show("working");
}
}
You have either to parse txtCode.Text to integer or convert randCode to string:
if (int.Parse(txtCode.Text) == randcode) ...
or
if (txtCode.Text == randcode.ToString()) ....
But there are some things you can/must fix:
In Random.Next(min, max) method, max is exclusive, so the call must be like this:
int randcode = mRandom.Next(0, codes.Length);
You are declaring ranCode inside btnRandom_Click(), and must be in Form1 class:
public partial class Form1 : Form
{
int randCode;
int[] codes = { 39835, 72835, 49162, 29585, 12653, 87350, 74783};
....
randcode = mRandom.Next(0, codes.Length);
And you have a ; after the if statement, so MessageBox.Show("working"); will be executed no matter the result.
Finally the code should be like this:
public partial class Form1 : Form
{
int randCode;
int[] codes = { 39835, 72835, 49162, 29585, 12653, 87350, 74783};
...
private void btnRandom_Click(object sender, EventArgs e)
{
Random mRandom = new Random();
randcode = mRandom.Next(0, codes.Length);
}
...
private void button1_Click(object sender, EventArgs e)
{
if (int.Parse(txtCode.Text) == randcode)
{
MessageBox.Show("working");
}
}
...
}
thats because txtCode.Text is a string and randcode is an integer. YOu cant compare these two. They must both be strings or ints. Try this
if(txtCode.Text == randcode.ToString())
I also note that int randcode is not in scope in this method. You meed to mkae randcode a member variable by declaring it at class scope

Trouble with random number guessing game in c#

So I am working on a project for school that in a guessing game for a randomly generated number between 1-100. The only trouble I am having at the moment is that every time the user enters a new number the generated number also changes. I tried putting the code to generate the number in the form loader but then I can't access it later in the program. Here's what I have so far.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void guessButton_Click(object sender, EventArgs e)
{
int userGuess;
userGuess = int.Parse(guessText.Text);
Random rand = new Random();
int number = rand.Next(1, 100);
label2.Text = "" + number;
if (userGuess > number)
{
resultLabel.Text = "Your guess is too high";
}
else if (userGuess < number)
{
resultLabel.Text = "Your guess is too low.";
}
else if (userGuess == number)
{
resultLabel.Text = "That is correct!";
}
guessText.Clear();
}
private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
As it currently stands, the Random number is overwritten every time the guessButton_Click function is run.
You are declaring Random inside the guessButton_Click function, that is called every time the guess button is clicked (that's also a memory leak!).
To fix, declare it as a global variable, in the namespace:
Edit: The below code compiles properly, and works perfectly.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
int number = new Random().Next(1, 100);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void guessButton_Click(object sender, EventArgs e)
{
int userGuess;
userGuess = int.Parse(guessText.Text);
label2.Text = "" + number;
if (userGuess > number)
{
resultLabel.Text = "Your guess is too high";
}
else if (userGuess < number)
{
resultLabel.Text = "Your guess is too low.";
}
else if (userGuess == number)
{
resultLabel.Text = "That is correct!";
}
guessText.Clear();
}
private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
You are getting a new random number every button click try the following:
public partial class Form1 : Form
{
Random rand;
int number;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
rand = new Random();
number = rand.Next(1, 100);
}
private void guessButton_Click(object sender, EventArgs e)
{
int userGuess;
userGuess = int.Parse(guessText.Text);
label2.Text = "" + number;
if (userGuess > number)
{
resultLabel.Text = "Your guess is too high";
}
else if (userGuess < number)
{
resultLabel.Text = "Your guess is too low.";
}
else if (userGuess == number)
{
resultLabel.Text = "That is correct!";
}
guessText.Clear();
}
}

Catch exception and reset windows form C#

I'm currently working on my first assignment using windows forms in visual studio and have been a little stuck.
I'm trying to test if a user input is numeric, and if the input is not numeric, a little message box pops up and alerts the user. (I've done this part). The issue I'm having is the and error continues to pop in visual studio
Is this a formatting issue? Should I reformat my code? As you can probably see I am new the C# (and programming).
My code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace wtgCalculator {
public partial class Form1 : Form {
const double maleratio = 0.536;
const double femaleratio = 0.492;
public Form1() {
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e) {
}
private void Form1_Load(object sender, EventArgs e) {
}
private void label1_Click(object sender, EventArgs e) {
}
private void textBox1_TextChanged_1(object sender, EventArgs e) {
}
private void WaistNumericCheck() {
double waist;
string inpwaist = heighttextbox.Text;
if (double.TryParse(inpwaist, out waist)) {
MessageBox.Show("Value must be numeric"); //this is where the problem is
}
}
private void HeightNumericCheck() {
//todo
}
private void button1_Click(object sender, EventArgs e) {
//record inputs to variables
WaistNumericCheck();
HeightNumericCheck();
double height = double.Parse(heighttextbox.Text);
double waist = double.Parse(waisttextbox.Text);
//check is inputs are within boundry
CheckDimensions(height, waist);
//test
// ShowResult(height, waist);
}
private void CheckLimits(double height, double waist) {
double result = CalculateRatio(height, waist);
if (Female.Checked) {
if (result < femaleratio) {
MessageBox.Show("Your risk of obesity related cardiovasular is low");
}
if (result > femaleratio) {
MessageBox.Show("Your risk of obesity related to cardiovascular is high");
}
}
if (Male.Checked) {
if (result < maleratio) {
MessageBox.Show("Your risk of obesity related cardiovasular is low");
}
if (result > maleratio) {
MessageBox.Show("Your risk of obesity related cardiovasular is High");
}
}
//testing
MessageBox.Show(result.ToString());
}
private void ShowResult(double height, double waist) {
//double result = CalculateRatio(height, waist);
//if (Female.Checked) {
// if (result < femaleratio) {
// MessageBox.Show("Your risk of obesity related cardiovasular is low");
// }
// if (result > femaleratio) {
// MessageBox.Show("Your risk of obesity related to cardiovascular is high");
// }
//}
//if (Male.Checked) {
//}
}
private static void CheckDimensions(double height, double waist) {
if (height <= 120) {
MessageBox.Show("Height must be greater than 120cm");
}
if (waist <= 60) {
MessageBox.Show("Waist must be greater than 60cm");
}
}
private void Gender_CheckedChanged(object sender, EventArgs e) {
button1.Enabled = true;
}
private static double CalculateRatio(double height, double waist) {
double finalratio = waist / height;
return finalratio;
}
}
}
Thanks again, and let me know if more information is required.
You're not really handling this correctly. .Parse() is supposed to throw an exception if the value cannot be converted. The whole point of .TryParse() is to avoid that. So, your methods need to be cleaned up and edited to actually accomplish something:
private bool WaistNumericCheck(out double waist)
{
bool canParse = double.TryParse(heighttextbox.Text, out waist);
if ( !canParse ) {
MessageBox.Show("Value must be numeric");
}
return canParse;
}
private bool HeightNumericCheck(out double height)
{
// todo -> same pattern as above
}
private void button1_Click(object sender, EventArgs e)
{
double height = 0, waist = 0;
if( WaistNumericCheck(waist) && HeightNumericCheck(height) )
{
CheckDimensions(height, waist);
/* ... the rest of your code */
}
}
This modifies your test methods to return a true/false based on whether the parse was successful, and outs your parsed variables so that you don't have to parse them again.
I suggest at some point that you review the MSDN documentation: http://msdn.microsoft.com/en-us/library/994c0zb1%28v=vs.110%29.aspx

Trying to load multiple tables on a single page using VIEWSTATE in c#

I Have got this method to work for single pages on a project that I am working on. The problem is that when there are multiple tables that need to be changed dynamically, the logic becomes very complex.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Part_9 : System.Web.UI.Page
{
private const string VIEWSTATEKEY1 = "ContactCount";
private const string VIEWSTATEKEY2 = "ContactCount";
private const string VIEWSTATEKEY3 = "ContactCount";
private const string VIEWSTATEKEY4 = "ContactCount";
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//Set the number of default controls
ViewState[VIEWSTATEKEY1] = ViewState[VIEWSTATEKEY1] == null ? 1 : ViewState[VIEWSTATEKEY1];
ViewState[VIEWSTATEKEY2] = ViewState[VIEWSTATEKEY2] == null ? 1 : ViewState[VIEWSTATEKEY2];
ViewState[VIEWSTATEKEY3] = ViewState[VIEWSTATEKEY3] == null ? 1 : ViewState[VIEWSTATEKEY3];
ViewState[VIEWSTATEKEY4] = ViewState[VIEWSTATEKEY4] == null ? 1 : ViewState[VIEWSTATEKEY4];
//Load the contact control based on Vewstate key
LoadPageControls1();
LoadPageControls2();
LoadPageControls3();
LoadPageControls4();
}
}
private void LoadPageControls1()
{
for (int i = 0; i < int.Parse(ViewState[VIEWSTATEKEY1].ToString()); i++)
{
Part9Table1.Controls.Add(LoadControl("~/UserControlPart9Table1.ascx"));
}
Part9Table2.Controls.Add(LoadControl("~/UserControlPart9Table2.ascx"));
Part9Table3.Controls.Add(LoadControl("~/UserControlPart9Table3.ascx"));
Part9Table4.Controls.Add(LoadControl("~/UserControlPart9Table4.ascx"));
}
private void LoadPageControls2()
{
for (int i = 0; i < int.Parse(ViewState[VIEWSTATEKEY2].ToString()); i++)
{
Part9Table2.Controls.Add(LoadControl("~/UserControlPart9Table2.ascx"));
}
Part9Table1.Controls.Add(LoadControl("~/UserControlPart9Table1.ascx"));
Part9Table3.Controls.Add(LoadControl("~/UserControlPart9Table3.ascx"));
Part9Table4.Controls.Add(LoadControl("~/UserControlPart9Table4.ascx"));
}
private void LoadPageControls3()
{
for (int i = 0; i < int.Parse(ViewState[VIEWSTATEKEY3].ToString()); i++)
{
Part9Table3.Controls.Add(LoadControl("~/UserControlPart9Table3.ascx"));
}
Part9Table1.Controls.Add(LoadControl("~/UserControlPart9Table1.ascx"));
Part9Table2.Controls.Add(LoadControl("~/UserControlPart9Table2.ascx"));
Part9Table4.Controls.Add(LoadControl("~/UserControlPart9Table4.ascx"));
}
private void LoadPageControls4()
{
for (int i = 0; i < int.Parse(ViewState[VIEWSTATEKEY4].ToString()); i++)
{
Part9Table4.Controls.Add(LoadControl("~/UserControlPart9Table4.ascx"));
}
Part9Table1.Controls.Add(LoadControl("~/UserControlPart9Table1.ascx"));
Part9Table2.Controls.Add(LoadControl("~/UserControlPart9Table2.ascx"));
Part9Table3.Controls.Add(LoadControl("~/UserControlPart9Table3.ascx"));
}
protected void Unnamed2_Click(object sender, EventArgs e)
{
Response.Redirect("Part 10.aspx");
}
protected void Unnamed1_Click(object sender, EventArgs e)
{
Response.Redirect("Part 8.aspx");
}
protected void Unnamed3_Click(object sender, EventArgs e)
{
ViewState[VIEWSTATEKEY1] = int.Parse(ViewState[VIEWSTATEKEY1].ToString()) + 1;
LoadPageControls1();
}
protected void Unnamed4_Click(object sender, EventArgs e)
{
ViewState[VIEWSTATEKEY2] = int.Parse(ViewState[VIEWSTATEKEY2].ToString()) + 1;
LoadPageControls2();
}
protected void Unnamed5_Click(object sender, EventArgs e)
{
ViewState[VIEWSTATEKEY3] = int.Parse(ViewState[VIEWSTATEKEY3].ToString()) + 1;
LoadPageControls3();
}
protected void Unnamed6_Click(object sender, EventArgs e)
{
ViewState[VIEWSTATEKEY4] = int.Parse(ViewState[VIEWSTATEKEY4].ToString()) + 1;
LoadPageControls4();
}
}
}
As you can see here. when the page loads up the content, it will load 4 new rows in each table because there are 4 load content methods. But when I click on one of the buttons, it will correct itself and add the extra row that you want to the table you selected and resetting the rest of the tables to one row. However, if I then click on another button, it will add a row to it, plus the previous rows added and reset all the other tables to one which means that there is a variable counting the number of rows for each table collectively instead of individually.
Any help here would be much appreciated.

Why is a variable not recognized in an event handler?

I have two issues with this piece of code. I 'm having trouble because the submit button event doesn't recognize the variable calculated in the text box event, and because the text box event isn't recognizing my if statements as statements. You can see where I'm having trouble in the comments below.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication11
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int points;
int userInput = int.Parse(textBox1.Text);
if (userInput == 0)
{
points == 5; //I CANNOT COMPILE BECAUSE APPARENTLY I AM NOT ALLOWED TO USE
THIS AS A STATEMENT?
}
if (userInput == 1)
{
points == 10;
}
if (userInput == 2)
{
points == 20;
}
if (userInput ==3)
{
points == 30;
}
else
{
points == 40;
}
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show = ("You have been awarded" + textBox1.points + "points");
} //I WANT TO BE ABLE TO RETRIEVE THE POINTS CALCULATED USING THE CALCULATION IN
TEXT BOX, BUT I CANNOT COMPILE THE BUTTON EVENT DOES NOT RECOGNIZE THE POINTS
VARIABLE
private void label1_Click(object sender, EventArgs e)
{
}
}
}
The == symbol is a comparison symbol not an assignment symbol
You need to use
if (userInput == 2) // this is a comparison
{
points = 20; // this is an assignment
}
First you have declared points local to the TextChanged event, so it won't be accessible in your button click event.
textBox1.points is not right since int points declaration has nothing to do with the TextBox, you may declare points as a class variable, something like
public partial class Form1 : Form
{
int points =0;
public Form1()
{
InitializeComponent();
}
//......//
this would then work out as
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show( string.Format("You have been awarded {0} points",this.points));
}
Also you do assignment using = sign, so points = 5; would be the right thing to do
To add value to variable you should write:
points = 5;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication11
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public int points=0;
private void Form1_Load(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int userInput = int.Parse(textBox1.Text);
if (userInput == 0)
{
points = 5;
}
if (userInput == 1)
{
points = 10;
}
if (userInput == 2)
{
points = 20;
}
if (userInput ==3)
{
points = 30;
}
else
{
points = 40;
}
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show = ("You have been awarded" + points.ToString() + "points");
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
As already stated - you confussed with assignment operator and with global/local variables.
But there is several other "errors" in your code. User input might be simple text - so there will be exception, you should use int.TryParse instead of int.Parse. Also there are plenty of ifs in your code - but they cannot fire all together, I recomend use switch. And of course you should try to name your constants somehow, it will make your code much more readable!
Overral your code might look like this:
int pointsAvarded = 0;
private void textBox1_TextChanged(object sender, EventArgs e)
{
pointsAvarded = 0; //so you can be sure to use the latest input
int userInput = 0;
if (int.TryParse(textBox1.Text, out userInput))
switch (userInput)
{
case 0:
points = 5;
break;
case 1:
points = 10;
break;
...
default:
points = 40;
break;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (pointsAvarded != 0)
MessageBox.Show("You have been awarded" + pointsAvarded + "points");
}

Categories