Set function result to variable within same function on external javascript file - javascript

The following is not bringing the results of my function into a variable and into my html page... why?
EXTERNAL JAVASCRIPT
function damageRoll(min, max) {
'use strict';
document.getElementById("combatResult").innerHTML = damageFinal;
min = min || peacemaker.damageMin;
max = max || peacemaker.damageMax;
var damageFinal = damageRoll();
return Math.floor(Math.random() * (max - min + 1) ) + min;}
HTML
<div id="combatResult"></div>
<button onclick="damageRoll()">Fight</button>
EDIT
Going to read through everyone's answers but min/max probably not the issue. I failed to show they get their values from another external js file and are functioning as expected in other areas of my code. Thanks.
EXTERNAL JAVASCRIPT #2
var peacemaker = {
damageMin: 3,
damageMax: 5,
};

You probably want thing like this.
function damageRoll(min, max) {
'use strict';
min = min || peacemaker.damageMin;
max = max || peacemaker.damageMax;
var damageFinal = Math.floor(Math.random() * (max - min + 1) ) + min;
document.getElementById("combatResult").innerHTML = damageFinal;
}
First, the min and max modification should be put at the front of the function. You should also consider put the damageFinal variable declaration earlier in the function like the above example. Don't overuse JavaScript's variable hoisting feature.
Next, your original code results in a endless self invoking. I don't understand your intention, but it will be better not to use self invoking in your situation.
PS: You can make code even simpler by using es6
function damageRoll(min = peacemaker.damageMin, max = peacemaker.damageMax) {
var damageFinal = Math.floor(Math.random() * (max - min + 1) ) + min;
document.getElementById("combatResult").innerHTML = damageFinal;
}

Your damageRoll() calls do not actually contain the required parameters min and max. You must add items when you're calling it, like here:
<button onclick="damageRoll(min, max)">Fight</button>
and within the function itself:
var damageFinal = damageRoll(min, max);
You're recursively calling the function, without a base. Nothing is going to occur, because the function will never finish being called. You may want to look into this.

it looks like you are a beginner learner so i will explain what i did instead of just posting the right answer.
First of all, you should split your function to one that handle the click event and one the calculate the result. it's better that the second function will use inner cope only (don't use variable from outside the function)
so your code should look like:
// example values for object
const peacemaker = {
damageMin: 100,
damageMax: 100
}
function damageRollEvent(e) {
'use strict';
e.preventDefault();
var _peacemaker = {
min: min || peacemaker.damageMin,
max: max || peacemaker.damageMax
}
var damageFinal = damageRoll(_peacemaker);
document.getElementById("combatResult").innerHTML = damageFinal;
}
function damageRoll(_peacemaker) {
'use strict';
return Math.floor(Math.random() * (_peacemaker.max - _peacemaker.min + 1)) + _peacemaker.min;
}
damageRollEvent function handle the event and messing with the html.
damageRoll returns the value you expect for and doing pure programming work.
the html
<div id="combatResult"></div>
<button onclick="damageRollEvent($event)">Fight</button>
i didn't test the code but it should work.

This is the way you shall proceed without recursively calling the function, you shall add a helper function in the middle. From the HTML you shall call the helper. Anyway you have to find a way to resolve the 2 variablrs, min and max. See this..
function damageRoll(min, max) {
var damageFinal = Math.floor(Math.random() * (max - min + 1) ) + min;
document.getElementById("combatResult").innerHTML = damageFinal;
}
function throwMinMax(){
// You should Find a way to resolve the two variables below
// we have No idea where the peacemaker stuff come from
var min = peacemaker.damageMin;
var max = peacemaker.damageMax;
damageRoll(min,max);
}

Related

How to access the value of a math.random calculation?

I'm writing a program that simulates a card shuffler. The program should randomly selects a random image within an array and displays it to the screen. Then it deletes that image from the array before running again. The problem I'm having is storing the value of the randomized number so I can delete said array position from the array. I'm pretty sure the math.random calculation needs to be within a function, but I'm having a hard time using that value to randomize the array position while simultaneously storing that random value.
var shuffler = {
cards: [...]
displayCard: function() {
document.getElementById("card-1").style.backgroundImage = 'url(' +
shuffler.cards[shuffler.randomizer()] + ')';
},
randomizer: function() {
Math.floor(Math.random() * shuffler.cards.length) = randomized;
return this.randomized;
shuffler.cards.splice(randomized, 1)
}
}
shuffler.displayCard();
You cannot store the value correctly because following line is errorsome
Math.floor(Math.random() * shuffler.cards.length) = randomized;
= sign in programming is not like = in math. It just assigns the value of right side to left side. Thus, you should do it like this instead:
this.randomized = Math.floor(Math.random() * shuffler.cards.length);
There are two problems. First one is with assignment of randomized. See the line
Math.floor(Math.random() * shuffler.cards.length) = randomized;
Here the LeftHandSide of assignment expression is an expression which is wrong. It should be
let randomized = Math.floor(Math.random() * shuffler.cards.length);
The second problem is that you are using splice() after return move it before return
The last problem is that you are using the variable name inside the methods of the object. You should use this instead of shuffler. The final code will look like.
var shuffler = {
cards: [...]
displayCard: function() {
document.getElementById("card-1").style.backgroundImage = 'url(' +
this.cards[this.randomizer()] + ')';
},
randomizer: function() {
let randomized = Math.floor(Math.random() * shuffler.cards.length);
this.cards.splice(randomized, 1)
return randomized;
}
}
shuffler.displayCard();
In the code snippet you have you're returning before you splice from your array, making it dead code that's unreachable.
In terms of answering the title of this question, you're in the right spirits of just simply storying the random number as a variable, however you need to have proper syntax.
bro check your syntax
randomizer: function() {
Math.floor(Math.random() * shuffler.cards.length) = randomized;
return this.randomized;
shuffler.cards.splice(randomized, 1)
}
I think it will be
randomizer: function() {
this.randomized = Math.floor(Math.random() * this.cards.length);
this.displayCard(this.randomized);
shuffler.cards.splice(this.randomized, 1);
return this.randomized;
}
and you also need to declare randomized property in your shuffler object.
You also need to fix your displayCard method.
displayCard: function(index) {
document.getElementById("card-1").style.backgroundImage = 'url(' +
shuffler.cards[index] + ')';
}

JS create an array with unique random numbers

Full code looks like this, ideally we have 4 div boxes that need to be randomly filled with random numbers ansValue, one of them (rightAnsValue with its rightAnsId) is already done and works fine, I've managed to make it unique in comparison to others (code without commented section). But met a problem with making others unique, I keep having some identical values in my boxes. In comments is one way I tried to solve this, but pretty sure there is a much simpler and smarter solution that actually works. I would appreciate if you could help to find an understandable solution to this problem.
(P.S. I've seen similar questions but they are either too dificult or done without JS.)
function createAnswers(){
for(ansId=1; ansId<5; ansId++){
if(ansId!=rightAnsId){
for(i=1; i<10; i++){
digitArray[i-1] = i;
}
genNewRandNum();
// ansArray.length = 3;
// ansArray.push(ansValue);
// for(k=0; k<3; k++){
// if(ansArray[k] == ansArray[k+1] || ansArray[k] == ansArray[k+2]){
// genNewRandNum();
// ansArray[k] = ansValue;
// }else if(ansArray[k+1] == ansArray[k+2]){
// genNewRandNum();
// ansArray[k+1] = ansValue;
// }else{
// break;
// }
// }
if(ansValue!=rightAnsValue){
document.getElementById("box" + ansId).innerHTML = ansValue;
}else{
genNewRandNum();
document.getElementById("box" + ansId).innerHTML = ansValue;
}
}
}
}
The way I generate new numbers:
function genNewRandNum(){
rand1 = digitArray[Math.floor(Math.random() * digitArray.length)];
rand2 = digitArray[Math.floor(Math.random() * digitArray.length)];
ansValue = rand1 * rand2;
}
Replace your genNewRandNum() with below code. I have used IIFE to create a closure variable alreadyGeneratedNumbers thats available inside the function generateRandomNumber() thats returned.
So everytime genNewRandNum() is executed, it checks against alreadyGeneratedNumbers to make sure it always returns a unique between 1 and 9.
var genNewRandNum = (function(){
var alreadyGeneratedNumbers = {};
return function generateRandomNumber() {
var min = Math.ceil(1),
max = Math.floor(9);
randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
if(alreadyGeneratedNumbers[randomNumber]) {
return generateRandomNumber();
} else {
alreadyGeneratedNumbers[randomNumber] = randomNumber;
return randomNumber;
}
}
})();
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
Note: If you call genNewRandNum() for the 10th time it will throw error. So if you have a use case where you would need to reset it after all numbers from 1 to 9 are returned, then you need to add code to handle that
The easiest way to brute-force this is to use accept/reject sampling. You can do something like so:
uniqueRandomNumbers = function(n, nextRandom)
{
var nums = {}; var m = 0;
while(m < n)
{
var r = nextRandom();
if(! nums.hasOwnProperty(r))
{
nums[r] = true; m++;
}
}
return Object.keys(nums);
}
Here I'm using the fact that js objects are implemented as hashmaps to get a hashset. (This has the downside of converting the numbers to strings, but if you're not planning on imediately doing arithmetic with them this is not a problem.)
In order to get four unique integers between 0 and 9 you can then do something like:
uniqueRandomNumbers(4, function() { return Math.floor(Math.random() * 10); })
If you want something a little better than brute force (which probably isn't relevant to your use case but could help someone googling this), one option is to go through each element and either take or leave it with an appropriate probability. This approach is outlined in the answers to this question.

JavaScript scope issue/error

I got at brainteaser in my mailbox, it is supposed to take 20 minutes but apparently, I got stuck at scope that I crashed Chrome. The idea is that a string is provided to you. You then use the string to generate random sentences akin to lorum ipsum.
var words = "The sky above the port was the color of television, tuned to a
dead channel. All this happened, more or less. I had the story, bit by bit,
from various people, and, as generally happens in such cases, each time it
was a different story. It was a pleasure to burn.";
var wordList = words.split(' ');
var numWords = getRandomInt(2, 8);
var numSentinces = getRandomInt(8, 40);
var sentinces = [];
var sentince = [];
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function genSentinces() {
while (numWords > 0) {
sentince.push(wordList[getRandomInt(0, wordList.length)]);
numWords--;
}
sentince = sentince.join(' ');
console.log(sentince)
return sentince;
}
genSentinces();
genSentinces();
I am assuming that the scope of the sentence variable is wrong as it runs the first time but not the second time. I think I need to add a this somewhere.
Any help would be appreciated, as I can read code that has this in it but I apparently can't write code with this yet.
The main mistake is that you forget, that if you will modify global variable (all variables outside your functions can be called "global" regarding to this functions), it will not take the original value without your intervention. For example, if you declare new variable outside the function like var x = 0;, and then modify this variable from within the function like x = 1, this variable will be equal to 1 now.
You init sentince variable as array (var sentince = [];), but after the first execution of genSentinces function, this variable will be a string (because you're doing sentince = words.join(' ')). For this reason, I declared new array words inside the function, and I push words to it instead of pushing to global sentince array.
You use numWords-- to decrease the counter on every loop iteration, but numWords is a global variable and it will still equal to 0 after the first function invocation (it's why I added numWords = getRandomInt(2, 8) after the loop).
Here is the working example, feel free to ask, if anything isn't clear:
var words = "The sky above the port was the color of television, tuned to a dead channel. All this happened, more or less. I had the story, bit by bit, from various people, and, as generally happens in such cases, each time it was a different story. It was a pleasure to burn.";
var wordList = words.split(' ');
var numWords = getRandomInt(2, 8);
var numSentinces = getRandomInt(8, 40);
var sentinces = [];
var sentince = [];
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function genSentinces() {
var words = [];
while (numWords > 0) {
words.push(wordList[getRandomInt(0, wordList.length)]);
numWords--;
}
numWords = getRandomInt(2, 8);
sentince = words.join(' ');
console.log(sentince)
return sentince;
}
genSentinces();
genSentinces();
You changed variable 'sentince' from array to string and when you call function second time you call 'sentince.push(...' to string type and variable variable 'numWords' equal to 0 after first call.

Javascript functions as values and closure

I am grappling to understand functions as values, and closure in Javascript.
Consider the code;
function multiplier(factor) {
return function (number) {return number * factor; }
}
var i = multiplier(10);
What is i actually holding at this point? I know I could use i next by doing something like
console.log(i(5));
which would produce the value 50. But I'd still like to know what Javascript actually gives to i before this.
Consider the following two examples. The first you have given and the second one I provided.
In the first one might think that the returned function is
function (number) {return number * 10; }
But this isn't really the case even if it is easy to think of it that way. factor is saved as a reference to the parameter factor. So the function multiplier returns a function with a reference to the value you provided.
If the value of factor changes then the function result is different.
function multiplier(factor) {
return function (number) {return number * factor; }
}
var i = multiplier(10);
console.log('Example1',i(5))
function multiplier2(factor) {
setTimeout(() => {factor = 100}, 1000)
return function (number) {return number * factor; }
}
var i2 = multiplier2(10);
console.log('Example2',i2(5))
setTimeout(() => {console.log('Example2',i2(5))}, 1100)
var i = multiplier(10);
is actually var i = function(number){return number * 10;}
then when calling console.log(i(5));
you are calling
console.log(function(5){return 5* 10;})
i is actually a brand new function: function (number) {return number * 10; }
So if you have j = multiplier(10); actually i is not j, because they are 2 different functions
One more note is that, after i = multiplier(10); you no longer have factor as reference or as value anymore, factor already disappear from your i

JavaScript function will only work once

I have a JavaScript function that is triggered onchange. What it does is take the value from a input field and then add it to the value entered in another field and then display the answer in a different field.
It works fine the first time, but when I enter a new value and leave the field there is an error: TotalPurchasePrice is not a function
function TotalPurchasePrice(BuyinPrice, TopupAmount) {
var BuyinPrice
var TopupAmount
BuyinPrice = BuyinPrice.toString().replace(/\£|\,/g, '');
TopupAmount = TopupAmount.toString().replace(/\£|\,/g, '');
TotalPurchasePrice = (BuyinPrice * 1) + (TopupAmount * 1);
document.getElementById('tTotalPurchasePrice').value = TotalPurchasePrice;
}
Can anyone tell me why this would only work once?
This line :
TotalPurchasePrice = (BuyinPrice * 1) + (TopupAmount * 1);
replaces the TotalPurchasePrice function by a number. Then it's not a function, hence the error you have.
Use a different variable name :
var totalPrice = (BuyinPrice * 1) + (TopupAmount * 1);
document.getElementById('tTotalPurchasePrice').value = totalPrice;
You could also simply have added the var keyword but it would have made the code confusing.
A way to reduce the probability of such errors is to follow best practices when naming functions and variables. Here you should have named your function as a verb to denote an action instead of a value.
You're are confusing JavaScript with VBScript here.
To return value use return keyword:
return (BuyinPrice * 1) + (TopupAmount * 1);
Then outside the function have such line:
document.getElementById('tTotalPurchasePrice').value = TotalPurchasePrice(BuyinPrice, TopupAmount);
Assigning the value of a variable inside a function without stating it with var (TotalPurchasePrice in your case) means that the variable is global.
Since you could have the function declaration written as: var TotalPurchasePrice = function(BuyinPrice, TopupAmount) {}, you are just overriding it.
You could either rename the variable inside the function or add a var statement in front of it like:
var TotalPurchasePrice = (BuyinPrice * 1) + (TopupAmount * 1);

Categories

Resources