Improving number guessing game code - c#

I'm trying to make a small guessing game where it generates a random number, and the user enters in a number using a TextBox and Button. Currently it is creating the random number and doing everything I want, but every time the user presses submit on the button, it generates a new random number for them to guess
I am very new to ASP.NET type stuff, so my code is probably inefficient and incorrect lol, so I have two particular questions.
How can I improve my code to make it work better/work at all.
Do I need a runner class to make it work, and how would I do so?
public partial class WebPageSeparated : System.Web.UI.Page
{
private int randNum;
private int theirGuess;
public WebPageSeparated()
{
Random randomNum = new Random();
randNum = randomNum.Next(0, 10);
theirGuess = 0;
}
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "Guessing game! Guess a number between [0,10) to see if you can get it right!";
new WebPageSeparated();
}
protected void Button1_Click(object sender, EventArgs e)
{
try
{
theirGuess = Convert.ToInt32(TextBox1.Text);
if (theirGuess != this.randNum)
{
Label1.Text = "Sorry, wrong number. Please try again!";
}
else if(theirGuess == this.randNum)
{
Label1.Text = "Correct! A new number has been generated, go ahead and try to do it again!";
new WebPageSeparated();
}
}
catch (System.FormatException)
{
Label1.Text = "Enter a number [1,10)";
}
}
}

Several things are wrong with your code:
You should never create a new instance of your page (new WebPageSeparated()). A new instance is created every time you navigate to the page (by entering its URL in the browser) and whenever you cause a PostBack (e.g. by clicking an asp:button).
If you want to have some code, which runs only the first time the page is invoked (i.e. not during a PostBack, only when navigating to the page), then you should wrap that code in a if (!IsPostBack) {} block.
Because a new instance of the page is created for each PostBack, you cannot store any state (the random number) in an instance-field of the page. You have to find another place where you store the state, e.g:
in a static field, e.g: private static int randNum
note: this is not recommended, since the static field is shared between all instances of your page (doesn't work if multiple users are on your website at the same time)
in a session variable, e.g. Session["randNum"] = randomNum.Next(0, 10)
in the ViewState of the page, e.g. ViewState["randNum"] = ...
this is what I'd recommend for your sample
in a database
With all these points in mind, your Page_Load method would look something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Random randomNum = new Random();
randNum = randomNum.Next(0, 10);
ViewState["randNum"] = randNum;
}
else
{
randNum = (int) ViewState["randNum"];
}
Label1.Text = "Guessing game! Guess a number between [0,10) to see if you can get it right!";
}
Also, in the case, the user guesses the correct number, you should generate and store a new random number (as done inside the if (!IsPostBack)).
Finally, some topics you might want to read more about: Page Lifecycle, PostBack, Viewstate, Session-state

The reason is asp.net postback all the data to server for every action performed in the browser. Since you are generating a random number in the constructor your facing this issue. I guesss this will help you.
public partial class WebPageSeparated : System.Web.UI.Page
{
private int randNum;
private int theirGuess;
protected void Page_Load(object sender, EventArgs e)
{
Random randomNum = new Random();
randNum = randomNum.Next(0, 10);
theirGuess = 0;
Label1.Text = "Guessing game! Guess a number between [0,10) to see if you can get it right!";
new WebPageSeparated();
}
protected void Button1_Click(object sender, EventArgs e)
{
try
{
theirGuess = Convert.ToInt32(TextBox1.Text);
if (theirGuess != this.randNum)
{
Label1.Text = "Sorry, wrong number. Please try again!";
}
else if(theirGuess == this.randNum)
{
Label1.Text = "Correct! A new number has been generated, go ahead and try to do it again!";
new WebPageSeparated();
}
}
catch (System.FormatException)
{
Label1.Text = "Enter a number [1,10)";
}
}

Related

new to programing trying to make a number guessing game in c#

Hi so I am new to programing I just started school and I wanted to get a head start on programing so please keep in mind that everything I show you is all self-taught. Here is my question I wanted to make a random number guessing game and for the most part it works but every time you click the button to guess it randoms a different number which I don’t want here is what I have so far
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// number of guesses
int numberOfGesses = 0;
private void btnCalc_Click(object sender, EventArgs e)
{
// make the generator
Random generator = new Random();
//make the number
int number = generator.Next(1, 10);
// get the users guess
int guess = int.Parse(txtInput.Text);
//check the users guess
if (guess == number)
{
lblAnswer.Text = "You got it";
numberOfGesses = 0;
}
else if (guess != number)
{
numberOfGesses = numberOfGesses + 1;
lblAnswer.Text = "try agian you have gessed" + (numberOfGesses) + " times";
}
}
}
I know it keeps creating a new number because every time I press the guess button it starts from the top and makes a new number. I tried to take this block and make it global but I got an error
// make the generator
Random generator = new Random();
//make the number
int number = generator.Next(1, 10);
again im realy new and i found this site when lookinging up some qeustions i had so i thought it would be a good place to help me learn about programing while i wait till i can get into the programing classes thank you for your time.
You likely got an error because C# doesn't allow you to assign a default value of a field based on another field.
public partial class Form1 : Form {
int numberOfGuess = 0;
Random generator = new Random();
int number;
// other methods
}
generator can be initialized before or after number, hence the error. Instead, you can put it in the form intializer (Form1 method), or make another button and click it and generate a new random number:
public partial class Form1 : Form
{
// number of guesses
int numberOfGesses = 0;
Random generator = new Random();
int number;
public Form1()
{
InitializeComponent();
// Generate the random number
number = generator.Next(1, 10);
}
private void btnRandom_Click(object sender, EventArgs e)
{
// Generate a new random number when you click a button on the form
number = generator.Next(1, 10);
}
private void btnCalc_Click(object sender, EventArgs e)
{
// get the users guess
int guess = int.Parse(txtInput.Text);
//check the users guess
if (guess == number)
{
lblAnswer.Text = "You got it";
numberOfGesses = 0;
}
else if (guess != number)
{
numberOfGesses = numberOfGesses + 1;
lblAnswer.Text = "try agian you have gessed" + (numberOfGesses) + " times";
}
}
}
You cannot use an instance variable to initialize another instance variable. Why? Because the compiler can rearrange these - there is no guarantee that generator will be initialized before number, so the above line might throw a NullReferenceException.
So change the default number value to 0:
Random generator = new Random();
int number = 0;
Initialise in the constructor:
public Form1()
{
InitializeComponent();
number = generator.Next(1, 10);
}
When the button is clicked generate the number since here you will be needing it:
private void btnCalc_Click(object sender, EventArgs e)
{
//take the input & Compare as before.
}

Displaying random line from text file in text box code error

I am building a program that on a button click displays a random line from a text file into a text box.
I am only a beginner at C# so I am not sure where I have gone wrong.
private void startButton_Click(object sender, EventArgs e)
{
int lineCount = File.ReadAllLines(#"D:...\QUESTIONS.text").Length;
Random rnd = new Random();
int randomLineNum = rnd.Next(lineCount);
int indicator = 0;
using (var reader = File.OpenText(#"D:...\QUESTIONS.text"))
{
while (reader.ReadLine() != null)
{
if (indicator == randomLineNum)
{
questionBox.Text = reader;
break;
}
indicator++;
}
}
}
Can you also help me figure out where this code is supposed to go.
Thank you for your help in advance! : )
you can remove many complexities in your code.
private Random r = new Random();
private void startButton_Click(object sender, EventArgs e)
{
var lines = File.ReadAllLines(#"D:...\QUESTIONS.text");
questionBox.Text = lines[r.Next(lines.Length)];
}
defining a random variable outside the function scope and reuse it
every time is a known best practice.
why reading the file twice? you are reading it once with ReadAllLines and then again with an StreamReader
This should do it:
private void startButton_Click(object sender, EventArgs e)
{
var lines = File.ReadAllLines(#"D:...\QUESTIONS.text");
int lineCount = lines.Length;
Random rnd = new Random();
int randomLineNum = rnd.Next(lineCount);
questionBox.Text = lines[randomLineNum];
}
There is no need to read the same file twice, so keep the lines in a local variable to access it later.

counter for attempts in c#

I am trying to get the counter named "Guesses" to keep a tally of attempts at guessing a random number and output the total attempts at guessing the number. I have tried leaving the counter declaration at 0 and 1 and the number of attempts to guess is always 0 or 1. Help would be appreciated and I will re-post entire working code once it's figured out. Here is my code.
int Answer; // declares the Answer variable outside button event
public frmGuess()
{ // generates random number outside button event so does not change on button click
InitializeComponent();
Random rand = new Random();
Answer = rand.Next(100) + 1; // makes it range 1 to 100
}
private void btnGuess_Click(object sender, EventArgs e)
{
int UserGuess;
int Guesses = 0; // start counter
if (string.IsNullOrEmpty(txtGuess.Text)) // input validation check to make sure not blank and is a whole number integer
{
MessageBox.Show("Please enter a whole number between 1 and 100");
return;
}
else
{
UserGuess = int.Parse(txtGuess.Text); // variable assign and code run
Guesses ++;
if (UserGuess > Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too high, try again.";
}
else if (UserGuess < Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too low, try again.";
}
else
{
lblAnswer.Text = "Congratulations the answer was " + Answer + "!\nYou guessed the number in " + Guesses + " tries.\nTo play again click the clear button."; //victory statement
}//end if
} //end if
}
private void btnClear_Click(object sender, EventArgs e) // clears Answer label and Guess textbox
{
txtGuess.Text = "";
lblAnswer.Text = "";
}
private void btnExit_Click(object sender, EventArgs e) // closes window
{
this.Close();
}
}
}`
Yes indeed! That took care of it. To think I placed the random number outside the button click but didn't do it to the counter - foolishness. Thanks all! Working code is :
{
int Answer; // declares the Answer variable outside button event
int Guesses = 0; // declares counter outside button event
public frmGuess()
{ // generates random number outside button event so does not change on button click
InitializeComponent();
Random rand = new Random();
Answer = rand.Next(100) + 1; // makes it range 1 to 100
}
private void btnGuess_Click(object sender, EventArgs e)
{
int UserGuess;
if (string.IsNullOrEmpty(txtGuess.Text)) // input validation check to make sure not blank and is a whole number integer
{
MessageBox.Show("Please enter a whole number between 1 and 100");
return;
}
else
{
UserGuess = int.Parse(txtGuess.Text); // variable assign and code run
Guesses ++; // adds 1 to attempts but doesn't count textbox blank or mistyping
if (UserGuess > Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too high, try again.";
Guesses++;
}
else if (UserGuess < Answer)
{
txtGuess.Text = "";
lblAnswer.Text = "Too low, try again.";
Guesses++;
}
else
{
lblAnswer.Text = "Congratulations the answer was " + Answer + "!\nYou guessed the number in " + Guesses + " tries.\nTo play again click the clear button.";
}//end if
} //end if
}
private void btnClear_Click(object sender, EventArgs e) // clears Answer label and Guess textbox
{
txtGuess.Text = "";
lblAnswer.Text = "";
}
private void btnExit_Click(object sender, EventArgs e) // closes window
{
this.Close();
}
}
}
`
You are resetting the counter in your click event.
int Answer; // declares the Answer variable outside button event
int Guesses = 0; // declare this outside button event, and initialize it to 0.
// initialization will happen when the Form object is created.
...
private void btnGuess_Click(object sender, EventArgs e)
{
int UserGuess;
// DO NOT reset the counter here. This line is the culprit that
// resets the counter every time you click the button
//int Guesses = 0; // start counter
...
}
...
It's a scoping issue. You currently define guesses within your event handler where it resets the counter with each button click. If you define it at the form level, even as a property or member variable, that scope will allow the variable to retain its value through multiple button click events.

asp.net submit process

i have a form with 2 labels initializing random numbers and a text box to check if the answer is correct after adding the two random numbers. The problem i am having is SUBMIT processes the next set of random numbers and so the result is always incorrect. here is the code i have so far.
namespace _2ndGradeMath
{
public partial class Default : System.Web.UI.Page
{
Random random = new Random();
protected void Page_Load(object sender, EventArgs e)
{
lblNum1.Text = random.Next(0, 10).ToString();
lblNum3.Text = random.Next(0, 10).ToString();
int num1 = int.Parse(lblNum1.Text);
int num2 = int.Parse(lblNum3.Text);
lblAnswer.Text = (num1 + num2).ToString();
lblAnswer.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (TextBox1.Text != lblAnswer.Text)
{
Button1.Attributes.Add("onClick", "javascript:alert('Incorrect');");
}
else if (TextBox1.Text == lblAnswer.Text)
{
Button1.Attributes.Add("onClick", "javascript:alert('Correct');");
}
TextBox1.Text = "";
}
}
}
Use IsPostBack to only run the initializing code when the page is initially loaded:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
lblNum1.Text = random.Next(0, 10).ToString();
lblNum3.Text = random.Next(0, 10).ToString();
int num1 = int.Parse(lblNum1.Text);
int num2 = int.Parse(lblNum3.Text);
lblAnswer.Text = (num1 + num2).ToString();
lblAnswer.Visible = false;
}
}
Here's the problem. You are loading new random numbers each time the page loads. That's what the Page_Load function does: it runs each time the page loads which includes every time the page is submitted. So when a user presses submit new random numbers are assigned, which makes his answer wrong. You need to assign random numbers in only two instances:
First, when the page loads for the first time. Which can be done by checking the property IsPostBackis false.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack){
lblNum1.Text = random.Next(0, 10).ToString();
lblNum3.Text = random.Next(0, 10).ToString();
}
.
.
.
}
Second, when the user answers correctly.
else if (TextBox1.Text == lblAnswer.Text)
{
Button1.Attributes.Add("onClick", "javascript:alert('Correct');");
lblNum1.Text = random.Next(0, 10).ToString();
lblNum3.Text = random.Next(0, 10).ToString();
}
Consider adding this code to PreRender:
protected override void OnPreRender(EventArgs e)
{
Session["Answer"] = lblAnswer.Text;
base.OnPreRender(e);
}
and then in the Click grab the answer from Session like this:
if (TextBox1.Text != Session["Answer"])
and bear in mind I'm assuming that you actually want to generate new numbers on every post back with this answer.

random numbers on Page_Load

I am creating a simple game where the computer generates random numbers and adds them up. The rule is that while the addition of both random numbers is < 17, generate another random number and add it to the previously generated. The computer also generates a random number for the user. However, the user decides whether he wants to generate more or not. In case he wants, the newly generated number is added to the previous ones.
The problem I am facing is that, the computer function of generating his random numbers is in the Page_Load event. This is leading to a problem; meaning that when the user has his random number displayed, lets say he decides to generate another one. In a Button_Click event, the user presses "Generate" button and has his newly random number. The problem in that is whenever the button is pressed, the page refreshes and the computer random numbers are changed since the method is in the page_load event.
How can I make the computer generate a random number, store it, without being effected by other events on the page. Also, how can I add the newly generated random number for the user to the previously generated ones?
This is the code:
int computer_first_number;
int computer_second_number;
int extra_number;
int computer_total;
int user_number1;
int user_number2;
int user_total;
private int randomNumber(int min, int max)
{
Random random = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0));
return random.Next(min, max);
}
protected void Page_Load(object sender, EventArgs e)
{
computer_first_number = randomNumber(1, 10);
computer_second_number = randomNumber(1, 10);
user_number1 = randomNumber(1, 10);
computer_total = computer_first_number + computer_second_number;
while (computer_total < 17)
{
try
{
extra_number = randomNumber(1, 10);
computer_total = computer_first_number + computer_second_number + extra_number;
}
catch (Exception ex)
{
Console.Write(ex);
}
}
}
protected void Button1_Click1(object sender, EventArgs e)
{
user_number2 = randomNumber(1, 10);
user_total = user_number1 + user_number2;
Label4.Text = Convert.ToString(user_total);
}
Store the value of random Number in ViewState (like ViewState["RandNum"] = random number. And in the pageload check if Page is postback (like Page.IsPostback). Something like;
private int randomNumber(int min, int max)
{
Random random = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0));
return random.Next(min, max);
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
int number = randomNumber(1, 10) + randomNumber(1, 10);
while (number < 17)
{
number += randomNumber(1, 10);
}
ViewState["RandNum"] = number;
}
Label4.Text = ViewState["RandNum"].ToString();
}
protected void Button1_Click1(object sender, EventArgs e)
{
int userNumber = randomNumber(1, 10);
userNumber = int.Parse(ViewState["RandNum"].ToString()) + userNumber;
ViewState["RandNum"] = userNumber;
Label4.Text = Convert.ToString(userNumber);
}
Please separate your questions with numbers, you need the session for this.
Session["randomNumber"] = computer_first_number;
computer_first_number = (int)Session["randomNumber"];
You can store any object the session, so use a List or Queue to store multiple numbers for a user.
Edit: like daryal said, always store the numbers, then if it's from a Postback, you know the numbers are stored. Even then session only lasts for 20 minutes (normally) so its always good to check if the objects are actually present in the Session.
Store the number. ASP.NET provides several options for persisting data within an application. Take a look at ASP.NET State Management Recommendations, specifically the "Server-Side State Management Options" section.
First, your Page_Load needs to have a IsPostback check in it:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostback){
computer_first_number = randomNumber(1, 10);
computer_second_number = randomNumber(1, 10);
user_number1 = randomNumber(1, 10);
... //keep your normal processing
//at the end, put your total in a hidden field
hidFieldRandomTotal.Value = computer_total;
} else {
//here's where you'd add on a new random number
int newRandomNumber = randomNumber(1,10);
computer_total = Convert.ToInt32(hidFieldRandomTotal.Value);
//add it to the total
hidfieldRandomTotal.Value = newRandomNumber + computer_total;
}
}
You need a way to preserve state between loading your page initially, and when the user posts data back. There are a number of ways to do this. What I'm showing above is pretty simple and not very elegant, but it's a start. You essentially have to know when you're initially loading the page (IsPostback == false) and when you're updating it (IsPostback == true).

Categories

Resources