Related
I am writing a Whack-A-Mole game for class using HTML5, CSS3 and JavaScript. I have run into a very interesting bug where, at seemingly random intervals, my moles with stop changing their "onBoard" variables and, as a result, will stop being assigned to the board. Something similar has also happened with the holes, but not as often in my testing. All of this is completely independent of user interaction.
You guys and gals are my absolute last hope before I scrap the project and start completely from scratch. This has frustrated me to no end. Here is the Codepen and my github if you prefer to have the images.
Since Codepen links apparently require accompanying code, here is the function where I believe the problem is occuring.
// Run the game
function run() {
var interval = (Math.floor(Math.random() * 7) * 1000);
if(firstRound) {
renderHole(mole(), hole(), lifeSpan());
firstRound = false;
}
setTimeout(function() {
renderHole(mole(), hole(), lifeSpan());
run();
}, interval);
}
What I believe is happening is this. The function runs at random intervals, between 0-6 seconds. If the function runs too quickly, the data that is passed to my renderHole() function gets overwritten with the new data, thus causing the previous hole and mole to never be taken off the board (variable wise at least).
EDIT: It turns out that my issue came from my not having returns on my recursive function calls. Having come from a different language, I was not aware that, in JavaScript, functions return "undefined" if nothing else is indicated. I am, however, marking GameAlchemist's answer as the correct one due to the fact that my original code was convoluted and confusing, as well as redundant in places. Thank you all for your help!
You have done here and there in your code some design mistakes that, one after another, makes the code hard to read and follow, and quite impossible to debug.
the mole() function might return a mole... or not... or create a timeout to call itself later.. what will be done with the result when mole calls itself again ? nothing, so it will just be marked as onBoard never to be seen again.
--->>> Have a clear definition and a single responsibility for mole(): for instance 'returns an available non-displayed mole character or null'. And that's all, no count, no marking of the objects, just KISS (Keep It Simple S...) : it should always return a value and never trigger a timeout.
Quite the same goes for hole() : return a free hole or null, no marking, no timeout set.
render should be simplified : get a mole, get a hole, if either couldn't be found bye bye. If a mole+hole was found, just setup the new mole/hole couple + event handler (in a separate function). Your main run function will ensure to try again and again to spawn moles.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am curious as to if I am using too many if/else if statements.
I am writing a tic-tac-toe program using javascript, and to determine if the computer should block the player I am using about 9 if statements and I use about 9 when determining if there is 3 in a row.
For example:
if(r1c1V === xOrO && r1c2V === xOrO && r1c3V === xOrO)
{
is3InARow = true;
}
else if(r2c1V === xOrO && r2c2V === xOrO && r2c3V === xOrO)
{
is3InARow = true;
}
else if(r3c1V === xOrO && r3c2V === xOrO && r3c3V === xOrO)
{
is3InARow = true;
}
.
.
.
.
and so on.
So my question is, am I using too many if statements? or is there no better way to do this?
My friend was telling me that I shouldn't really use that many if statements, but I am not sure if he is true or not, I can understand why in some cases that it would be slower or bad, but I am not sure.
Thanks in advance!!
This is rather subjective, so is not really ideal for Stack Overflow.
What your friend is probably suggesting is that programs which use long if/else statements, nested ifs etc. are sometimes difficult to maintain, and are not always very readable. You can sometimes replace long if statements with a separate function, which can be much easier to maintain.
For instance in tic-tac-toe:
function checkRow(rowToCheck){
if (rowToCheck[0] === rowToCheck[1] && rowToCheck[1] === rowToCheck[2]){
return true;
} else {
return false;
}
}
Not to say that is perfect or even good code, but you can see how it would allow you to reduce the number of if statements in your code. It could be factored further:
function checkRow(rowToCheck){
var allMatch = true;
for (var i=0;i<rowToCheck.length && allMatch;i++){
allMatch = rowToCheck[i] === rowToCheck[0];
}
return allMatch;
}
That allows for rows of varying length, and cuts down of the if statements. Anyway I hope that explains some of the ways you can remove if statements.
Edit
Further in the future, I'd suggest that there is yet another, better way to check the equality of the elements in a row:
const o = 'o'
const x = 'x'
const rows = [
[o, x, x],
[x, x, x],
[o, o, x]
]
const rowIsEqual = row => !row
.some(square => square !== row[0])
const results = rows.map(rowIsEqual)
console.dir(results)
Programming is all about automating processes. You will not hear me say that the way you are doing this is wrong. If it works then it is oke. But of course it would be more beautiful if you could find a way to make it check everything automatically. Like looping through all x cords and just check if all of those are checked. This may not be easier, but it will be more extendable. If you'd ever wish to play a game on a ten by ten grid. then you would only have to say that that is the size of the field. Right now you would need to add all those other lines of code.
In general, yes, "too many" ifs are bad. Any problem can be solved just using ifs, but everything you see around you, functional programming, recursion, object modelling, is there to stop the if's getting out of control and leaving you with sprawling incomprehensible code. You should be more worried about the depth of nested ifs than the length of a sequence. Here's tic-tac-toe on rosetta code, if you want to see real cleverness.
There's no hard-and-fast rule. Do bear in mind that && and || are short-circutted meaning that evaluation stops once the result is known. That and the fact that you are able to order the if statements in any way you please means that you can optimise things by considering frequent comparisons first.
Always do what's clearest, and if performance is crucial, what's fastest.
So many apps are built with long if then else statements? Why? Wouldn't a dictionary be better? Look up the keyword and perform the associated action. I'm surprised I can't find a simple python library that does this for multiple back-ends including databases.
I guess using too many if- else statements decrease the readability of the program.You can use switch-case statement instead of using if-else statements.Just google switch-case in javascript and you will get many useful links to get an idea about it.
In your scenario, its not bad at all.
You can add return on your code if it can so that it won't execute other condition... JUST if its possible on your scenario.
In these cases we use 'Recursion'.
To answer your question; if you use to many if statements you are doing something wrong. You can use other methods to get the to goal you want.
Example:
you got a grid of 2,2 (0,1,2 and 0,1,2). So what you should do is create a algorithm that calculates the score. A very popular one is MiniMax.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 8 years ago.
Improve this question
I would like to avoid unresponsive javascript in all browsers.
Is it possible to write code with that in mind?
DETAILS: Problem is that currently there is a potential script block that executes fine in Chrome on my PC, but causing problems on IE (various versions). The worst thing is that I really don't know for sure if it is that script block at all. I will rewrite and solve that. However, I would like to know what exactly I should be avoiding while coding. This...
http://www.sitepoint.com/javascript-execution-browser-limits/
...is an interesting read but it's too general.
EDIT: I'm using jQuery/jQueryUI as well.
EDIT 2: There are patterns/principles to use to avoid particular problems. E.g. singleton pattern, PRG pattern, DRY principle... and such. Is there something like that for this kind of problem?
I've run into problems like this before as well.
The thing to keep in mind as you code, is where does my code begin execution, and where does my code end execution. For all of the time between those two points, the browser's UI thread is blocked, and the browser makers have understandably developed counter measures.
As far as what to avoid, avoid long, continuous loops.
Here's an extreme example:
function howManyMultiplesOfFourBelow(foo) {
var i = 0, j = 0;
while (i < foo) {
i++;
if (i % 4 === 0) {
j++;
}
}
return j;
}
If you pass 10,000,000 to that function, IE will definitely throw a fit. There is more than one way to program around this kind of situation; what I prefer is to break up the code using setTimeout/setInterval. After setting an interval and returning out of a function, we release the UI thread back to the browser, and the browser is in charge of executing the interval as often as we've requested (or as often as it is able).
I combine this with Futures/Promises; In particular, jQuery's implementation.
Using this style, the above example could be rewritten not to block the UI thread during the calculation by leveraging promises, and setInterval.
function howManyMultiplesOfFourBelow(foo) {
var deferred = $.Deferred(),
interval,
i = 0,
j = 0;
interval = setInterval(function () {
if (i >= foo) {
clearInterval(interval);
deferred.resolve(j);
return;
}
i++;
if (i % 4 === 0) {
j++;
}
}, 1);
return deferred.promise();
}
The first important difference is that this function no longer returns the answer, but instead a promise of an answer. So, consuming code might look like this:
howManyMultiplesOfFourBelow(10000000).done(function (multiples) {
//Update the DOM with the answer (multiples)
});
Returning to your question more generally, think about how much of your code must be run continuously, and if any of it could be delayed, or broken up in order to release the UI thread briefly.
I would like to edit my if else statement in javascript dynamically.
So after one if statement is used, it could be removed. I get this maybe isn't possible but after a search online failed, my curiosity begged me to ask.
For instance:
if (x > 200 && x % 25 === 0) {
doSomething1();
} else if (x > 300 && !inRange) {
doSomething2();
} else if (x > 400 && x % 7 === 0) {
doSomething3();
}
There are eight if else statements within this loop. The loop determines which object to create. There are 2000 objects created over the course of a couple minutes. If on average we reach the fourth statement before it breaks, then there are 8,000 calculations being performed just within this one set of statements.
I want to streamline the script for speed and again, curiosity if we can actually write javascript dynamically without using separate functions etc. After an if statement fails, it is often not required anymore. The next statement could I suppose, include code to remove its predecessor dynamically. This might save 3 or 4 thousand calculations - not huge I know, but worthy of consideration given that there are lots of other things going on as well.
Is there a way to remove them dynamically or does anyone have any tricks or patterns up their sleeves?
Also, even if this is not available in js, what would this be called?
No. And the need for such would indicate poor design.
You should use a conditional expression to determine when which code segment should be run, as you mention. If you pass a certain threshold within your code after which you no longer want a condition to be executed in your loop, why not simply break the loop and have a new code block handling the doSomethingElse clause. If you're using setInterval, that's the point at which you would call clearInterval, and then trigger some new action if necessary. Anyway, running a single (or even a few) simple conditional statement doesn't add much overhead, and isn't likely to be the limiting factor in your optimization anyway.
Ignoring the fact that I doubt this is a bottleneck in modern browsers that JIT the JavaScript (CPUs are very good at predictive branching) as shown because simple number comparison is not going to be expensive even in large iterations with smart predictions once it's compiled.
You can do this by injecting a different function:
checker: function(x) {
if (x > 200) {
doSomething1();
}
else if (x > 300) {
doSomething2();
}
else if (y > 400) {
doSomething3();
}
}
Can be changed to
checker: function(x) {
if (x > 200) {
doSomething1();
}
else if (x > 300) {
doSomething2();
this.checker = smallerChecker;
}
else if (y > 400) {
doSomething3();
}
}
function smallerChecker(x) {
if (x > 200) {
doSomething1();
}
else if (y > 400) {
doSomething3();
}
}
Fundamentally, you simply need to make the behavior injectable, and then you change it however you see fit. Be-it by replacing the function doing the checking outright (the functional way) as I did above, or enabling an object to replace it (the OO way).
Why would you want to remove them dynamically? Altering the code dynamically is unnecessary and a bag of worms that's overdoing it for this situation. You should be using a flag.
I'll answer separately for whether you're trying to skip a large group of if statements, or an individual if statement.
Foreword
As mentioned in the comments on your question, run profiling to make sure you know where your performance problems are!
You mention your aversion to simply using boolean flags to make an if statement not run in your answer. This is fine, and it's what people normally do. This should not be an actual performance concern, and profiling will probably show your performance problems lie elsewhere. If they don't and this boolean flag check is genuinely your bottleneck - you have bigger problems, such as expecting too much from your JavaScript code, or that you didn't use the profiling tool correctly, or misinterpreted its results.
If you're trying to avoid running the body of an if statement, or its conditions, those are a bigger performance concern to you than the boolean flag check itself.
For skipping a large group of if statements
Wrap your bunch of if statements in a condition.
if (runBunchOfIfStatements) {
// all those if statements here
}
When you're past the point of wanting those if statements to run, set the runBunchOfIfStatements flag to false (of course, you should probably pick a more meaningful name than that).
That said, 8 or 9 if statements is a code length issue, and more than likely means nothing at all for performance concerns - unless those if statements happen to involve very intensive checks. If you're worried just because there's a lot of if checks, you're probably looking in the wrong place.
For individual if statements
Say you have only one if statement you want to skip. You had this code in your answer:
} else if (x > 300 && !doneSomething2) {
doSomething2();
doneSomething2 = 1;
}
This is fine. You're just making a tiny check: see the foreword. Look elsewhere for your performance concern. It could be rewritten slightly to more closely follow convention (which I'm about to get to), but in this situation, the change will have negligible impact.
Let's take a situation where there is actually a performance concern here. Suppose that instead of checking x > 300 you're doing something more intensive like calculateSeveralSquareRoots(). Generally, you do take this approach, but you rearrange it like this:
} else if (needCalculations && calculateSeveralSquareRoots() {
// do stuff
needCalculations = false;
}
The difference here is the needCalculations flag comes first, not second. JavaScript's comparison operators have short circuit evaluation. This means that when evaluating a && b, if a is false, b never even gets checked - we already know the result will be false. If the flag comes first, that means calculateSeveralSquareRoots() never gets run, and you save time on the check.
If the flag came second, then you're potentially wasting a lot of time on that function for a condition that might almost always resolve to false anyway thanks to that flag.
So in your original, you could have the flag come before the x > 300 evaluation, just to follow convention. But again... if an if statement like this is a real and significant performance concern for you, then you have bigger issues.
Order them in order of likelihood (so if >400 is most common, check for that first, and if x<200 is next most common, check for that, etc.) The example code is in order of increasing boundaries.
Next, your code doesn't show it and you just imply it, this is in a loop. (And if it isn't a loop, then this isn't a perf issue of interest) You could try fancy loops like Duff's device.
And figuring out what code can be changed to use more native API's is going to make a magical difference, whereas code optimizations like this will likely make only a marginal difference.
If you want it to be dynamic, you could always have a collection of conditions associated with actions and as soon as executed, these gets removed from the collection. However, I doubt it will lead to faster code execution, but you would have to create a jsperf test to know for sure.
DEMO: http://jsfiddle.net/a2ZEj/1/
function doSomethingA() {}
function doSomethingB() {}
var doOperation = (function doOperation() {
var operations = [
{
check: function (someArg) {
return someArg > 100;
},
exec: doSomethingA
},
{
check: function (someArg) {
return someArg > 100 && someArg < 200;
},
exec: doSomethingB
}
];
return function (someArg) {
var i = 0,
len = operations.length,
item;
for (; i < len; i++) {
if ((item = operations[i]).check(someArg)) {
item.exec();
operations.splice(i, 1);
console.log('executed ' + item.exec.name);
return;
}
}
};
})();
doOperation(101); //calls doSomethingA
doOperation(101); //calls doSomethingB
doOperation(101); //does nothing
You can create a method as below and create dynamic conditions
function buildCond(lhv1,rhv1,lhv2,rhv2)
{
var condition1,condition2;
condition1 = condition2 = '';
if(rhv1 !== -1){
condition1 = lhv1 + " == " + rhv1 + " && ";
}
if(rhv2 !== -1){
condition2 = lhv2 + " == " + rhv2 + " && ";
}
return condition1 + condition2;
}
And then call this method with eval to execute
if(eval(buildCond(var1,value1,var2,value2)) === true){
//do stuff
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
Whenever I think of using the while loop, I don't see why I can't just use an if statement instead. I know that a while loop runs 'while' a given statement is true, but if the condition is terminated inside the block instantaneously, then I cannot visualize anything happening 'while' something is true. If anyone can give me examples of how/why I should use a while loop. It would be very appreciated.
I'm going to try to give you a very high-level answer because I think it will be easier to grasp intuitively.
Think of all algorithms as recipes. A typical recipe might have parts that look like the following:
If the peanut has a shell, separate it from the shell
Beat an egg until it is whipped and bubbly
Take 5 onions and chop each of them in half
These types of directions have you do tasks in different ways.
The first one is really an "if" statement. You do something if a condition (peanut has a shell) is true. You literally do:
if (not shelled) {
shell the peanut! // happens once
}
The second one is a while loop. You beat the egg while it is not whipped and bubbly. You do the same thing over and over (whipping) continuously, and you look at it (over and over) when doing this to check and see if it has turned very bubbly. Once it gets bubbly and whipped enough, you stop. When you stop it is because you have passed your "While" condition. An important thing to note is that before you start, you don't necessarily know just how many "beats" of an egg it takes to get it whipped. You just have to do it many times and check (with your eyes) many times. You literally do:
while(not whipped enough) {
beat egg! // happens over and over
}
Just like in recipes, you don't want someone doing a certain action until the end of time, so you must always make sure your while loops have sensible stopping conditions. Most while loops depend on something changing inside of the loop and will stop when that thing has changed enough.
The third recipe example is a for loop. For each onion you have (5) you do something once to that one onion. You literally do:
for (onions 1 to 5) {
Chop an onion! // done 5 times total, once per onion
}
while is a looping construct, not just another form of if
var i = 0;
while ( i < 10 ) {
//this stuff will happen until
//i < 10
// usually you iterate the counter so it
// eventually breaks the loop because
// i < 10 is no longer true
i++;
}
this does the same thing as this
for (var i = 0; i < 10; i++) {
//this stuff will happen until
//i < 10
}
Good use case for while
generally a for loop is used when the number of iterations that need to take place is known, so generally when you're iterating over an array and you know the length of the array for is a good choice because you can set the amount of iterations explicitly.
a better use case for while is when the amount of iterations is not static (known) and/or you are waiting for an event to occur to break the loop.
while will keep running until the condition becomes false.
If the condition is still true at the end of the block, the loop will run all over again.
if will only run once.
Well an if statement will not loop back around. It will only ever happen once unless you put it in a loop. A while statement will happen more than once as long as the statement is still true.
A while loop will execute over and over as long as the conditions are met, being that it will go to infinity if the condition never changes.
An if will execute once when the condition is met
If you wanted to create an infinite loop a while loop will do the trick
var done=false;
while(!done){
alert("I am annoying");
}
The for statement can be simulated with a while:
for(var i=0; i<length; i++) {}
// is the same as
var i=0;
while(i<length) {
// stuff
i++;
}
It is also used for loops like:
while(true) {
// stuff... (like waiting for user input, analyzing some data until
// it hits a brick wall and needs to quit)
if(some_condition) {
break;
}
}
Or for other stuff:
while(a != b) {
if(a > b) {
a -= b;
} else {
b -= a;
}
} // find the GCD of a and b
As you can see, it's very different from if, and solves other problems.