Related
I'm putting together a quiz with A/B questions. Every answer has 5 parameters that have to be updated as the user advances through the quiz to show a final results page.
It's very simple but I can't figure out why the parameters aren't updating. This is my first Javascrips project, can somebody point me in the right direction? Thank you!
//The five parameters to be updated
let totalOrg = 2;
let totalDel = 2;
let totalMod = 0;
let totalLux = 2;
let totalSer = 2;
// Array with values to modify the parameters for A or B answers
var valueDataA = [
[1,2,5,1,3],
[6,5,1,2,8]
];
var valueDataB = [
[-6,-3,-7,-3,-2],
[-1,-7,-5,-2,-3]
];
//Function to add the values to the parameters
function chooseOptionA() {
totalOrg = totalOrg + valueDataA[currentQuestion][0];
totalDel = totalDel + valueDataA[currentQuestion][1];
totalMod = totalMod + valueDataA[currentQuestion][2];
totalLux = totalLux + valueDataA[currentQuestion][3];
totalSer = totalSer + valueDataA[currentQuestion][4];
console.log(totalParameters);
};
function chooseOptionB() {
totalOrg = totalOrg + valueDataB[currentQuestion][0];
totalDel = totalDel + valueDataB[currentQuestion][1];
totalMod = totalMod + valueDataB[currentQuestion][2];
totalLux = totalLux + valueDataB[currentQuestion][3];
totalSer = totalSer + valueDataB[currentQuestion][4];
console.log(totalParameters);
};
let totalParameters = [totalOrg, totalDel, totalMod, totalLux, totalSer];
When you place totalOrg in the array totalParameters, you are not placing a pointer to the first variable, but the value, i.e. 2. So the final line of code is no different from:
let totalParameters = [2, 2, 0, 2, 2];
This will clarify why that array is not getting any changes when the functions are called. There are several ways to do this. I will propose one, where the first "parameter" values are stored in a single object, whose property names correspond to your current variable names. You must then adapt the rest of your code to reference those properties:
let totalParameters = {
totalOrg: 2,
totalDel: 2,
totalMod: 0,
totalLux: 2,
totalSer: 2
};
var valueDataA = [
[1,2,5,1,3],
[6,5,1,2,8]
];
var valueDataB = [
[-6,-3,-7,-3,-2],
[-1,-7,-5,-2,-3]
];
function chooseOptionA() {
totalParameters.totalOrg += valueDataA[currentQuestion][0];
totalParameters.totalDel += valueDataA[currentQuestion][1];
totalParameters.totalMod += valueDataA[currentQuestion][2];
totalParameters.totalLux += valueDataA[currentQuestion][3];
totalParameters.totalSer += valueDataA[currentQuestion][4];
console.log(totalParameters);
};
function chooseOptionB() {
totalParameters.totalOrg += valueDataB[currentQuestion][0];
totalParameters.totalDel += valueDataB[currentQuestion][1];
totalParameters.totalMod += valueDataB[currentQuestion][2];
totalParameters.totalLux += valueDataB[currentQuestion][3];
totalParameters.totalSer += valueDataB[currentQuestion][4];
console.log(totalParameters);
};
Let me pitch you a different approach
//The five parameters to be updated
let totalOrg = 2;
let totalDel = 2;
let totalMod = 0;
let totalLux = 2;
let totalSer = 2;
// Array with values to modify the parameters for A or B answers
var valueDataA = [
[1,2,5,1,3],
[6,5,1,2,8]
];
var valueDataB = [
[-6,-3,-7,-3,-2],
[-1,-7,-5,-2,-3]
];
/**
* updateParameters
*
* Function to update the values of the parameters
*
* #param {Array<Number>} parameters
* #param {Array<Number>} parameterUpdates
* #returns {Array<Number>}
*/
function updateParameters(parameters, parameterUpdates) {
for (let i = 0; i < parameters.length; i++) {
parameters[i] += parameterUpdates[i];
}
return parameters;
}
let totalParameters = [totalOrg, totalDel, totalMod, totalLux, totalSer];
for (let currentQuestionIndex = 0; currentQuestionIndex < 2 /** questions.length */; currentQuestionIndex++) {
let option = 'A'; /** actually getUserChoice(); */
if (option == 'A') {
totalParameters = updateParameters(totalParameters, valueDataA[currentQuestionIndex])
} else if(option == 'B') {
totalParameters = updateParameters(totalParameters, valueDataB[currentQuestionIndex])
}
console.log(totalParameters);
// you can use destructuring assignment to get individual parameters written
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
[totalOrg, totalDel, totalMod, totalLux, totalSer] = totalParameters;
}
I am new to Programming and am looking for a nudge or some tips into the right direction with an iteration. I am trying to create looping for a random password generator I have created.
I need the function to loop 3 times and I'm aware some of the code is incorrect as I was just trying to see what I could get to work, I'm open to anything you guys throw my way - I will be posting the code below. :)
//Function to generate and display to console Word 1 - random number
function Word1() {
var random = Math.floor(Math.random() * 9 + 1);
return random
}
// function to generate and display to console Word 2 - random emotion
function Word2() {
var emotions = [ 'sad', 'happy', 'cheerful', 'angry', 'fear', 'surprise'];
return emotions[Math.floor(Math.random()*emotions.length)];
}
//function to generate and display to console Word 3 - random plural noun
function Word3() {
var emotions = [ 'computer', 'day', 'car', 'flower', 'house', 'cat'];
var plural = ['s'];
var random = emotions[Math.floor(Math.random()*emotions.length)];
var emotion_plural = random + plural;
return emotion_plural
}
//function to generate and display to console Word 4 - random verb
function Word4() {
var verbs = [ 'running', 'walking', 'sleeping', 'talking', 'singing', 'sitting'];
return verbs[Math.floor(Math.random()*verbs.length)];
}
// function to create password one-line string
function passWord() {
return `${Word1()} ${Word2()} ${Word3()} ${Word4()}`
//console.log(passWord());
}
Your code wasnt off to a terrible start for being basic. You had some typos... Javascript variable and function names are case sensitive.
I also broke out some of the variables just to make the process more "readable". Its not overall how I would do everything, but I kept to your initial stab at it.
var Word1 = function() {
var randomNumber = Math.floor(Math.random() * 9 + 1);
return randomNumber
};
var Word2 = function() {
var emotions = ['sad', 'happy', 'cheerful', 'angry', 'fear', 'surprise'];
var randomNumber = Math.floor(Math.random() * emotions.length);
var randomEmotion = emotions[randomNumber];
return randomEmotion;
};
var Word3 = function() {
var nouns = ['computer', 'day', 'car', 'flower', 'house', 'cat'];
var plural = 's';
var randomNumber = Math.floor(Math.random() * nouns.length);
var randomNoun = nouns[randomNumber];
var pluralRandomNoun = randomNoun + plural;
return pluralRandomNoun;
};
var Word4 = function() {
var verbs = ['running', 'walking', 'sleeping', 'talking', 'singing', 'sitting'];
var randomNumber = Math.floor(Math.random() * verbs.length);
var randomVerb = verbs[randomNumber];
return randomVerb;
};
var passWord = function() {
var randomPassword = Word1() + Word2() + Word3() + Word4();
return randomPassword;
};
for (var i = 0; i < 3; i++) {
console.log(passWord());
}
So I want to make it so that every time I run the code the item of this array that shows up will be different. Here is the code I've done so far.
let array = ["apple","orange"];
randomItem = array[Math.floor(Math.random() * array.length)];
if(randomItem != document.getElementById('spaceText').innerHTML){
document.getElementById('spaceText').innerHTML = randomItem;
} else while(randomItem == document.getElementById('spaceText').innerHTML){
randomItem = array[Math.floor(Math.random() * array.length)];
}
I'm not entirely sure how to finish this .. here is how I'm looking at the problem,
You have an array that includes several strings you want to pick from
you want to generate a random number to select one item from the array
you want to check if the selected item is equal to the content of the html element of yours.
if not, then you would like to insert that item into the html element
if it is equal you want to generate another random number
There are multiple ways to achieve this:
You could build a new array without the value you don't want, and choose a random from that.
You could also make a loop which keeps going until you get a value you want.
You could also move the value you don't want to the end of the array, swapping place, and then choose a value within upperBound - 1.
You could also just remove the value you get from the array each time, if you don't want it to appear at all again.
There are multiple ways that all depend on the context and goal of the system.
In your case you don't have to generate a random number more than once, just use filter method
const array = ["Apple","Orange","Cherry","Banana","Pear"];
const spaceText = document.getElementById('spaceText');
function randomText() {
//the next fruit cannot equal the current text content
const options = array.filter(fruit => fruit !== spaceText.textContent);
const randomIndex = Math.floor(Math.random() * options.length);
console.log("Random fruit is:",options[randomIndex]);
spaceText.textContent = options[randomIndex];
}
<div id="spaceText">Apple</div>
<button onclick="randomText()">Randomize</button>
Does this help you? All it does is selecting a new item from the array and taking care that it is not the one that was selected previously
const items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
let selectedItemIndex;
function selectNewOne() {
const randomItemIndex = Math.floor(Math.random() * items.length);
if (randomItemIndex === selectedItemIndex) {
return selectNewOne();
}
return randomItemIndex;
}
// this is just for testing purposes
for (let i = 0; i < 5; i++) {
selectedItemIndex = selectNewOne();
console.log(items[selectedItemIndex]);
}
Here is one approach, Keep the random number in object (or set) and generate new random until you found not already seen one. Generator function will be helpful to do that.
const getRandomUniqueInList = function* (arr) {
const myRandom = () => Math.floor((Math.random() * 100) % arr.length);
const list = [];
while (list.length < arr.length) {
let index = myRandom();
while (list.includes(index)) {
index = myRandom();
}
list.push(index);
yield index;
}
return -1;
};
const items = new Array(10).fill(0);
const itr = getRandomUniqueInList(items);
let next = itr.next();
while (!next.done) {
console.log('Random: ', next.value);
next = itr.next();
}
Another variant for get random upto specified max number and implement with Set and generator method.
const getRandomUpto = function* (max = 50) {
const myRandom = () => Math.ceil(Math.random() * max);
const set = new Set();
let rand = myRandom();
while (set.size < max) {
while (set.has(rand)) {
rand = myRandom();
}
set.add(rand);
yield rand;
}
};
const sample_max = 10;
const itr = getRandomUpto(sample_max);
let next = itr.next();
while(!next.done) {
const myRandom = () => Math.ceil(Math.random() * sample_max);
console.log('Random, (not repeat):', next.value, '(may repeat): ', myRandom());
next = itr.next()
}
Based on your code sample. You are using innerHTML which assumed to be string. So the approach is when you trigger the function, pull a random element/word from the array, then matches if it exists in the current innerHTML value, if it is true, it will skip it else it will append the random word into the innerHTML.
This could work with arrays as well as an alternative to innerHTML / string
let array = ["apple","orange", "banana","cherry","strawberry" ];
random = () =>{
let randomItem = array[Math.floor(Math.random() * array.length)];
let currentString = document.getElementById('spaceText').innerHTML
if( ! (parseFloat(currentString.indexOf(randomItem)) >=0) ){
currentString += ' '+randomItem
document.getElementById('spaceText').innerHTML = currentString
}else{
console.log(randomItem+' already exists')
}
}
<div id="spaceText">Inital value</div>
<button onclick="random()">Random</button>
in JS, I have a list of variables, which I shuffle. I want to maintain the order of the shuffle, but change the values of the variables in the list. Is there a way to do that? Below is an example of my code. I explain what I want in the comments.
<p id="demo"></p>
<script>
var gen = "male "
var race = "white "
var rel = "christian "
var chars =[gen,race,rel]
chars = shuffle(chars);
document.getElementById("demo").innerHTML = chars+"";
/*prints for example "white christian male " which is what I want
/*lets say I want to change the gender, and maintain the newly shuffled order (race-rel-gen in this case)*/
/* The below doesn't work. I want it to print "white christian female ", but it just reprints the original string*/
gen = "female "
document.getElementById("demo").innerHTML = chars+"";
</script>
Considering you want to maintain the pre-shuffled order, you can try to use an object, instead of string, then it'll keep reference. Something like this:
/* function to convert your array of objects into a pretty string */
const arrtoStr = (arr) => arr.map((obj) => obj.value).join(' ')
var gen = { value: "male" }
var race = { value: "white" }
var rel = { value: "christian" }
var chars =[gen,race,rel]
chars = shuffle(chars);
//will output, for instance: "white christian male"
document.getElementById("demo").innerHTML = arrtoStr(chars);
// change object's key named 'value'
gen.value = "female"
//will output: "white christian female"
document.getElementById("demo").innerHTML = arrtoStr(chars);
You can use a map object and some supplemental functions to take care of this.
let char = new Map([
['gen', 'male'],
['race', 'white'],
['rel', 'christian'],
["order", shuffle([0,1,2])],
["display", ['gen', 'race', 'rel']]
]);
function shuffle(arr) {
return arr.sort(_ => Math.random() > .5);
}
function display(mItm) {
return mItm.get("order").map(itm => mItm.get(mItm.get("display")[itm]));
}
//display char
document.querySelector("#demo").innerHTML += "</br>" + display(char);
//display new race
char.set("race", "blue");
document.querySelector("#demo").innerHTML += "</br>" + display(char);
// reshuffle
char.set("order", shuffle(char.get("order")));
document.querySelector("#demo").innerHTML += "</br>" + display(char);
<p id="demo"></p>
If I understand correctly, the solution below should work. Keeping a person object and an order array separate should give you more flexibility. I am using Lodash for shuffle as a convenience.
CodePen Demo
this.person = {
gen: "male",
race: "white",
rel: "christian"
};
this.order = ["gen", "race", "rel"];
function output() {
let temp = [];
this.order.forEach((key) => {
temp.push(this.person[key]);
});
document.getElementById("demo").innerHTML += temp.join(", ") + "<br>";
}
// shuffle the order of properties
_.shuffle(this.order);
// output original data
output();
// change specifics, but keep the order of properties
this.person["gen"] = "female";
output();
this.person["race"] = "black";
output();
this.person["rel"] = "jewish";
output();
You can either assign the array again after assigning the new variable value like this:
var gen = "male "
var race = "white "
var rel = "christian "
var chars =[gen,race,rel]
chars = shuffle(chars);
document.getElementById("demo").innerHTML = chars+"";
gen = "female "
var chars =[gen,race,rel]
chars = shuffle(chars);
document.getElementById("demo").innerHTML = chars+"";
jsFiddle: https://jsfiddle.net/AndrewL64/p6rgo01a/
Or create a reusable function like this:
function newVal(gen, race, rel) {
var chars =[gen,race,rel]
chars = shuffle(chars);
document.getElementById("demo").innerHTML = chars+"";
}
newVal('male ','white ', 'christian ');
newVal('female','white ', 'christian ');
jsFiddle: https://jsfiddle.net/AndrewL64/p6rgo01a/1/
You, possibly asked wrong question, or, your original intentions are not reflected in question, but as far as I understand, you are looking for sth like that.
var races = ["caucasian", "ethiopian", "malayan", "american", "mongolian"];
var beliefs = ["jewish", "buddhist", "muslim", "christian", "shintoist"];
var genders = ["male", "female"];
var randomArrayElement = function(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
function makeCombo(r, b, g) {
var race = randomArrayElement(r);
var belief = randomArrayElement(b);
var gender = randomArrayElement(g);
return [race, belief, gender].join(" ");
}
document.querySelector("button").addEventListener("click", function(e){
document.getElementById("profile-area").innerText = makeCombo(races, beliefs, genders);
})
<p id='profile-area'></p>
<button>Generate a profile</button>
You should define a shuffle function. Something like this:
// define shuffle function
function shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
Then you can call this function with chars as a param to create a shuffled array like this:
var chars = [gen, race, rel];
You can then output the result as a string like this:
document.getElementById("demo").innerHTML = shuffle(chars).join(" ");
The join(" ") to replace the comma with an space.
option 1) reshuffle with new value(s)
As your original chars array's order doesn't shuffle, you can change the value's by doing this:
chars[0] = "female";
You can update the DOM by calling the shuffle function again as shown above.
option 2) keep the shuffled order en output it with an updated value
To keep the shuffled order, but output the array again with an updated value, you need to store the shuffled output in a new variable. You will get something like this:
var chars = [gen, race, rel];
var shuffled = shuffle(chars);
document.getElementById("demo").innerHTML = shuffled;
// change value of gen
shuffled[shuffled.indexOf("male")] = "female";
// output again
document.getElementById("demo").innerHTML = shuffled;
This question already has an answer here:
Math random to find Names in an Array while not duplicating
(1 answer)
Closed 1 year ago.
window.onload = start;
function start () {
var name = ["Hans","Ole","Nils","Olav","Per","Knut","Kari","Line","Pia"]
var random = Math.floor(Math.random()*8)
var random2 = Math.floor(Math.random()*8)
var random3 = Math.floor(Math.random()*8)
var name2 = []
name2.push(name[random])
name2.push(name[random2])
name2.push(name[random3])
for(i=0; i<3; i++) {
document.getElementById("par").innerHTML += name2[i] + "<br/>" ;
}
}
So far with this code i can generate 3 random names from the name array. But i want the 3 names not to be repeated, and I don't know how to make that happen.
Perhaps this could help. I randomized the order of the array and then just pick the first three elements. This allows for zero repeats of names and generating a new answer each time the function is ran. Not sure what your HTML looks like so I just added the id "demo".
var players = ["Hans","Ole","Nils","Olav","Per","Knut","Kari","Line","Pia"];
function tournament() {
var names = [];
players.sort(function(a,b){return 0.5 - Math.random()});
for (i=0; i<3; i++){
names.push(players[i]);
}
document.getElementById("demo").innerHTML = names;
}
I created a solution that uses recursion.
The function randomNames gets repeated three times. Each time it gets called count gets increased and names is an array without the names that are already taken. It returns an array that holds the three random names.
function start () {
var name = ["Hans","Ole","Nils","Olav","Per","Knut","Kari","Line","Pia"]
function randomNames(count, names) {
if(count >= 3) return [];
var random = Math.floor(Math.random()*(names.length-1));
// remove current name
var name = names.splice(random, 1);
return randomNames(++count, names).concat(name);
}
var random = randomNames(0, name);
}
You could use a hash table for the chosen items and check against until all wanted items are found.
window.onload = start;
function start() {
var name = ["Hans", "Ole", "Nils", "Olav", "Per", "Knut", "Kari", "Line", "Pia"],
hash = {},
random;
while (Object.keys(hash).length < 3) {
do {
random = Math.floor(Math.random() * name.length);
} while (hash[random])
hash[random] = true;
document.getElementById("par").innerHTML += name[random] + "<br/>";
}
}
<div id="par"></div>
ES6 with Set
window.onload = start;
function start() {
var name = ["Hans", "Ole", "Nils", "Olav", "Per", "Knut", "Kari", "Line", "Pia"],
hash = new Set,
random;
while (hash.size < 3) {
do {
random = Math.floor(Math.random() * name.length);
} while (hash.has(random))
hash.add(random);
document.getElementById("par").innerHTML += name[random] + "<br/>";
}
}
<div id="par"></div>