Pin code application that increments number of attempts - c#

I have been trying to finish this small application for counting the number of attempts if you fail to write the correct pin code.
This is my code so far, and I am not understanding why my code isn't working and it keeps on incrementing non stop.
private void btn_login_Click(object sender, EventArgs e)
{
int attempts = 0;
int pin_number;
do
{
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (pin_number != 1326)
{
attempts++;
MessageBox.Show($"pin code is incorrect you have {attempts} of 3 attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
} while (pin_number == 1326 && attempts < 3);
}

Every time you click the button is an "attempt", correct? Well, what's the first thing you do every time you click the button...
int attempts = 0;
So every attempt is the first attempt. Except when the user gets it right. Then what you have is an infinite loop because the pin_number is correct and attempts is never incremented.
First, get rid of the loop entirely. There's no need to repeatedly check the same input. Once it's checked, it's checked. Second, track the number of attempts outside the scope of each attempt, such as at the class level. Third, check the number of attempts. Perhaps something like this:
private int attempts = 0;
private void btn_login_Click(object sender, EventArgs e)
{
int pin_number;
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (attempts < 3 && pin_number != 1326)
{
attempts++;
MessageBox.Show($"pin code is incorrect you have {attempts} of 3 attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
}
Now it's at least checking the pin as expected. Though at this point you have some logic to reconsider for your program. Off the top of my head...
It never notifies the user if they got the pin right. Perhaps something else should happen?
After the number of attempts is exhausted, there's no warning to indicate this. It looks exactly as it does if the pin is correct.
The text implies that the number of attempts is counting down, but it's actually counting up.
Perhaps something like this might get you started:
private int attempts = 3;
private void btn_login_Click(object sender, EventArgs e)
{
int pin_number;
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (attempts <= 0)
{
MessageBox.Show($"No more attempts left");
}
else if (pin_number != 1326)
{
attempts--;
MessageBox.Show($"Pin code is incorrect you have {attempts} attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
}
Examine each statement in the logic. For your own logic, particularly around if blocks and loops and whatnot, perhaps even grab a piece of paper and draw out the different code paths and write down in each path what should happen there. Every detail is important, such as when to show a message or when to modify a value. There's a lot of polish that can be added to this code, and I imagine it's an academic exercise so I'll leave that to you.

Right now you have a loop inside your button click handler. You probably don't want that since you want to enable the user to enter a new pin code and click the Login button again.
But that also means that you need to store the number of attempts outside the click handler, since it needs to be saved from one click to the next.
So if you change your code to something like this, I think you'll get the functionality you're after
private int attempts = 0;
private void btn_login_Click(object sender, EventArgs e)
{
int pin_number;
pin_number = int.Parse(txt_pin.Text);
MessageBox.Show("Hi There");
if (pin_number != 1326)
{
attempts++;
MessageBox.Show($"pin code is incorrect you have {3-attempts} of 3 attempts left");
txt_pin.Text = "";
txt_pin.Focus();
}
if (attempts >= 3)
{
btn_login.Enabled = false;
}
}

Related

How can I increase one of two numbers in a comparative statement with a button click

I'm making a little UWP app in C# that simulates drawing straws. The problem that I'm having is that I want the user to get to a point where they click a button, and the variable baseNumber (initially set to 2 -- the fewest amount of drawn straws to make any sense) is compared to a randomly generated number that is passed through from another button event. I have this part down.
The part that is giving me fits is that I want the next user to then click the same button, and I want the baseNumber incremented by 1, and have that new number compared to the losingStraw. If that user is declared safe, I want the number to increment again for the next user with their button click, until ultimately the numbers equal each other, a user draws the short straw, and another code path is taken.
I'm very new to coding, so what I want might not even be possible. Here's an example of what I've tried, below. I have also tried variants on a do / do while and a for loop.
If I could somehow stop something like a for loop at each pass and make it wait for user input (the button press), that would be ideal. I couldn't figure that out either though.
Any help or ideas you can offer would be greatly appreciated!
private void drawButton_Click(object sender, RoutedEventArgs e)
{
int baseNumber = 2;
int losingStraw = Convert.ToInt32(drawButton.Tag);
if (baseNumber < losingStraw)
{
instructions.Text = "You are safe!";
baseNumber = baseNumber++; // that doesn't work at all. I was hoping that baseNumber
}
else
{
instructions.Text = "You have drawn the losing straw";
}
}
You have to write baseNumber++; instead of baseNumber = baseNumber++; since ++ aka the unary operators helps increases integer value by one. Thus baseNumber++; means baseNumber = baseNumber + 1;
Edit
In your case the variable int baseNumber = 2; has been declare and initialized in the event itself thus every-time the event is fired the baseNumber will be initialized by 2 and you would not be able to see any changes. Thus you can do something like this
int baseNumber; // you can do 2 here as well
public YourFormName()
{
baseNumber = 2;
}
private void drawButton_Click(object sender, RoutedEventArgs e)
{
int losingStraw = Convert.ToInt32(drawButton.Tag);
if (baseNumber < losingStraw)
{
instructions.Text = "You are safe!";
baseNumber = baseNumber++; // that doesn't work at all. I was hoping that baseNumber
}
else
{
instructions.Text = "You have drawn the losing straw";
}
}
Just put the baseNumber outside the method, can be globally declared so that everytime you increment it, it will never to reset to 2 again when entered on butotn click :) -HAPPY CODING-
public class YourClass
{
int baseNumber = 2;
private void drawButton_Click(object sender, RoutedEventArgs e)
{
int losingStraw = Convert.ToInt32(drawButton.Tag);
if (baseNumber < losingStraw)
{
instructions.Text = "You are safe!";
baseNumber = baseNumber++; // that doesn't work at all. I was hoping that baseNumber
}
else
{
instructions.Text = "You have drawn the losing straw";
}
}
}

C# String comparison not working

I'm having this wierd problem within the application I'm currently working on.
string searchText = "onMouseOver=\"CallList_onMouseOver(this);\" id=\"";
List<int> searchOrders = AllIndexesOf(scraper.clientBrowser.DocumentText, searchText);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < searchOrders.Count; i++)
{
string order = scraper.clientBrowser.DocumentText.Substring(searchOrders[i] + searchText.Length, 6);
scraper.clientBrowser.Document.GetElementById(order).InvokeMember("Click");
for (int j = 0; j < scraper.clientBrowser.Document.Window.Frames.Count; j++)
{
if (scraper.clientBrowser.Document.Window.Frames[j].Document != null && scraper.clientBrowser.Document.Window.Frames[j].Document.Body != null)
{
string orderText = scraper.clientBrowser.Document.Window.Frames[j].Document.Body.InnerText ?? "Nope";
//MessageBox.Show(j + Environment.NewLine + orderText);
if (!orderText.Contains("Nope"))
{
sb.AppendLine(orderText + Environment.NewLine);
}
}
}
}
Clipboard.SetText(sb.ToString());
The thing is, whenever I uncomment the MessageBox.Show, I can clearly see orderText is filled with another value than "Nope", the Stringbuilder gets filled, and the correct text is copied.
However if I comment the Messagebox.Show, the outcome of this loop is always "Nope". I'm stuck here, I have no idea what could cause something like this.
The scraper.clientBrowser is a System.Windows.Forms.WebBrowser.
Update:
Solved the issue by waiting for the document to be loaded, created this mechanism:
public bool DocumentLoaded
{
get { return documentLoaded; }
set { documentLoaded = value; }
}
private void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
this.DocumentLoaded = true;
this.clientBrowser = sender as WebBrowser;
}
void clientBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
this.DocumentLoaded = false;
}
Then in the class I'm using:
while(!scraper.DocumentLoaded)
{
System.Threading.Thread.Sleep(100);
}
It sounds like you need to ensure that the page is fully loaded, like there might be a race condition. I would suggest wiring up the WebBrowser.DocumentCompleted event, and then attempting your scrapping logic.
Update
I overlooked this initially, this certainly has something to do with your issue. The line where you are invoking a click, like so scraper.clientBrowser.Document.GetElementById(order).InvokeMember("Click");. This is done in the iteration, which will more than likely manipulate the DOM -- will it not? I suggest going about this problem entirely different. What are you trying to achieve exactly, (not how you're trying to do it)?
With this alone, I would suggest that you refer to this SO Q/A and look at how they're waiting for the click to finish.
Only one thing I can guest here:
When you uncomment MessageBox.Show, at the time the message box show the info, the clientBrowser use this time to finish loading page. Then when you press OK on message box, the page is load completed, so you get the result. When you comment it, you dont wai for page loaded, so the result is diffent.

Comparing to previous string gets me stuck in a loop

Ok, so I have a program that checks a twitch url for whenever someone new follows the channel by comparing a certain string is different from a "temp" string that I use for reference. But instead of only outputting a message every time the string is different it gets stuck in a loop of outputting the latest follower and then second latest follower then latest follower again etc.
What am I missing? Also, is there a better way of checking if a certain string is updated?
private void DonationListen()
{
try
{
followers = this.donationClient.DownloadString("https://api.twitch.tv/kraken/channels/" + channel.Trim() + "/follows");
donationTimer.Interval = 10000;
donationTimer.Elapsed += new ElapsedEventHandler(CheckUpdates);
donationTimer.Start();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void CheckUpdates(object source, ElapsedEventArgs e)
{
donationTimer.Stop();
int startIndex = followers.IndexOf("display_name\":") + 15;
int endIndex = followers.IndexOf(",\"logo", startIndex);
prevFollower = followers.Substring(startIndex, (endIndex - 1) - startIndex);
if (firstRun == true)
{
temp = prevFollower;
}
else if (prevFollower != temp)
{
//New follower detected
temp = prevFollower;
if (updateFollower != null)
{
updateFollower(prevFollower);
}
}
else
{
//Follower is the same as before
}
firstRun = false;
DonationListen();
}
I'm thinking it might have something to do with the downloadstring trying to get a new string from the url but failing since it's currently being updated and therefore the CheckUpdates doesn't have correct information or something?
Without a good code example, it is difficult to know for sure what the problem is. So we are left inspecting the code you did show us.
Based on that, it appears to me as though your "loop" is being caused by repeatedly subscribing to the same event.
In your DonationListen() method, you have this statement:
donationTimer.Elapsed += new ElapsedEventHandler(CheckUpdates);
In the CheckUpdates() method (i.e. the handler you are subscribing), you have this statement (as the very last statement):
DonationListen();
In other words, every time the timer's Elapsed event is raised, you add another event handler instance to the event. For every handler you add, the CheckUpdates() method will be called.
Again, without a good code example, it is difficult to know for sure what the best fix would be. But given the code that is here, it appears to me that you could just remove that last statement from the CheckUpdates() method, as the DonationListen() method does not appear to do anything that needs doing again.

autoscroll a textbox in c# 1 line down every x seconds

im trying to get a textbox to autoscroll a line down every X seconds.
i have found the AutoScrollOffset and ScrollToCaret functions, but these functions do not give the desired result.
I think my solution would be to do the autoscroll function in a backgroundworkerthread, that does a scroll down by 1 line every x seconds. But i have no idea how to, and info from the net isnt verry usefull either.
I hope someone can help me, thnx in advance!
(im using .net 4.5)
Borrowing heavily from this answer, and combining it with a Timer, you could do something like this:
private int lineNumber = 1;
private void timer1_Tick(object sender, EventArgs e)
{
nfobox.HideSelection = false;
nfobox.SelectionStart = nfobox.GetFirstCharIndexFromLine(lineNumber - 1);
nfobox.SelectionLength = nfobox.Lines[lineNumber - 1].Length;
nfobox.ScrollToCaret();
lineNumber++;
// include some code to detect the last line, or you'll get an exception
}
This will only work if your lines are separated by a line feed.
If it's one long line that wraps, then the whole thing will be selected on the first "tick" and then it's done.
"Grant Winney" is rigth. you can't directly modify the Uİ from a background thread.
But You use the way below.
int lineCounter = 0;
int nextLineLength = 0;
private void timer1_Tick(object sender, EventArgs e)
{
textBox1.SelectionStart = nextLineLength;
textBox1.SelectionLength = 0;
textBox1.ScrollToCaret();
nextLineLength += textBox1.Lines[lineCounter++].Length + "\r\n".Length; //"\r\n" is next line parameters
}

How to get "previous" and "next" functionality?

I have a program that people can leave comments on a video. The comments come is as in queue status. The admin can go into the admin section and mark the comments as either approved or removed. They want to be able to automatically go to the next item marked in queue when they press either the previous or next buttons, as well as if they approve or remove a comment. I do not know jQuery or JavaScript well enough to know if it is possible to do it using those, or how to do it through the code behind (this is in C# .NET). Any help would be appreciated:
Status and value:
In queue = 0
Approved = 1
Removed = 2
Here is the code-behind. The status changes work, the only thing I cannot do is have it go to the next record marked in queue. The first two events are blank because I do not know how to fill them, but simply put, all the need to do too is go to the next record marked in queue.
If you need any more code, please let me know...
protected void previous_clicked(object sender, EventArgs e)
{
}
protected void next_clicked(object sender, EventArgs e)
{
}
protected void approve_clicked(object sender, EventArgs e)
{
currentMessage = new videomessage(Request["id"].ToString());
status.SelectedValue = "1";
currentMessage.status = "1";
currentMessage.Save();
}
protected void remove_clicked(object sender, EventArgs e)
{
currentMessage = new videomessage(Request["id"].ToString());
status.SelectedValue = "2";
currentMessage.status = "2";
currentMessage.Save();
}
Sounds more like an architectural challenge to me.
I recommend using a Queue. This is a collection type following a first-in, first-out (FIFO) approach. You put objects into the queue and get them back out in the same order. An object that was received out of this queue is automatically is removed from the queue, so you can be sure that you do not handle the same element twice.
Your described workflow then would work as these simple steps:
Whenever a message arrives, you put the object into your queue.
When the admin clicks on the next button, you request the first object out of the queue.
Your admin does his administrative tasks and approves the message.
Clicking on Next start with above item 1 again.
[EDIT]
Oops, I realized that my Queue approach would not allow for navigating back to previous items.
In this case I suggest using a simple List collection. This list can be accessed via the 0-based position in the list. This makes it easy to implement a forward/ backward navigation.
For my sample code, please bear in mind that there is a lot that I cannot know about your environment, so my code make a lot assumptions here.
You need to somwhere store a collection that contains your messages to be approved:
private IList<videomessage> _messagesToApprove = new List<videomessage>();
You will also need some variable that keeps track of the current position in your collection:
// Store the index of the current message
// Initial value depends on your environment. :-)
private int _currentIndex = 0;
To begin with, you will need a starting point where new messages are added to that collection, like subscribing to some event or so. Whenever a message arrives, add it to the collection by calling a method like:
// I made this method up because I do not know where your messages really come from.
// => ADJUST TO YOUR NEEDS.
private void onNewMessageArriving(string messageId)
{
videomessage arrivingMessage = new videomessage(messageId);
_messagesToApprove.Add(arrivingMessage);
}
The you can easily implement the navigation by incrementing/ decrementing the position index:
private void previous_Click(object sender, EventArgs e)
{
// Check that we do not go back further than the beginning of the list
if ((_currentIndex - 1) >= 0)
{
_currentIndex--;
this.currentMessage = this._messagesToApprove[_currentIndex];
}
else
{
// Do nothing if the position would be invalid
return;
}
}
private void next_Click(object sender, EventArgs e)
{
// Check if we have new messages to approve in our list.
if ((_currentIndex + 1) < _messagesToApprove.Count)
{
_currentIndex++;
currentMessage = _messagesToApprove[_currentIndex];
}
else
{
// Do nothing if the position would be invalid
return;
}
}
private void approve_Click(object sender, EventArgs e)
{
// Sorry, I don't know where exactly this comes from, needs to be adjusted to your environment
status.SelectedValue = "1";
this.currentMessage.status = "1";
this.currentMessage.Save();
// If you want to remove items that have been checked by the admin, delete it from the approval list.
// Otherwise remove this line :-)
this._messagesToApprove.RemoveAt(_currentIndex);
}
private void remove_Click(object sender, EventArgs e)
{
// Sorry, I don't know where exactly this comes from, needs to be adjusted to your environment
status.SelectedValue = "2";
this.currentMessage.status = "2";
this.currentMessage.Save();
// If you want to remove items that have been checked by the admin, delete it from the approval list.
// Otherwise remove this line :-)
this._messagesToApprove.RemoveAt(_currentIndex);
}
Save the id of current comment in session or viewstate get it back on next or previous button click and display the accordingly:
Session["id"] = 2;
int id = (int) Session["id"];

Categories