I'm having brain fade trying to write a single logical expression that suits the question's comment
// **Don't do xyz between 10.00pm and 7:30am**
//
if(hour > 22 || (hour < 7 && minutes < 30)
output("too early or too late");
Without coming up with something god awful like:
if (hour > 20)
"Too late";
if (hour < 7)
"Too early"
else
if (hour == 7 && minute < 30)
"Too early"
Please put me out of my misery.
|| is your friend here. If you have multiple conditions and if any of them are true you want to do something then instead of using
if (condition1)
do_something();
if (condition2)
do_something();
if (condition3)
do_something();
You can use
if (condition1 || condition2 || condition3)
do_something();
So to relate that to what you have your single if statement would be
if(hour > 21 || hour < 7 || (hour == 7 && minute < 30))
output("too early or too late");
Related
This question already has answers here:
C# conditional AND (&&) OR (||) precedence
(6 answers)
Closed 3 years ago.
I'm going through some C# coding exercises and have run into some operator logic that's stumped me.
The following line of code evaluates to false:
int a = 40, int b = 50;
if (a >= 20 && a <= 30 && (b < 20 || b > 30))
{
return a;
}
However, if I remove the brackets from inside the if statement, it evaluates to true.
if (a >= 20 && a <= 30 && b < 20 || b > 30)
{
return a;
}
Can anyone explain what I'm missing? Given that a isn't between 20 and 30, shouldn't it return false? I don't understand why putting the b portion of the if statement in brackets makes it evaluate to false.
Is it evaluating everything prior to "b > 30" as a single condition?
This is all to do with operator precedence.
Just like how * are evaluated first before + (we say * has a higher precedence than +), && is evaluated before ||, as specified.
In the first code snippet, you used brackets to "override" this precedence, making the || part evaluate first, just like how you can add parenthesis to the expression 1 + 2 * 3 to make it evaluate to 9 instead of 7.
a >= 20 && a <= 30 && (b < 20 || b > 30)
^^^^^^^^^^^^^^^^^
this part first
which becomes:
a >= 20 && a <= 30 && true
^^^^^^^ ^^^^^^^
now these parts
which becomes:
false && false && true
resulting in false.
In the second example however, there are no parentheses so the expression is evaluated according to the normal precedence rules:
a >= 20 && a <= 30 && b < 20 || b > 30
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This part first
Which becomes:
false || b > 30
^^^^^^
then this
which becomes:
false || true
resulting in true.
If you look at the second part where you have removed the parenthesis, it is now divided into two subparts.
First one being : a >= 20 && a <= 30 && b < 20 This evaluates to false.
First one being : b > 30 This statement evaluates to true.
So at the end you have something like this
F || T from both the statements which should eventually give you true as end result
I am trying to spawn my obstacles with level improvement, but for some reason when i tested it in game it doesn't work how i want.
Lets say i start game from 26 level.
I play normally until the level 36, even the 35 level spawning correctly but when player reach level exactly on 36 the code goes into else statement not in else if..
This is my code to spawn obstacles by levels..
if (curentLevel > 0 && curentLevel < 10)
{
SpawnSpawner(0);
}
else if (curentLevel > 10 && curentLevel < 35)
{
SpawnSpawner(1);
}
else if (curentLevel > 35 && curentLevel < 50)
{
SpawnSpawner(2);
}
else if (curentLevel > 50 && curentLevel < 60)
{
SpawnSpawner(5);
}
else
{
}
the code on in else statement gets executed which is empty in my example exactly on level 36.
I hope there is solution why because I told the program to check if curentlevel is higher then 35 which is on 36 level and if the level is smaller then 50 which is 36 , so I don't have idea why then its not executed this code:
else if (curentLevel > 35 && curentLevel < 50)
I bet I do something wrong but I hope someone will point me to solution and explain why program doesn't work on my way of thinking, thanks so much...
As per #Ruzihm's explaination in the comment, you're checking if less than 35 and bigger than 35, so when currentLevel is exactly equal to 35, it will not evaluate true in any conditions.
The solution, as per #DavidFreeman's answer in the comments - the solution to your issue is to make the code less complex:
if (curentLevel < 10)
{
SpawnSpawner(0);
}
else if (curentLevel < 35)
{
SpawnSpawner(1);
}
else if (curentLevel < 50)
{
SpawnSpawner(2);
}
else if (curentLevel < 60)
{
SpawnSpawner(5);
}
else
{
}
The if (currentLevel > 10) is redundant, if it doesn't evaluate true in currentLevel < 10 it will definitely be 10 OR MORE in the next else if.
If you must use specific ranges, you must take care to include all levels in the conditionals, like #BACON writes, with your current conditions you're covering the currentLevel 1-9, 11-34, 36-49, and 51-59, since 10 < 10 == false & 10 > 10 == false. You need to include the 10th level in one of the conditionals, like 10 <= 10 == true
I want to do IF under serveral condition AND && and OR || on it
i have two range of number
Top1 - Bottom1 and
Top2 - Bottom2
and only executed when Currentnumber is within these two range
am i doing it okay ?
if (OnlyAbove == True
&& (Top1 > Currentnumber || Top2 > Currentnumber)
&& (Bottom1 < Currentnumber || Bottom2 < Currentnumber)
)
{
Statement
}
I'm going to go out on a limb and say: no, you're not doing right on this one - mostly because what your code is currently doing doesn't make sense.
One thing that helps out with stuff like this is to phrase it in common english - so you go from:
if (OnlyAbove == True
&& (Top1 > Currentnumber || Top2 > Currentnumber)
&& (Bottom1 < Currentnumber || Bottom2 < Currentnumber)
)
{
Statement
}
... to ...
if OnlyAbove
AND (CurrentNumber above at least one of the two Tops)
AND (CurrentNumber below at least one of the bottoms)
After all, the stuff between those inner parenthesis is saying "Top1 > current OR Top2 > current" - which really isn't what you're looking for.
Something that'll help out - not only writing code like this, but reading it down the line, is to go a bit overboard with variables. Variables are awesome at helping you document logic, since you can name them very descriptively.
So imagine code that looks like this:
bool betweenRange1 = (Currentnumber > Bottom1) && (Currentnumber < Top1);
bool betweenRange2 = (Currentnumber > Bottom2) && (Currentnumber < Top2);
if (OnlyAbove && betweenRange1 && betweenRange2)
{
Statement
}
... that IF statement starts to look a lot more readable - it's obvious at a glance at what it's getting at. If you're having trouble parsing IF statements, it's not a bad habit to get into. Maybe a bit overkill... but overkill's a lot better than having code you're not sure of what it's doing :-)
I'm making a game in unity, and I have this 'if statement' that by every 5 waves my shop menu will become visible. The code does work, but I am certain I'm doing something wrong or could do something better!
if (waveCount == 5 || waveCount == 10 || waveCount == 15 || waveCount == 20 || waveCount == 25 || waveCount == 30 || waveCount == 35 || waveCount == 40 || waveCount == 45 || waveCount == 50)
{
// yield return new WaitForSeconds(shopWait);
shopPanel.SetActive(true);
}
As you can see the 'if statement' not that good, normally it continues all the way to waveCount == 100 but i cut that out. There must be a simpler or cleaner way to do this :/ but i just can't wrap my head around it :(
Edit 1:
Thanks, I didn't know much about modulo, know I know what I have to read about :)
You can use modulo operation:
if (waveCount % 5 == 0)
Yes, there are indeed simpler ways of doing this. If you use a little bit of maths and logic, you can figure this out.
Since you want to check whether the value of waveCount is a multiple of 5, you can use % to get the reminder of waveCount / 5. If that reminder is 0, waveCount is a multiple of 5.
if (waveCount % 5 == 0 && waveCount <= 100)
I added waveCount <= 100 to replicate your code's behaviour when waveCount is larger than 100 i.e. not get into the if statement.
Alternatively, you can put all the values into a list:
var list = new List<int>();
for (int i = 1 ; i <= 20 ; i++) {
list.Add(i * 5);
}
And then check whether the list contains the number:
if (list.Contains(waveNumber))
The advantage of this is that if you decided to change how the game works and say that the shop menu can be opened at waves 9, 52, and 77, you just add the numbers to the list, without modifying the if statement. This provides a lot of flexibility.
if (waveCount % 5 == 0 && waveCount <= 50) {
//...code
}
If your “if” statement's body just contains shopPanel.SetActive(true); you can do that without even using “if” like that.
shopPanel.SetActive(waveCount % 5 == 0 && waveCount <= 50);
Give it a try
if (waveCount % 5 == 0 && waveCount <= 50)
Use the modulo-operator:
if(waveCount % 5 == 0 && waveCount <= 100) ...
The operator calculates the remainder of an integer-divison. In your case the statement should return zero indicating that your number divided by 5 has no remainder.
Just to generalize: in case the data you have doesn't match a pattern, you can put all the things to match against in a set, then test the set for membership:
var thingsToMatch = Set(2, 5, 8, 14, 23, 80, 274...);
if (someNumber in thingsToMatch) {...}
As long as you know the set isn't being recreated everytime the function is called, this has proven to be fairly fast. If your language doesn't automatically cache the set, you can make it a static variable of the function.
You can use the remainder operator for this:
if (waveCount % 5 == 0 && waveCount > 0 && waveCount <= 50)
{
//yield return new WaitForSeconds(shopWait);
shopPanel.SetActive(true);
}
You can test whether the remainder of the division by 5 is 0, which means that the number is divisible by 5.
if (waveCount % 5 == 0 && waveCount >= 5 && waveCount <= 50)
C# performs integer math on integer number types (int, long, uint, ...).
Example:
13 / 5 = 2
I.e. you never get a decimal fraction part. The complementary operation is the modulo operation. It gives you the remainder of this division:
13 % 5 = 3
I.e., 13 / 5 is 2 plus remainder 3. Together, division and modulo operation allow you to perform the reverse operation.
(5 * (13 / 5)) + (13 % 5) =
(5 * 2 ) + ( 3 ) = 13
If you have irregular figures, quite different approaches are to use a switch statement:
switch (waveCount) {
case 5:
case 10:
case 15:
case 20:
case 25:
case 30:
case 35:
case 40:
case 45:
case 50:
shopPanel.SetActive(true);
break;
}
or an array of allowed values:
private static readonly int[] AllowedValues =
new int[] { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 };
if(Array.IndexOf(AllowedValues, waveCount) >= 0) { ... }
I'm walking through a Forloop 100'000 times. (that number can be diversified)
Every 1000th time I want do something specially, what I don't do in the other walkthroughs.
Something like that:
for (int i = 0; i < 100000; i++)
{
doTasks(); //Normal
if(i == 1000 || i == 2000 || i == 3000 || i == 4000 ) //and so on...
{
doSomethingElse(); //Special, For every 1000th walkthrough
}
}
What would be the most efficient way to accomplish that task?
Try with a modulo operator. Not sure about the C# syntax, but something like:
if(i % 1000 == 0)
{
//Do something
}
if (i != 0 && i % 1000 == 0)
It means if i mod 1000 is 0 (so on 1000, 2000, 3000, ...) but not on i == 0
if (i != 0 && i % 1000 == 0) {
doSomethingElse();
}
% is the modulus operator, returning the remainder of a division operation. If the remainder is zero then you have a multiple of 1000. However you need to exclude 0 specifically because 0 is evenly divisible by 1000 as well.
Using the modulo operator:
if (i % 1000 == 0) {
// do something...
will do what you want.
It divides by the given argument (in this case, 1000) and gives you the remainder. In this case you're interested in a remainder of 0. See the doc for the modulo operator here
I'm really nitpicking here, and potentially answering a dead horse, but do this:
if(i%1000 == 999) ...
Instead of comparing to 0 and avoiding the first iteration.
use operator % http://msdn.microsoft.com/en-us/library/6a71f45d.aspx