While loop not properly checking all conditions? - c#

So the assignment is as follows: you can enter all sorts of numbers but when you enter 0 two times in a row it needs to stop. The first time you enter a number your not allowed to enter 0.
This is the code I have setup:
class MainClass
{
public static void Main (string[] args)
{
int givenNumber, prevNumber;
Console.WriteLine ("Enter a number: ");
int.TryParse (Console.ReadLine (), out givenNumber);
// I've set the prevNumber to givenNumber because the variable has to be initialized
// before I can use it in the condition below. I thought setting it to the giveNumber
// wouldn't harm. Note that the first time your not allowed to enter 0
prevNumber = givenNumber;
while (givenNumber != 0 && prevNumber != 0) {
prevNumber = givenNumber; //Here is where they both are 0 at a given moment, but only after the condition.
Console.WriteLine ("Enter a number: ");
int.TryParse (Console.ReadLine (), out givenNumber);
}
Console.WriteLine ("Tada");
}
}
The problem is that it already stops when you've only entered one 0. For example if I'd first enter a 7 to start with, and my next number would be 0. When I debug it it says that my givenNumber is 0 and prevNumber is 7, when it goes back to the while condition it stops and finishes. When the program finishes the debug clearly says prevNumber = 7 and givenNumber = 0. I am using the conditional AND correct am I not?
Any clue? I'm not allowed to use arrays for this matter.
Thanks in advance

Ooh, right, you've got the logic wrong. It should be this:
while ((givenNumber != 0) || (prevNumber != 0)) {
Look up DeMorgan's laws to see why...

Your problem is with your conditional statement.
Right now you're checking whether both the givenNumber and the PrevNumber DO NOT equal 0.
So, if neither of them equals 0 then the statement will evaluate to TRUE. However, if either one of the numbers is 0 then the statement will evaluate to FALSE, since (TRUE) && (FALSE) evaluates to FALSE.
There are two ways to fix this: You can either use || (the "OR" operator) with the two "!=" statements, or you can negate the whole thing and use regular equality rather than "!=" as such: !(givenNumber == 0 && prevNumber == 0)

while (givenNumber != 0 && prevNumber != 0)
For first read value from console - number 7
givenNumer will be 7
prevNumber will be 7 too (because of assignment prevNumber = givenNumber;)
Thus while (7 != 0 && 7 != 0) will pass
Second read from Console - number 0
Thus while (0 != 0 && 7 != 0) will not pass because 0 != 0 is FALSE and while loop ends if condition is result is FALSE

Related

How to update variable from with if statement MQL5

I have been googling for two days now, but can't figure this out and it seems to be basic.
Within the void OnTick(), I would like to create a variable int a;. Lets say it starts out with no value int a;, then I test condition if a is NULL or || equals 1 like this if (a == NULL || a == 1) which should always return true the first time the if statement runs due to NULL. I then assign a value to the variable a = 0;, so now a should equal 0.
This should trigger the else if(a == 0) the next time OnTick() is called, at this point I assign a = 1; resulting in the if being triggered next time round, etc and infinitum, constantly checking and assigning values switching between 0 and 1.
void OnTick()
int a;
if (PositionsTotal() < 1)
{
if(a == NULL || a == 1)
{
a = 0;
}
else if(a == 0)
{
a = 1;
}
}
I do not know what is going on, but during Testing in Strategy tester, I am getting a long string of numbers which switches between negatives and positives always with the same number -123456789 or 123456789, always 9 digits long.
Or during Debugging from Meta Editor. A random positive 3 digit number which never changes!
So far I have had both 303 and 597.
Beyond frustrating and most likely answered somewhere else.
Just not sure how to phrase the search term.
Thanks for you help.
I think the problem is that you declare your variable a inside the method OnTick, so it starts with an arbitrary value every time you call this method. Try declaring it outside this method.

Or in IF statement not working properly

I have this Or condition in an IF statement (in a foreach loop) in a Windows Form C# program:
if ((splittedFile.Count() != 3) || (splittedFile.Count() != 4))
continue;
and it always does continue, even if splittedFile.Count() is 3 or 4.
The thing is that if I remove the Or condition:
if ((splittedFile.Count() != 4))
continue;
it works properly!! Any ideas why?
This is the correct behavior, you need to use &&.
The reason is that the count is fixed number, let's say n. Now the condition reads:
n is not 3 or n is not 4.
Given n is 4, this means it is not 3, thus the test succeeds and vice versa.
A compiler can't detect this is trivially true, because between the two if statements, the Count() might change (for instance in a multithreading setting where the second thread would add/remove something to/from the collection). I agree however some analysis tools could be capable in some conditions to detect such trivial behavior. In general however such analysis can't be implemented because of Rice's theorem.
If you use &&, the expression reads:
n is not 3 and n is not 4.
Thus both conditions should be true. In other words only if n is less than three and greater than 4, the condition holds.
Try:
if ((splittedFile.Count() != 3) && (splittedFile.Count() != 4))
continue;
I know || sound logical because : if splittedFile.count is not 3 OR it is not 4 then continue; But because there are 2 NOT ! operators in the if expression an AND && is needed.
put a real number into your expression:
if( 3 != 3 || 3 != 4)
which is
if( false || true )
your expression will always be true, as splittedFile.Count() is always (not 3) or (not 4)
you want to && your results together, which looks like
(x != 3) || (x != 4)
or
!( x == 3 || x == 4)
Because one of your expressions will be always true. That's why true || something always returns true.
Let's analyze your splittedFile.Count() is 3, 4 and other than these values.
For 3, your expression will be false || true and this returns true.
For 4, your expression will be true || false and this returns true.
For other than 3 or 4, your expression will be true || true and this returns true.
Strongly suspect you are looking for && operator which provides logical-AND.

Pick out every word beginning with a capital letter

I would like to pick out every word in a string which beggings with a capital letter, but an Array out of bounds error appears on line 3;
foreach (string strWord in words)
{
if (Char.IsUpper(strWord[0]) && strWord.Length > 0)
{
Console.Write(strWord + " :: ");
}
}
Thank you for your help
Swap the arguments, otherwise it crashes before checking:
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
Just do the strWord.Length > 0 first
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
{
Console.Write(strWord + " :: ");
}
So you can make sure strWord has at least one letter before trying to get first letter.
What is happening here is that you are checking the value of strWord[0] first without first making sure that there is any letter in the word or not, so in-case the value of strWord is NULL the program throws an exception that the index 0 is being called though it has not been given value, so to rectify this problem you should check the length of the word first and then check if the character strWord[0] is Upper case or not this way if the string is NULL then if condition will be discarded before it gets to the second part corrected code 1:-
if (strWord.Length > 0)
{
if(Char.IsUpper(strWord[0]))
{
Console.Write(strWord + " :: ");
}
}
corrected code 2:-
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
{
Console.Write(strWord + " :: ");
}
Make sure the length check is first when you use the && operator because the arguments are evaluated in order. If the first argument fails the second will not execute, and the IsUpper is causing out-of-bounds errors when Length is 0:
http://msdn.microsoft.com/en-us/library/2a723cdk.aspx
So you just need to swap the evaluations around:
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
{
//etc
}
The &&-operator is a short-circuiting operator which mans that it only evaluates the first condition if that returns already false. So it's the right choice if you want to prevent an exception. But you have to use the correct order, first the check then the method that can fail.
So like this:
if (strWord.Length > 0 && Char.IsUpper(strWord[0]))
...
However, you could also use this neat LINQ query:
var allWordsThatStartWithUpperCaseLetters = words
.Where(w => w.Length > 0 && Char.IsUpper(w[0]));
string result = string.Join(" :: ", allWordsThatStartWithUpperCaseLetters);

C# Logic Conflict within a condition

Relevant misc info:
Project = Tic Tac Toe (console app)
My issue is the following:
I have an array that initially is filled with 0's which MUST stay as 0's unless the user takes a move (then it'll become a 1) or the computer makes a move then it becomes a 2.
Example code:
else if (posStatus[2] != 0 && posStatus[5] != 0 && posStatus[8] != 0 && (posStatus[2] + posStatus[5] + posStatus[8] % 2 == 0))
{
if (posStatus[2] == 0)
{
posStatus[2] = 2;
return;
}
else if (posStatus[5] == 0)
{
posStatus[5] = 2;
return;
}
else if (posStatus[8] == 0)
{
posStatus[8] = 2;
return;
}
issue:
There is a grid that is 9 long which three rows, 3 columns and two diagonals. Initially all values are set to 0 and this is used to determine if the space is free so changing to another type would cause issues. If the value 1 is held player 1 has played there. If the value 2 is held the computer has played there.
So originally I had put in
posStatus[0] + posStatus[1] + posStatus[2] % 2 == 0)
Which decides where the computer will play in this case it will be the first row if the enemy player has put 2 values there which logically should work perfectly and it does apart from my issue which is as follows:
When nothing is played on a row the values are: 0, 0 ,0 if you do 0 + 0 + 0 % 2 you'll discover that equals 0 which is the parameter for the above condition. This means it will attempt to make sure there is a value in each row/column/diagonal which of course is not good as it means the player can win in 3 turns..
So to combat this I added in (I'm aware I can refactor it) I added:
posStatus[0] != 0 && posStatus[1] != 0 && posStatus[2] != 0
Which means if a row/column/diagonal is empty do not play there which means it never plays in empty rows/columns/diagonals which is an issue.
Suggestions?
You have to check few conditions for each time, need not to consider the sequence. Possible cases of win for any player would be:
0,1,2
0,3,6
0,4,8
1,4,7
2,4,6
2,5,8
3,4,5
AND 6,7,8
I am assuming that numbering is row wise and started from 0.
Now you have to tell computer based on the input of user.
For example:
User has selected 2, so you have posStatus[2] = 1 Now the only cells you have to check are 0,1,4,5 and 6 as these are the only possible cells for win.
To handle the beginning of game situation, you have two options:
Let the user start always.
Start anyone from 0,2,6 and 8 as these are part of the maximum solutions.
Another Approach:
There are 3 possibilities of success:
A. Row wise : Add or substitute number by 1 and check status ,
B. Column wise : Add or substitute number by 3 and check status ,
C. Diagonally : Add or substitute number by 2 AND 4 then check status
For example if user has selected i cell. Your check should be:
A. See the status of (i-2),(i-1),(i+1) AND (i+2) - Obviously this should be in range of 0-8
B. See the status of (i-6),(i-3),(i+3) AND (i+6)
C. See the status of (i-8),(i-4),(i-2),(i+2),(i+4) AND (i+8)

Why does while loop OR not work but AND does?

I have a simple while loop in C# and basically I'm testing two conditions
while (opponentOne.HP >= 0 || opponentTwo.HP >= 0)
Which when I read this means, while the first opponents HP is more than equal to 0 OR the seconds opponents HP is more than equal to 0, exit. So when only one of them are true, exit the while loop?
However this does not do what I want it to do, it waits for both of them to become true before exiting the loop, however if I change || to && it will work
while (opponentOne.HP >= 0 && opponentTwo.HP >= 0)
Which now says while the firsts opponents HP is more than 0 and the seconds opponent is more than 0, exit...
Have I got something mixed up here?
I thought the loop should break when both conditions are met.
The condition isn't the condition "to exit", it's the condition to continue
So first one says "continue looping as long as either oponents have >0HP" and the second one says "continue as long as both opponents have >0HP"
A while loop will keep looping until the condition BECOMES FALSE.
So in the first case :
NOT (1.HP >= 0 || 2.HP >= 0)
if we apply DeMorgan's equivalency to it:
It will break when
NOT 1.HP >= 0 AND NOT 2.HP >= 0
Have I got something mixed up here?
Yes, && means that both sides must be true(both oppponents must be alive), otherwise the loop is exited.
|| means that one of both sides must be true, so only one opponent must be alive.
Replace the while-loop with an if-statement(for demonstration purposes only):
if(opponentOne.lives && opponentTwo.lives)
{
// do something
}
else // one is dead
{
// exit
}

Categories