I have these If statements based off of a Math.random() function and it works for the most part but sometimes nothing evaluates to true
I've tried changing the numbers that the Boolean statements compare too and I've tried changing the number that Math.random is multiplied by
var dodge = {
dodgeValue: function() {
return Math.floor(Math.random() * 10) + 1
},
roll: function() {
console.log('ROLL AFTER DODGE?'); //DELETE THIS
if (this.dodgeValue() <= 5) {
console.log('Ball Rolls to Person One');
dodgeBall.ball.position = 'on ground';
dodgeBall.personOne.ball();
}
if (this.dodgeValue() >= 5) {
console.log('Ball Rolls to Person Two');
dodgeBall.ball.position = 'on ground';
dodgeBall.personTwo.ball();
}
},
This is one of the two parts that have the same problem the other one when copied and pasted was really jumbled so I left it out but if anyone had any ideas on why this is happening or how to fix it that would be great.
You're generating two random numbers. A new one each time you write this.dodgeValue().
Additionally, if the value is exactly 5 then both branches will run - this probably isn't intended behaviour.
You should do something like let dodge = this.dodgeValue(); and then use if( dodge <= 5). Additionally, you should use else rather than an "if A then ... if not A then ..."
That's because you call dodgeValue twice, which calls random twice.
Ignoring the fact that random numbers in computers are actually psudeorandom for a second, let's look at what happens when you call dodgeValue twice to get two random numbers like you have.
You could conceivably get the following numbers from this code:
4
6 8
6 2
In the first case, the first if will be true and execute, since 4 <= 5.
The first if will be false, but the second if will be true, since 6 > 5 (first if is false) and 8 >= 5 (second if is true).
Now, what happens in that third case? Both if's will be false, since 6 > 5 (first if is false) and 2 < 5 (second if is false).
If that is how you intend for it to work (which I'm assuming not), keep your code as is. If not, you have 2 options depending on your needs.
If you need to store the output of dodgeValue for later, you can use a variable:
var dodge = {
dodgeValue: function() {
return Math.floor(Math.random() * 10) + 1
},
roll: function() {
console.log('ROLL AFTER DODGE?'); //DELETE THIS
var val = this.dodgeValue();
if (val <= 5) {
console.log('Ball Rolls to Person One');
dodgeBall.ball.position = 'on ground';
dodgeBall.personOne.ball();
}
if (val >= 5) {
console.log('Ball Rolls to Person Two');
dodgeBall.ball.position = 'on ground';
dodgeBall.personTwo.ball();
}
},
If you just need them to be opposites of each other, then just use an else clause instead.
var dodge = {
dodgeValue: function() {
return Math.floor(Math.random() * 10) + 1
},
roll: function() {
console.log('ROLL AFTER DODGE?'); //DELETE THIS
if (this.dodgeValue() <= 5) {
console.log('Ball Rolls to Person One');
dodgeBall.ball.position = 'on ground';
dodgeBall.personOne.ball();
} else {
console.log('Ball Rolls to Person Two');
dodgeBall.ball.position = 'on ground';
dodgeBall.personTwo.ball();
}
},
Related
I'm using setInterval to check every second for document.hasFocus(), so every second it returns true or false.
setInterval(function() {
console.log(document.hasFocus());
}, 1000);
When the return of true is equal to or greater than 15, I would like to do something. I wrote the code below (which obviously doesn't work) to make it easier to understand what I want to achieve.
if (document.hasFocus()) ≥ 15 {
do something
}
Could anyone help me with this?
document.hasFocus() returns a boolean not a number.
So you can use a counter and increment it each time document.hasFocus() returns true.
Then you can test the counter.
As far as I can see, you just want to count for 15 times before calling some function or executing some logic, the variable that is responsible for counting represents your application state. So we will call it count
let count = 0;
then we just increment count while the condition is met every second, until finally we stop the interval when the condition is met
let intervalToken = setInterval(function checkDocument(){
if(document.hasFocus()){
count = count + 1;
if(count > 15){
clearInterval(intervalToken); // stop intervale here
callMyFunction(); // call your function here
}
}
}, 1000)
Simply add a counter like this:
let counter = 0;
if (document.hasFocus() && ++counter >= 15) {
alert('you did it!');
}
You just need a variable to count the number of times document.hasFocus().
let focusCount = 0;
setInterval(() => {
focusCount = document.hasFocus() ? focusCount + 1 : focusCount;
if (focusCount >= 15) {
console.log(focusCount);
}
}, 1000);
In the example below, I don't want to make a counter as a param. Rather, I just want to return '+ 1' each time so that what gets returned is the number of steps it takes. My issue lies with the base case. If I do return + 1, I get the correct number of steps plus one additional step so I tried just return but that delivers NaN. Is it even possible?
var numberOfSteps = function(num) {
if (num == 0) {
return;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
};
edit : The goal is to track how many steps it takes to reduce a number to 0. If it's even, divide by 2 or else subtract by 1. Ultimately, I want to return the number of steps it takes for any given number to get reduced to 0 following those rules
I hope the point has gotten through in the long comment thread and other answers that return + 1 is equivalent to return (+1), that is, return the integer positive one. And since there are no steps to take once you've reached zero, +1 is the wrong answer. Similarly, a plain return is functionally equivalent to return undefined. But undefined is not a number, and you're going to run into problems if you later try to add 1 to it. So the solution from the comments or other answers to return the correct number of steps, which in this case 0, will fix your code.
I would like to point out another way to solve this, though:
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (n % 2 == 0 ? n / 2 : n - 1)
console .log (numberOfSteps (12))
There are superficial differences here from the other solutions, such as using an arrow function, using a conditional statement (ternary) rather than if-statements, and using <= 0 instead of < 0 to avoid possible infinite loops on negative numbers.
But the fundamental difference is that this code only has one recursive branch. I think this is a better match to the problem.
We can think of this as a function which answers "How many steps does it take to reach 0 from our input number if each step cuts even numbers in half and subtracts one from odd ones?" Well that logically leads to a base case (we're already at 0) so have to return 0, and a recursive one (we're at some positive integer) so have to add 1 to the total steps required from our next entry.
By doing this single recursive call and adding one to the result, we make it clearer what the recursion is doing.
If this is unclear, then this alternative might show what I mean:
const takeStep = (n) =>
n % 2 == 0 ? n / 2 : n - 1
const numberOfSteps = (n) =>
n <= 0
? 0
: 1 + numberOfSteps (takeStep (n))
Think you just need to return 0 when it's...zero.
var numberOfSteps = function(num) {
if (num == 0) {
return 0;
} else {
if (num % 2 == 0) {
return 1 + numberOfSteps(num/2);
} else {
return 1 + numberOfSteps(num - 1);
}
}
}
return + 1 maybe doesn't do what you think it does: it returns the number 1. + here means positive not negative, there is no addition or subtraction going on. It will also give you one too many steps.
return; by itself returns undefined, which when converted to a Number, translates to NaN, because, well, it's not a number.
I want an item to appear every now and then. Usually one item appear that give +10 score but i want a rare item to appear at a random chance that give more points.
Ive already tried something that looks like this except repurposed for what i need
if (Math.random() * 100 < 80) {
sendMessage("hi");
}
else if (Math.random() * 100 < 5) {
sendMessage("bye");
}
I expected for a gold thing to appear but it never did
You should probably first determine what you want the probabilities of these events to be and how frequently you want them to occur.
Presumably you'd have some short time interval between these events, say for example 60 seconds. And then the chance of a rare one could be 5%. So your example at the moment seems to be a bit off because of your else statement.
const rand => Math.rand() * 100;
if(rand() <= 80){
// 80% of any reward appearing
if(rand() <= 5){
// Give the super reward, 5% chance
} else {
// Give the regular reward
}
}
Hope that makes sense.
basically you need to calculate once the random probability and then assign the reward based on your logic.
const normalProbability = 80;
const epicProbability = 5;
const obtainReward = () => {
const calculated = Math.random() * 100;
if (calculated <= normalProbability && calculated > epicProbability) {
console.log(`normal probability to appear a common object... you got ${calculated}%`)
return calculated;
} else if (calculated <= epicProbability) {
console.log(`epic probability to appear a common object, you got ${calculated}%`);
return calculated;
}
console.log(`no reward because you got... ${calculated}%`);
return calculated;
}
console.log("starting the automatic process")
setInterval(() => obtainReward(), 3000);
I've been looking on how to make a simple coin flip script using JavaScript, and I've seen videos of people that seem to over-complicate things using 20 different elements or whatever you call them. What I set out to do is create a "magic 8 ball" kind of script but only using simple commands. I have it working so that I have a text box, then next to it is a button when pressed it will execute a function.
My problem:T
Instead of returning a number when using Math.floor(Math.random() * 4), I want to return the words like "yes" "no" "maybe" etc. Additionally, I was wondering what the () do in Math.random().
My code is below. The first statement works if nothing is typed in it says "please enter a question" but the rest doesn't.
function checkFunction() {
if (question.value == '') {
document.getElementById("fortune").innerHTML = "Please Enter A Question";
} else {
Math.floor(Math.random(data) * 4);
if (data == 0) {
document.getElementById("fortune").innerHTML = "Maybe";
} else if (data == 1) {
document.getElementById("fortune").innerHTML = "Try Again";
} else if (data == 2) {
document.getElementById("fortune").innerHTML = "Yes";
} else if (data == 3) {
document.getElementById("fortune").innerHTML = "No";
} else {
return "Invalid";
}
}
}
I don't care if it's long, I just want it to be simple. I don't want to have to define a bunch of variables and mess around with calling them up because I'm just trying to take it a step at a time. I'm basically trying to figure out the maximum potential of an if statement before moving on and learning new things.
I was wondering what the () do in Math.random().
Math.random() is a function and it takes no parameters. The () means it's a function. You are passing data to the function but the function will not use it because it is parameterless.
If you don't like to have that return:
function checkFunction() {
var arr = ['Maybe','Try Again','Yes','No'],
index = Math.floor(Math.random() * 5); //0 to 4
document.getElementById('fortune').innerHTML = (question.value=='')? 'Please Enter A Question' : (index<arr.length)? arr[index] : 'Invalid';
}
If you like to have the return use this:
function checkFunction() {
var arr = ['Maybe','Try Again','Yes','No'],
index = Math.floor(Math.random() * 5); //0 to 4
var tmp = (question.value=='')? 'Please Enter A Question' : (index<arr.length)? arr[index] : false;
if (tmp===false){
return 'Invalid';
}else{
document.getElementById('fortune').innerHTML = tmp;
}
}
Math.floor(Math.random(data) * 4);
ignores the parameter data because Math.random doesn't take a parameter. The expression statement evaluates to an integer value in range [0, 4). After execution data is still undefined (or whatever it was before).
You could use an integer random number generator function such as:
function randomInt( low, high) {
var range = high - low + 1;
return low + Math.floor( range * Math.random());
}
to return an integer in the inclusive range [low, high] when called.
I have a canvas game which calls a function incScore every time an action is performed in the game to increase the score.
Inside incScore I have a few if statements to draw a particular image to represent a level number on the canvas.
I also want to have a sound play once per level up. The way I've gone about things the lvlup sound will play every time the score matches the if statement.
Can anyone please help me get this so that the sound will only play once when the level changes and not again until the next level change? I'm also mention I'm using jQuery incase it has anything that could help me.
incScore(); //everytime an action in the game causes the score to increase
function incScore(){
if (scoreTotal < 500){
lvlimg = "L01";
drawLevel(lvlimg);
lvlupSound();
}
else if (scoreTotal > 500 && scoreTotal < 1000){
lvlimg = "L02";
drawLevel(lvlimg);
lvlupSound();
}
else{
lvlimg = "L03";
drawLevel(lvlimg);
lvlupSound();
}
}
You could shorten your function and use a semi static property to save the state. Using that, you can compare the current level to the previous and play a sound if they differ.
function incScore(){
incScore.level = incScore.level || 'L0'; //< initialize property
lvlimg = "L0" + scoreTotal < 500 ? 1 : scoreTotal < 1000 ? 2 : 3;
drawLevel(lvlimg);
if (incScore.level!=='L0' &&
incScore.level !== lvlimg) { lvlupSound(); };
// ^compare local level to current
incScore.level = lvlimg;
// ^ update local level
}
[edit, based on comment] The third line is a so called ternary, or conditional operator. See MDN. You can use more conditions.
To avoid playing a sound before the score has reached a first level, you could use
if (incScore.level!=='L0' && incScore.level !== lvlimg).
I've created a mockup jsFiddle
A simple solution could be comparing the current level to the old one, to detect when the level changed:
function scoreToLevel(score)
if(score < 500){
return 1
}else if (score < 1000){
return 2
}else{
return 3
}
}
function incScore()
var next_level = scoreToLevel(scoreTotal)
if(next_level !== current_level){
lvlimg = "L0" + next_level;
drawLevel(lvlimg)
lvlupSound()
}
}
The easiest solution is to factor the sound out of those if statements. If the levels are nice and regular like that(every 500 points) and the points always increase in a way that you will always land exactly on an even multiple of 500 when you level up, something like this should do:
if(scoreTotal % 500 === 0 && scoreTotal < 1001)
{
lvlupSound();
}
If you won't always land directly on the gate to the next level(maybe the player can earn anywhere between 1 and 15 points at a time) then you should be able to get by using something along the lines of this before you increment the player's score:
if( (scoreTotal % 500) > ((scoreTotal + increment) % 500)
{
lvlupSound();
}
if your level boundries are not regular like that obviously it gets a little bit more complex, but that should get you started.
That is because you have the in every statement for every score (which means from 0 to infinite).
You will need to write inner if statements such as;
if (scoreTotal < 500){
lvlimg = "L01";
drawLevel(lvlimg);
if(scoreTotal x times of each the level) // That means for each level completed
{
lvlupSound();
}
}
If your score increment is only 1, then only play the tone when the score equals the threshold for a new level.
If they can increase their score by more than 1, then you could pass the number of points in and check the score before and after to see if the numbers fall on each side of the threshold.
If that still doesn't work, some more info on the "level" and points would be appreciated.
Try something like this (demo):
var scoreTotal,
lastLevel = 0,
levels = [500, 1000, 2500, 5000, 10000, 25000, 50000, 75000],
currentLevel = 0,
lvlImg;
function incScore() {
while (scoreTotal > levels[currentLevel]) {
currentLevel++;
}
if (lastLevel !== currentLevel) {
lastLevel = currentLevel;
// gives a two digit number with a leading zero
lvlImg = ('0' + currentLevel).slice(-2);
drawLevel("L" + lvlimg);
lvlupSound();
}
}
Then you can easily add additional levels by adding the score cutoff to the levels variable.