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) { ... }
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
This question already has answers here:
How can I get every nth item from a List<T>?
(10 answers)
Closed 5 years ago.
I have this loop which is performing a simple task for me every time my variable is a multiple of 3, currently I have to create a big loop which contains every multiple of 3 with a logical OR (3, 6, 9, ...). I am wondering if there is a more efficient way of doing this.
This is my code snippet:
if (waveCounter == 3 || waveCounter == 6 || waveCounter == 9 || waveCounter == 12)
{
amount = 0.03f;
dayNight.lightAmout = amount;
dayNight.light.intensity = Mathf.Lerp(dayNight.light.intensity, dayNight.lightAmout, fadeTime * Time.deltaTime);
}
else
{
amount = 1f;
dayNight.lightAmout = amount;
dayNight.light.intensity = Mathf.Lerp(dayNight.light.intensity, dayNight.lightAmout, fadeTime * Time.deltaTime);
}
My objective here is to get rid of writing those multiples of 3 in the if statement and still achieving the same goal every time my waveCounter variable is the next multiple of 3.
if((waveCounter % 3) == 0)
Modulo arithmetic: it divides a number by 3 and checks for the remainder. A number that is divisable by 3 has no remainder (and thus ==0)
Use the modulus operator, which, in simple terms, gets the remainder after division.
https://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx
If the remainder is 0, then you know the number is divisible by 3:
if(waveCounter % 3 == 0)
{
//do something
}
This problem can be solved with the modulo (or division remainder) operator as follows.
if (0 == waveCounter % 3)
{
// do stuff
}
else
{
// do other stuff
}
Is there any way to have a int value that is multiple values?
Under here you can see the code, im doing a minigame as a proof of concept.
currently i have x happen at loop number 4 and y happens at loop number 9.
Is there any way to repeat theese actions on other loops wihout maing it a huge mess like this: i == 4||i == 14 || i == 18
what im trying to ask is if its possible to just write i == a
and then have a be multiple values.
If you havent figured already, im quite the beginner at C#, so if you can explain it in a easy to understand way, i would be very thankfull.
If what i wrote is a bit hard to understand, then im sorry for not being a native english speaker, just ask if you're unsure of what i mean.
for (int i = 0; i < 50; i++)
{
string input;
input = Console.ReadKey().Key.ToString();
Console.Clear();
if (input == "A") Animation.frame1();
else Animation.fall();
if (i == 4) Animation.blocklow2();
if (i == 9) Animation.blockhigh2();
input = Console.ReadKey().Key.ToString();
Console.Clear();
if (input == "W" && i == 4) Animation.blockjump();
if (input == "S" && i == 9) Animation.blockduck();
if (input == "D" && i != 4 && i != 9) Animation.frame2();
else if (input != "W" && i == 4) Animation.fall();
else if (input != "S" && i == 9) Animation.smack();
if (i == 3) Animation.blocklow();
if (i == 8) Animation.blockhigh();
}
You could do if (new int[] { 4, 14, 18 }.Contains(i)) to check for multiple values.
Store a list of ints that you want to check against and then use .Contains
List<int> frame2ints = new List<int>{4,9};
if (input == "D" && !frame2ints.Contains(i)) Animation.frame2();
In certain situations you can perform bitwise tests to see whether some bits are set in your number:
if ((x & 4) != 0)
{
// This case covers numbers
// 4, 5, 6, 7, 12, 13, 14, and many others...
}
General answer to your question is NO, and it only makes sense to use additional knowledge about the values you are testing and then use that knowledge.
Another option is to test whether a number belongs to a sequence, like HHLV said in other answer.
So, how did you get to values 4, 14 and 18?
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