If Conditionals Inside of For Loop - javascript

I'm looking for insight into my if conditionals within my for loop. Currently, when I execute this function, the initial if conditional outside of the for loop runs, then the for loop starts. My test data has a length of 12, so the for loop runs the if (length > 10) conditional twice, and then runs the else if (length == 10) conditional. However, then it stalls and won't execute the next else if conditional (else if (length > 3 && length <=10 && mergedGroup != [])).
I think the issue lies with mergedGroup != [] but I'm not sure how to say "don't execute this conditional unless length > 3 and length <= 10 and mergedGroup array isn't empty."
Assume all functions and variables inside this executeFullRun function are built and correct (I've tested them line by line in the console, just having issues putting them into one function to run all of them together).
Any insight?
function executeFullRun(players) {
if (group1 != [] && group2!= []) {
makeGroups(players);
}
var length = group1.length + group2.length;
for (i=0;i<length;i++) {
if (length > 10) {
while (group1.length + group2.length > 10) {
winTribalImmunity(group1,group2);
voteOffPreMerge(vulnerablePlayers);
console.log('Group Vote');
length -= 1;
console.log(length);
}
} else if (length == 10) {
if (group1.length + group2.length == 10) {
mergeGroups(group1,group2);
console.log('Merge Groups');
console.log(length);
}
} else if (length > 3 && length <=10 && mergedGroup != []) {
while (length > 3) {
winIndividualImmunity(mergedGroup);
voteOffPostMerge(vulnerableIndividuals);
console.log('Individual Vote');
length -= 1;
console.log(length);
}
} else {
if (length == 3) {
winGame(mergedGroup);
console.log('Winner!');
}
}
}
}

You can't compare an empty array to another empty array by doing someExistingArray != [].
They are completely different object references and therefore are never equal, regardless if contents and length are identical.
Check the array length instead
Try
if (length > 3 && length <=10 && mergedGroup.length) {
And
if (group1.length && group2.length) {

Related

The output of a fizbuzz function is undefined

I have a Javascript code that is not running in the console in Chrome. It is showing "Undefined" when I call the function.
let output = [];
let count = 1;
function fizzBuzz() {
while (count <= 100) {
if (count % 3 === 0 && count % 5 === 0) {
output.push("FizzBuzz");
} else if (count % 3 === 0) {
output.push("Fizz");
} else if (count % 5 === 0) {
output.push("Buzz");
} else {
output.push(count);
}
count++;
}
}
I am expecting it to output an array of numbers up to 100 but inserting "Fizz" for multiples of 3, "Buzz" for multiples of 5, and "FizzBuzz" for multiples of both 3 and 5.
You have the following code
let output =[];
let count = 1;
function fizzBuzz() {
while(count<=100) {
if(count % 3 === 0 && count % 5 === 0){
output.push("FizzBuzz");
}else if (count % 3 === 0){
output.push("Fizz");
}else if (count % 5 === 0){
output.push("Buzz");
}else{
output.push(count);
}
count++;
}
}
which you are executing by calling fizzBuzz(). You're getting undefined because when you call fizzBuzz() in the console you're seeing the return value of the execution, which in your code doesn't ever return anything, so we get undefined.
You have two options.
Return output at the end of your function, outside of the while loop. In this case, it'd be best to also move your output and count variables inside, like so
function fizzBuzz() {
let output =[];
let count = 1;
while(count<=100) {
if(count % 3 === 0 && count % 5 === 0){
output.push("FizzBuzz");
}else if (count % 3 === 0){
output.push("Fizz");
}else if (count % 5 === 0){
output.push("Buzz");
}else{
output.push(count);
}
count++;
}
return output;
}
We move the output and count declarations inside so that every time we call fizzBuzz() we start from scratch. If we kept them outside, then if you called fizzBuzz() twice, we'd see the results from the first call in the results from the second call as well.
Your second option is to call fizzBuzz() with how your code currently is, and then print the value of output. I think you're just making a simple mistake and don't realize that your fizzBuzz doesn't return anything.
fizzBuzz();
console.log(output);
or, if you're executing this in your browsers developer console then
fizzBuzz()
output
You are missing a return statement for the output
let output =[];
let count = 1;
function fizzBuzz() {
while(count<=100) {
if(count % 3 === 0 && count % 5 === 0){
output.push("FizzBuzz");
}else if (count % 3 === 0){
output.push("Fizz");
}else if (count % 5 === 0){
output.push("Buzz");
}else{
output.push(count);
}
count++;
}
return output;
}
console.log(fizzBuzz());
If you want run your code without getting undefined then you can use var instead of using 'let'. Due to the variable block scope you are getting undefined.
Just replace let with var.
Then return output variable in your function body. use console.log(your function name)

FizzBuzz is it possible make my solution shorter?

I tried to make 3 conditions in one array.forEach, but this give me incorrect output. Is it possible to short my code to one array.forEach? Have 3 conditions inside it?
var array = []; // create empty array
for (var i = 1; i < 101; i++) {
array.push(i); // write in array all values of i, each iteration
}
array.forEach((number) => {
if (array[number] % 3 === 0 && array[number] % 5 === 0) {
array[number] = "FizzBuzz";
}
});
array.forEach((number) => { //
if (array[number] % 3 === 0) {
array[number] = "Fizz";
}
});
array.forEach((number) => {
if (array[number] % 5 === 0) {
array[number] = "Buzz";
}
});
for (let i = 0; i < array.length; i++) { //output array elements
console.log(array[i]);
}
First pointer: that's a lot of whitespace.
Second pointer, rather than creating an array then cycling through that array, you can do it all in one loop, using the if....else block; something like this:
for (var i = 1; i < 101; i++) {
if (i % 3 === 0 && i % 5 === 0) {
console.log("FizzBuzz");
}
else if (i % 3 === 0) {
console.log("Fizz");
}
else if (i % 5 === 0) {
console.log("Buzz");
}
else {
console.log(i);
}
}
You are "walking over" the Array multiple times.
IMHO the most important Array Method to learn is Map:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Which "walks over" the Array and returns a new value for that Array index
let arr = Array(100)
.fill((x, div, label) => x % div ? "" : label) //store Function in every index
.map((func, idx) =>
func(++idx, 3, "Fizz") + func(idx, 5, "Buzz") || idx
);
document.body.append(arr.join(", "));
fill takes a single Object, it is not executed 100 times!
Since JavaScript Functions are Objects this code declares a function once
Note the ++idx because we want to start at 1, not 0
In JavaScript ""+"" is a Falsy value, thus it returns the idx value for non-FizzBuzz numbers
More Array Methods explained: https://array-methods.github.io

finding lowest number between its 2 neighboor in an array

I want to exectute a function, preferably inside the forEach, for every element that is surrendered by 2 higher or equal number, or if its first or last element, just compared to second, or second last number.
I come up with this code, but I'm sure there is a better way:
var Pointdata = [98,59,39,0,48,85,19,43,3,98,65,100];
Pointdata.forEach(function(Current,i,array){
if (Current <= array[i+1] && Current <= array[i-1]) {
DrawPoint(Current,i,array);
}
else if (Current <= array[i+1] && i == 0) {
DrawPoint(Current,i,array);
}
else if(Current <= array[i-1] && i+1 == array.length) {
DrawPoint(Current,i,array);
}
function DrawPoint(Current,i,array) {
// marks peak points of canavas chart.
}
You could use just a single condition inside, Current is a.
if ((i + 1 === array.length || a <= array[i + 1]) && (i === 0 || a <= array[i - 1])) {
DrawPoint(a, i, array);
}
What about this?
for (i = 1; i < array.length - 1; i++) {
var Current = array[i];
if (Current <= array[i+1] && Current <= array[i-1]) {
DrawPoint(Current,i,array);
}
}
Couple of benefits:
You can skip edge cases like start and end indices
Only one conditional to think about
But if you want to keep those edge cases you can write them all in one if block separating them by or conditions like if ((Current <= array[i+1] && Current <= array[i-1]) || (Current <= array[i+1] && i == 0) || (Current <= array[i-1] && i+1 == array.length))
function markPeaks(data, draw) {
var xs = [Infinity].concat(data).concat(Infinity)
xs.forEach(function(x, i, array) {
if (Number.isFinite(x)) // skip first and last
if (array[i-1] >= x && x <= array[i+1]) // n-1 ≥ n ≤ n+1
draw(x, i-1, array) // minus1 because of 1st 'helper' Infinity
})
}
markPeaks(/*pointdata, /*drawpoint*/)

How NOT to break a function/loop on returning a value (Js)

Hey so I am making a 2D tile game, or really I am just messing around. I have made the map from an array, where 0 represents nothing, and other characters represents a walkable tile.
var map=[["t","t","t","t","t","t","t","t","t","t","t","t","t","t","t","t","t","t","t","t"],
["l","1","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","b","r"],
["l","r","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","r"],
["l","1","t","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","l","r"],
["l","1","1","t","t","t","t","t","t","t","t","t","t","t","t","r","0","0","l","r"],
["l","b","b","b","b","b","b","b","b","1","1","b","b","b","b","b","t","t","b","r"],
["0","0","0","0","0","0","0","0","0","l","r","0","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","0","0","l","r","0","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","0","0","l","r","0","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","0","l","1","1","r","0","0","0","0","0","0","0","0"],
["0","0","0","0","0","0","0","l","1","1","1","1","r","0","0","0","0","0","0","0"],
["t","t","t","t","t","t","t","1","1","1","1","1","1","t","t","t","t","t","t","t"]];
On screen it looks like this
You see my moveable character here as well.
Now I have come this far, and I'd like my character to collide with the empty tiles represented as the value of 0 in my map array.
This is my code for checking collision (brackets are correct in the script):
function collisioncheck(ind){
for(var i in map){
for(var j in map[i]){
if(yass==true){
if(map[i][j]==0){
if(ind==0 && playerPosX==j*32+32 && playerPosY>i*32-32 && playerPosY<i*32+32){
return false;
}else if(ind==1 && playerPosX==j*32-32 && playerPosY>i*32-32 && playerPosY<i*32+32){
return false;
}else if(ind==2 && playerPosY==i*32+32 && playerPosX>j*32-32 && playerPosX<j*32+32){
return false;
}else if(ind==3 && playerPosY==i*32-32 && playerPosX>j*32-32 && playerPosX<j*32+32){
return false;
}else{
return true;
}
}
}else{
return true;
}
}
}
var yass=false;
function exist(){
for(var i in map){
for( var j in map[i]){
if(map[i][j]==0){
yass=true;
break;
}
}
}
So, this works. But only for the first 0 in the map. My problem is that the return statements breaks the for-loop and function. So my character will not collide with any other blank tile but the first one.
I will have to rewrite this, but is there any smart solution to this?
Link to jsfiddle here (Character not visible)
You're on the right track, your loop only runs for one iteration because you always return something after an iteration. However, you should only call return when you know the final result, because - as you said - it will exit the function.
It is correct to call 'return false' right away after a collision is detected, because if the player collides with at least one block, then there is a collision. On the opposite, 'return true' should only be called when you are sure that there are no collisions at all on the entire board, and you need to test every block on the map before you can confirm this.
function collisioncheck(ind) {
for (var i in map) {
for (var j in map[i]) {
if (yass == true) {
if (map[i][j] == 0) {
if (ind == 0 && playerPosX == j * 32 + 32 && playerPosY > i * 32 - 32 && playerPosY < i * 32 + 32) {
return false;
} else if (ind == 1 && playerPosX == j * 32 - 32 && playerPosY > i * 32 - 32 && playerPosY < i * 32 + 32) {
return false;
} else if (ind == 2 && playerPosY == i * 32 + 32 && playerPosX > j * 32 - 32 && playerPosX < j * 32 + 32) {
return false;
} else if (ind == 3 && playerPosY == i * 32 - 32 && playerPosX > j * 32 - 32 && playerPosX < j * 32 + 32) {
return false;
}
// else: do nothing. (i.e. let the loop run for the next block)
}
} else {
return true;
}
}
}
return true;
}
What we do here is go through all the blocks, if we find a collision we return false and exit the function. We only reach the 'return true' statement if we went through all the blocks without finding any collision, which is exactly what you want.
You need to use continue instead of return in the last else of your main if/else block on line 15

Modulo in If statement being treated as statement

I am trying to write a javascript program that will count to 100, however, for every number divisible by 3, it will instead say 'divisible by 3' instead of displaying number
I'm using modulo to find out which numbers are divisible by 3 but my if statement is being treated as a statement rather then a conditional.
https://jsfiddle.net/gyoyfv7L/
My Code
var i = 1;
while (i < 101){
if(i % 3 = 0){
$("#main").append("divisible by 3");
}
else{
$("#main").append(i + '<br />');
}
i++;
}
= is for assignment. You want == or === for equality checking.
if(i % 3 == 0){
// ------^^
or
if(i % 3 === 0){
// ------^^^
== is "loose" in that it does type coercion using JavaScript's (sometimes surprising) rules. === is "strict" in that it will always be false when comparing values of different types.
Side note: When you have a loop consisting of an initialization of a control variable, a test of that variable, and an unconditional update of that variable at the end, it's better to use the idiomatic loop construct for that (for) rather than while:
for (var i = 1; i < 101; i++) {
if(i % 3 == 0){
$("#main").append("divisible by 3");
}
else{
$("#main").append(i + '<br />');
}
}

Categories

Resources