How to make loop wait until button is clicked - c#

I'm working on a mathematical game that gives 10 different adding questions one by one. Those questions are displayed on the label and you can answer it by writing into a text box and clicking submit. I'm stuck with answering part, particularly with loop waiting until I press a button.
From looking it up, I found a method to make it as a new event, but I didn't get how I can make my loop wait for that event to continue
My code looks like this
int Between = 1;
Random rnd = new Random();
for (int i = 0; i < 10; i++)
{
if (Between == 1)
{
int num1 = rnd.Next(1, 11); // 1-10
int num2 = rnd.Next(1, 11); // 1-10
string number1 = num1.ToString();
string number2 = num2.ToString();
kusimus.Text = number1 + " + " + number2;
}
I need to add waiting after kusimus.Text = number1 + " + " + number2;. Reading the text box isn't yet added cause it wouldn't have use without button, so it aint included. "between" ain't completed eiter, so that's why i have if with int of it right before it

If you want to ask a total of 10 questions, one at a time, you don't need to use a loop and wait within it. You can simply use the button click event to check the answer and update the question label.
Move Between and rnd to be class members, so you can access them in multiple methods. Alongside these, create two integers to store the current correct answer, and how many questions have been asked.
For my answer, I used these names:
private int Between = 1;
private Random rnd = new Random();
private int questionsAsked = 0;
private int currentAnswer = 0;
Update the label for the first question in the form's constructor, like so.
public Form1()
{
InitializeComponent();
// Get two random numbers
int num1 = rnd.Next(1, 11); // 1-10
int num2 = rnd.Next(1, 11); // 1-10
// Save the answer.
currentAnswer = num1 + num2;
// Update the label.
kusimus.Text = String.Format("{0} + {1}", num1, num2);
// Keep track of how many questions have been asked.
questionsAsked++;
}
Then do much of the same in the click event, including answer checking.
private void button1_Click(object sender, EventArgs e)
{
// We've already asked ten questions, don't do anything else.
if (questionsAsked > 10) return;
// If the user entered a valid integer into the text box
int answer;
if (int.TryParse(txtBoxAnswer.Text, out answer))
{
// Implement Between if still needed.
if (Between == 1)
{
if (answer == currentAnswer)
{
// the answer is correct.
}
else
{
// the answer is incorrect
}
int num1 = rnd.Next(1, 11); // 1-10
int num2 = rnd.Next(1, 11); // 1-10
currentAnswer = num1 + num2;
kusimus.Text = String.Format("{0} + {1}", num1, num2);
}
// We've asked another question.
questionsAsked++;
if (questionsAsked > 10)
{
// User has answered last question, do something?
}
}
}

If you place it in the button click event it will work and fire when you click the button.
private void Button_Click(object sender, RoutedEventArgs e)
{
int between = 1;
Random rnd = new Random();
//This loop is pointless since there's only one number that can use it.
//However; I've left it as it incase you're needing it for another reason.
for (int i = 0; i < 10; i++)
{
if (between == 1)
{
int num1 = rnd.Next(1, 11); // 1-10
int num2 = rnd.Next(1, 11); // 1-10
string number1 = num1.ToString();
string number2 = num2.ToString();
kusimus.Text = number1 + " + " + number2;
}
}
}
Now, here's something to note also just FYI:
/* If the work is a loop, string manipulation, or anything that may require more than 100ms of work
* then I suggest doing it asynchronously. Hopefully this helps.
* If it's confusing or you need more comments to explain what's going on let me know.
* Don't worry about the work being done... I just tried to keep it as similar as I could to your question
* and still make it useful for the example.
* Note: This is WPF so the Textblock works like this but it should be RichTextBox for WinForms and button will just be button.Enabled = true : false */
private async void Button_Click(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
textblock1.Text = string.Empty;
var between = 1;
Random rnd = new Random();
var randomText = await Task.Run(() =>
{
var stringBuilder = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
if (between == 1)
{
int num1 = rnd.Next(1, 11); // 1-10
int num2 = rnd.Next(1, 11); // 1-10
string number1 = num1.ToString();
string number2 = num2.ToString();
stringBuilder.AppendLine(number1 + " + " + number2);
}
}
return stringBuilder.ToString();
});
textblock1.Text = randomText;
button1.IsEnabled = true;
}

Related

How do I use a random number I generated in a separate sum

I'm a complete beginner and trying to create a Times Table game app that asks the user to input a number, generates a multiplication sum, and then checks if it's the write answer to deliver a congratulations message and then adds the score.
I've managed to generate the random number, but when I input the correct answer I get the Incorrect message which makes me think that the random number is not pulling through to the second button. Any help much appreciated!
Button 1
private void button1_Click(object sender, EventArgs e)
{
userInput = Convert.ToInt32(textBox1.Text);
if (userInput >= 1 && userInput <= 10)
{
Random rNum = new Random(); //uses built in function Random()
int rrNum = rNum.Next(1, 12); // creates a number between 1 and 12
label5.Text = (Convert.ToString(rrNum) + " x " + userInput);
}
}
Button 2
private void button2_Click(object sender, EventArgs e)
{
userAnswer = Convert.ToInt32(textBox2.Text);
Random rNum = new Random();
int rrNum = rNum.Next(1, 12);
if (userAnswer == userInput * rrNum)
{
label8.Text = "Congratulations!";
pictureBox1.Enabled = true;
pictureBox1.Visible = true;
}
else
{
label8.Text = ("Incorrect, try again!");
}
}

How to find a way of output the number of attempts for each question of the quiz?

I am making the quiz application on C# in Console version. I have almost done all things, but I don't know how to show the number of attempts for each question, after when the quiz is finished. If you know something, let me know.
I can not add more lines of the code, as the website doesn't allow to do it
if (keys[index] == answer) // Answer is correct
{
Console.WriteLine();
Console.WriteLine("Congratulations. That's correct!");
Console.WriteLine();
totalScore += markPerQuestion;
index++;
Console.WriteLine("The total score is: {0}", totalScore);
Console.WriteLine("Used attempt(s): {0}", attempt);
attempt = 1;
count = attempt;
markPerQuestion = 20;
}
else // Answer is incorrect
{
attempt++;
count++;
if (attempt <= 3)
{
markPerQuestion /= 2;
}
else if (attempt > 3 && attempt < 5) // The fourth attempt gives zero points
{
markPerQuestion = 0;
totalScore += markPerQuestion;
}
else if(attempt >= 5) // Move to the next question
{
Console.WriteLine("Sorry, you used all attempts for that question. Moving to the next question");
index++;
markPerQuestion = 20;
attempt = 1;
count = attempt;
continue;
}
Console.WriteLine("Oops, try again");
}
if ((index > keys.Length - 1 && index > questions.Length - 1)) // Questions and answer keys are finished
{
for (int i = 0; i < questions.Length; i++)
{
Console.WriteLine("Question {0} was answered after {1} attempt(s)", (i + 1), count);
}
break;
}
Consider this solution:
Create a public class that will allow you to store the results.
public class QuizMark
{
public int Attempts;
public int Mark;
}
For the Console app create a method to control the Quiz. Call the method Quiz() from the Main method.
private const int MAX_ATTEMPTS = 5;
private static void Quiz()
{
var quizResults = new List<QuizMark>();
var questionAnswers = new List<int>() { 1, 3, 5, 2, 3, 6 };
foreach(var a in questionAnswers)
{
var v = QuizQuestion(a);
quizResults.Add(v);
}
int i = 0;
quizResults.ForEach(e => Console.WriteLine($"Question: {++i} Attempts: {e.Attempts} Mark: {e.Mark}"));
var total = quizResults.Sum(s => s.Mark);
Console.WriteLine($"Total Points: {total}");
}
Notice the List collection that stores an object of the class QuizMark. This is where the results of each question are stored: attempts and points.
The List questionAnswers simply contains the expected answer to each of the questions.
Now create the method that is going to control how each question in the quiz will be handled:
private static QuizMark QuizQuestion(int answer)
{
var quizMark = new QuizMark();
int guess = 0; //Store ReadLine in this variable
int mark = 20;
for (int attempt = 1; attempt < MAX_ATTEMPTS + 1; attempt++)
{
guess++; //remove when adding Console.ReadLine
if (guess.Equals(answer))
{
quizMark.Attempts = attempt;
quizMark.Mark = mark;
break;
}
else
{
mark = attempt <= 3 ? mark/2 : 0;
quizMark.Attempts = attempt;
quizMark.Mark = mark;
}
}
return quizMark;
}
You will need to replace the incrementor guess++ with the actual guess the user makes. This code is designed to go though automatically just as a demonstration.
IMPORTANT NOTE:
You will want to do some error handling any time you allow users to enter data. They might enter non-integer values. Probably using a loop around a Console.ReadLine where you check the value of the input with a Int32.TryParse().

Keeping track of points in simple console game

I'm having a hard time wrapping my mind around this. Every time the player makes a wrong guess, it should subtract his/her bet from the initial balance.
Since it is in a loop, it always takes the initial balance from the beginning spits out the same balance every time. (obviously)
I've tried assigning different variables and just can't seem to figure it out.
I've omitted the medium and hard difficulty methods as they are of no use right now, until I figure out this one.
My Main() only calls the setDifficulty(). Nothing else.
class Control
{
int selectedNumber = 0;
Random num = new Random();
bool playAgain = true;
int difficulty = 0;
int bet = 0;
int initialBalance = 20;
int runningCredits = 0;
int credits = 0;
public Control()
{ }
//sets game difficulty
public void SetDifficulty()
{
Console.Clear();
Console.WriteLine("Please select level of difficulty between 1 - 100");
difficulty = int.Parse(Console.ReadLine());
if (difficulty >= 1 && difficulty <= 20)
LetsPlayEasy();
else if (difficulty >= 21 && difficulty <= 50)
LetsPlayMedium();
else if (difficulty >= 51 && difficulty <= 100)
LetsPlayHard();
else
{
SetDifficulty();
}
}
//easy level method
public void LetsPlayEasy()
{
//variables
int userGuess;
int numGuesses = 0;
selectedNumber = num.Next(1, 101);
Console.BackgroundColor = ConsoleColor.DarkYellow;
Console.Clear();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Difficulty level = EASY");
Console.WriteLine("\nBeggining credit balance = " + initialBalance);
Console.WriteLine("\nPlease place a bet. You will lose those credits for every incorrect guess!");
bet = int.Parse(Console.ReadLine());
do
{
Console.WriteLine("\nGuess a number between 1 and 100.");
userGuess = Convert.ToInt32(Console.ReadLine());
numGuesses++;
UI output = new UI();
output.CompareNumbers(userGuess, ref selectedNumber, ref playAgain, ref numGuesses);
runningCredits = (initialBalance - bet);
Console.WriteLine("\nYou have " + runningCredits + " credits remaining.");
} while (playAgain == true);
}
class UI
{
Random num = new Random();
int keepGoing;
public UI()
{ }
//compare user's guess to selected number
public void CompareNumbers(int userGuess, ref int selectedNumber, ref bool playAgain, ref int numGuesses)
{
Control difficulty = new Control();
Admin say = new Admin();
if (userGuess > selectedNumber)
{
Console.Beep(600, 300);
Console.WriteLine("\nToo High! Guess Again!");
}
else if (userGuess < selectedNumber)
{
Console.Beep(300, 300);
Console.WriteLine("\nToo Low! Guess Again!");
}
else
{
Console.Beep(350, 300);
Console.Beep(380, 200);
Console.Beep(380, 100);
Console.Beep(500, 1100);
Console.WriteLine("\n\nCongrats! It took you " + numGuesses + " guesses to win.");
numGuesses = 0;
Console.WriteLine("Press 1 to play again or 2 to quit.");
keepGoing = int.Parse(Console.ReadLine());
while (keepGoing != 1 && keepGoing != 2)
{
Console.WriteLine("\n\nPlease type either 1 or 2 only!");
keepGoing = int.Parse(Console.ReadLine());
}
if (keepGoing == 2)
{
playAgain = false;
say.Goodbye();
}
else
{
Console.Clear();
difficulty.SetDifficulty();
}
}
}
}
}
Initialise runningBalance to initialBalance and only use this value for calculations. If you only need initialBalance once, you can also do it by simply switching runningBalance to initialBalance without initializing runningBalance.
Console.WriteLine("\nBeggining credit balance = " + initialBalance);
Console.WriteLine("\nPlease place a bet. You will lose those credits for every incorrect guess!");
bet = int.Parse(Console.ReadLine());
runningBalance = initialBalance
do
{
Console.WriteLine("\nGuess a number between 1 and 100.");
userGuess = Convert.ToInt32(Console.ReadLine());
numGuesses++;
UI output = new UI();
output.CompareNumbers(userGuess, ref selectedNumber, ref playAgain, ref numGuesses);
runningCredits -= bet;
Console.WriteLine("\nYou have " + runningCredits + " credits remaining.");
} while (playAgain == true);
runningCredits = (initialBalance - bet);
You don't change initialBalance or bet in the loop, so every iteration has the same value of runningCredits.
Outside the loop, do this:
runningCredits = initialBalance;
Inside the loop, do this:
runningCredits -= bet;
Note: you don't have any code to check in the loop to see if the user guessed right or wrong (and as such, the user always loses and you always subtract out the bet).

Hint system to tell a random false selection

I'm making a c# windows form application in which there are five buttons each corresponding to a number 1-5 and the user guesses a random number out of those. I need to implement a hint which would tell the user a random false selection. How would I do this?
public partial class frmGuessANumber : Form
{
int number;
public frmGuessANumber()
{
InitializeComponent();
Random rnd = new Random();
number = rnd.Next(1, 6);
}
private void SelectionMade(object sender, EventArgs e)
{
Button selection = (Button)sender;
int guess = Convert.ToInt32(selection.Text);
if (guess == number)
{
DisableButtons();
lblMessage.Text = "Congratulations! " + guess + " is correct!";
lblMessage.Visible = true;
}
else
{
DisableButtons();
lblMessage.Text = "Sorry! " + guess + " isn't the right answer.";
lblMessage.Visible = true;
}
}
private void lblHint_MouseHover(object sender, EventArgs e)
{
Random rnd = new Random();
int wrongSelection = rnd.Next(2, 6);
if (number == 1)
lblHint.Text = "The number is not " + wrongSelection;
else
lblHint.Text = "The number is not " + (number - 1);
}
private void DisableButtons()
{
btnGuess1.Enabled = false;
btnGuess2.Enabled = false;
btnGuess3.Enabled = false;
btnGuess4.Enabled = false;
btnGuess5.Enabled = false;
}
}
You could
1) enumerate the possible numbers using Enumerable.Range
2) then take all except the correct solution (in your case number). You can use the Where method
3) then you would randomly pick a number from this set as a hint. You can use the ElementAt method
Random rnd = new Random();
int CorrectAnswer = rnd.Next(1, 6);
int hint = Enumerable.Range(1,6).Where(x=>x != CorrectAnswer ).ElementAt(rnd.Next(1,5));
Since the user has been deleted, I will just leave the answer for future people with a similar problem:

Pick a random random from a list. If it's not the chosen one, pick another one.

I have this Guess the number game. The user thinks of a number and the computer will guess it. I have this code but the thing is, every attempt that computer makes there's a chance that the random number will repeat. I would like to know how to create a random list, the computer will pick a number from the list, if it's not correct I would like to have that number deleted so it will not be picked up again. I am new in this field so I would really appreciate any help.
private void btnStartTheGame_Click(object sender, EventArgs e)
{
int guessTheNumber = Convert.ToInt32(txtNumberGuess.Text);
DialogResult dialogResult;
do
{
Random newNumberGenerator = new Random();
number = newNumberGenerator.Next(0, 10);
dialogResult = MessageBox.Show("Is number" + number.ToString() + " you are thinking about?", "Answer the question!", MessageBoxButtons.YesNo);
}while (dialogResult == DialogResult.No);
MessageBox.Show("Congratulation! You guessed the number!!");
}
Here is a short but complete program which does as you require (I have used a console application rather than forms):
private static void Main(string[] args)
{
string dialogResult = "";
bool[] alreadyGuessed = new bool[10];
int guesses = 0;
Random newNumberGenerator = new Random();
do
{
int number = newNumberGenerator.Next(0, 10);
if (!alreadyGuessed[number])
{
guesses++;
alreadyGuessed[number] = true;
Console.WriteLine("Are you thinking of the number " + number.ToString() + "?")
dialogResult = Console.ReadLine();
}
}
while (dialogResult.ToUpper() != "Y" && guesses < 10);
if (dialogResult.ToUpper() == "Y")
{
Console.WriteLine("I guessed the number!");
}
else
{
Console.WriteLine("No numbers left!");
}
Console.ReadLine();
}
The logic in your original program seemed somewhat backwards; it wasn't clear whether it was the user or the computer doing the guessing. This program assumes that you are thinking of a number between 0 and 9 (inclusive) and leaving the computer to try to guess it, but you can obviously adapt it to your needs. I have also omitted any validation logic.
EDIT: As Tarec correctly points out, this doesn't extend to very large number sets. To do that you'd need a proper shuffling algorithm like this:
public static void Shuffle(int[] array)
{
var random = new Random();
for (int i = array.Length; i > 1; i--)
{
int j = random.Next(i);
int temp = array[j];
array[j] = array[i - 1];
array[i - 1] = temp;
}
}
Then you could change your program to this:
private static void Main(string[] args)
{
string dialogResult = "";
int size = 10;
int[] array = Enumerable.Range(0, size).ToArray();
Shuffle(array);
for (int i = 0; i < size; i++)
{
int number = array[i];
Console.WriteLine("Are you thinking of the number " + number.ToString() + "?");
dialogResult = Console.ReadLine();
if (dialogResult.ToUpper() == "Y")
{
break;
}
}
if (dialogResult.ToUpper() == "Y")
{
Console.WriteLine("I guessed the number!");
}
else
{
Console.WriteLine("No numbers left!");
}
Console.ReadLine();
}
Now you can change 'size' to whatever you like and the program will work correctly. This is probably overkill for the original poster's needs, though.
List<int> randomNumbers = Enumerable.Range(0,10).ToList();
DialogResult dialogResult;
Random newNumberGenerator = new Random();
do
{
int index = newNumberGenerator.Next(0, randomNumbers.Count);
dialogResult = MessageBox.Show("Is number" + randomNumbers[index] + " you are thinking about?", "Answer the question!", MessageBoxButtons.YesNo);
if(dialogResult==DialogResult.No)
{
randomNumbers.RemoveAt(index);
}
}
while (dialogResult == DialogResult.No);
I modified your code by adding an array of number to be chosen. Then I random only the index of the array. If the number if not correct, the number is removed from the array and redo again.
int guessTheNumber = Convert.ToInt32(txtNumberGuess.Text);
DialogResult dialogResult;
ArrayList numberList = new ArrayList();
for(int i=1; i<10; i++)
numberList.Add(i);
int length = index.Count;
do
{
Random newNumberGenerator = new Random();
index = newNumberGenerator.Next(length);
dialogResult = MessageBox.Show("Is number" + numberList[index].ToString() + " you are thinking about?", "Answer the question!", MessageBoxButtons.YesNo);
if( dialogResult == DialogResult.No)
{
numberList.RemoveAt(index);
length = length - 1;
if(length == 0)
{
MessageBox.Show("No number left!!");
return;
}
}
}while (dialogResult == DialogResult.No);
MessageBox.Show("Congratulation! You guessed the number!!");

Categories