Repetition of two variables one after the other in Math.random() - javascript

I wrote the following code to randomly change the background color, but sometimes the two colors are repeated one after the other .... How do you think I can write the code so that the two colors are not repeated one after the other?
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
btn.addEventListener("click", function() {
const randomNumber = getRandomNumber()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomNumber() {
return Math.floor(Math.random() * colors.length)
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>

This will happen because since it is completely random you might get the same number again.
You can put a while loop to ensure you are getting a new color every time. Keep a loop that keeps on running unless you get a new number.
Here prevNumber is used to keep track of the previous number. Now the code keeps on generating a new number until you have a different number from the previous one.
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
let prevNumber = 0;
btn.addEventListener("click", function() {
let randomNumber = getRandomNumber();
while(randomNumber == prevNumber){
randomNumber = getRandomNumber();
}
prevNumber = randomNumber;
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomNumber() {
return Math.floor(Math.random() * colors.length)
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>

You could save the last number generated. If that number comes back again, get another one.
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
let last = -1
btn.addEventListener("click", function() {
let randomNumber = getRandomIndex()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomIndex() {
let randomIndex = Math.floor(Math.random() * colors.length)
if (randomIndex === last) {
return randomIndex = getRandomIndex()
} else {
last = randomIndex
return randomIndex
}
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>

Both current answers are totally ok. If you want to randomize just once you can do:
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
let currentColor = colors.pop();
btn.addEventListener("click", function() {
const randomNumber = getRandomNumber()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
function getRandomNumber() {
const chosen = Math.floor(Math.random() * colors.length)
const newColor = colors[chosen];
colors.splice(chosen,1,currentColor);
currentColor = newColor;
return chosen;
}
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>
This way you prevent the current colour to be selected, and once the randomization has been done, you insert the one left out while removing the newly selected

write closure like noConsecutiveRandom to get random number but not consecutively repeat.
const colors = ["green", "red", "rgba(133,122,200)", "#f15025"];
const btn = document.getElementById("btn");
const color = document.querySelector(".color");
function noConsecutiveRandom(size) {
let last;
return function rand() {
const cur = Math.floor(Math.random() * size);
return cur === last ? rand() : (last = cur);
};
}
const getRandomNumber = noConsecutiveRandom(colors.length);
btn.addEventListener("click", function() {
const randomNumber = getRandomNumber()
document.body.style.backgroundColor = colors[randomNumber];
color.textContent = colors[randomNumber]
})
<h2>background color : <span class="color">#f1f5f8</span></h2>
<button class="btn btn-hero" id="btn">click me</button>

Related

JS counting numbers with thousands separator

For example, I want to display the number 90,000 while it is counting up.
I have already managed to count up with the following code, but without "." or ",":
<div class="fact">
<div class="number" num="90000">0</div>
</div>
const counters = document.querySelectorAll('.number');
const speed = 500;
counters.forEach( counter => {
const animate = () => {
const value = +counter.getAttribute('num');
const data = +counter.innerText;
const time = value / speed;
if(data < value) {
counter.innerText = Math.ceil(data + time);
setTimeout(animate, 1);
}else{
counter.innerText = value;
}
}
animate();
});
Have already found examples with thousands separator but I can't manage to convert it to my project.
while (/(\d+)(\d{3})/.test(val.toString())){
val = val.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
I have little experience with javascript.
Per my comment, Keep data separate from formatting
const counters = document.querySelectorAll('.number');
const speed = 500;
const formatter = new Intl.NumberFormat();
counters.forEach(counter => {
const animate = () => {
let value = +counter.dataset.num;
let data = +counter.dataset.state;
let time = value / speed;
if (data < value) {
counter.dataset.state = Math.ceil(data + time);
setTimeout(animate, 1);
}
counter.innerText = formatter.format(counter.dataset.state);
}
animate();
});
<div class="fact">
<div class="number" data-num="90000" data-state="0">0</div>
<div class="number" data-num="45000" data-state="0">0</div>
</div>

How to style a singular v-for item in vue, based on a condition?

I am making a multiple choice quiz game and want what the user clicked to change to either red or green depending on if that answer is correct or incorrect. I made a variable called selected which is what the user pressed- this does correctly update. I have also got all of the v-for items to change to the same colour depending on if the answer is correct or not, I only need help separating it so that only one of the v-for things change colour.
Here is my relative HTML:
<button type="button" class="btn" class="answer" v-for="option in options" #click="checkAnswer(option)" #click="selected = option" :style="{backgroundColor: colour}">
{{option}}<br/>
</button>
<button type="button" #click="getQ" #click="shuffle(options)" class="btn button next">Next</button>
Here is the relative JS:
let colour = Vue.ref('');
let selected = Vue.ref('');
let options = Vue.ref([correctAnswer, incorrectAnswerOne, incorrectAnswerTwo, incorrectAnswerThree]);
// Methods
let shuffle = function(options) {
let num = options.length, t, raInt;
//while there are remaining elements to shuffle
while (num) {
//choose random
raInt = Math.floor(Math.random() * num--);
//swap with current element
t = options[num];
options[num] = options[raInt];
options[raInt] = t;
}
return options;
};
let checkAnswer = function(clicked) {
console.log(clicked.value);
console.log(correctAnswer.value);
if (clicked.value == correctAnswer.value) { // checks if the button that was clicked is the same as the answers value
this.result = "Correct!"; //if it does, result changes to Correct!
this.colour = "green";
} else {
this.result = "Incorrect!"; //if the answer is incorrect, result changes to Incorrect!
this.colour = "red";
};
};
And here is some CSS:
.answer {
width: 100%;
background-color: #dbdbdb;
padding: 4% 2%;
margin: 1 0;
}
.answer:hover {
background-color: #c2c2c2
}
I haven’t really tried that much. I’m not sure what to try. In a different project I did style a different div based on what other div was selected, but I am not sure how to change just one part of a v-for, or if it is even possible.
Thanks in advance
You can set condition for showing color style:
const { ref, computed } = Vue
const app = Vue.createApp({
setup() {
let correctAnswer = 3
let incorrectAnswerOne = 1
let incorrectAnswerTwo = 2
let incorrectAnswerThree = 4
let colour = ref('');
let selected = ref('');
let options = ref([correctAnswer, incorrectAnswerOne, incorrectAnswerTwo, incorrectAnswerThree]);
let shuffled = ref([])
let shuffle = (array) => {
selected.value = null
let currentIndex = array.length, randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
shuffled.value = array;
};
shuffle(options.value)
let checkAnswer = function(clicked) {
// 👇 set selected
selected.value = clicked
if (clicked == correctAnswer) {
this.result = "Correct!";
this.colour = "green";
} else {
this.result = "Incorrect!";
this.colour = "red";
};
};
return { colour, selected, options, shuffle, checkAnswer, shuffled }
},
})
app.mount('#demo')
.answer {
width: 100%;
background-color: #dbdbdb;
padding: .5em 2em;
margin: 1 0;
}
.answer:hover {
background-color: #c2c2c2
}
.btns {
display: flex;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<div class="btns">
<div v-for="(option, i) in shuffled" :key="i" >
<!-- 👇 condition -->
<button class="answer" #click="checkAnswer(option)" :style="selected == option && {backgroundColor: colour}">
{{option}}<br/>
</button>
</div>
</div>
<button type="button" #click="getQ, shuffle(options)" class="btn button next">Next</button>
</div>

how to activated new function after button clicked for three times

i want to add new function after i clicked the button 3 times and erase/remove the former function
html file:
<body>
<div id="background">
<p>this background white, before</p>
</div>
<button class="btn-1">change color</button>
</body>
javascript:
const btn1 = document.querySelector(".btn-1") ;
const bg = document.getElementById("background")
const toRed = ()=>{
bg.style.backgroundColor = "red";
}
const toBlue = ()=>{
bg.style.backgroundColor = "steelblue";
}
btn1.addEventListener('click', toRed);
// i want this btn1 have function to clear function toRed and add toBlue instead after clicked 3 times
remove the event listener and add a new one when it was clicked three times:
const btn1 = document.querySelector(".btn-1");
const bg = document.getElementById("background");
var redClicked = 0;
const toRed = ()=>{
bg.style.backgroundColor = "red";
redClicked++;
if (redClicked >= 3) {
btn1.removeEventListener('click', toRed);
btn1.addEventListener('click', toBlue);
}
}
const toBlue = ()=>{
bg.style.backgroundColor = "steelblue";
}
btn1.addEventListener('click', toRed);
<body>
<div id="background">
<p>this background white, before</p>
</div>
<button class="btn-1">change color</button>
</body>

How to use the Values from JS, instead of taking the value from the HTML?

I have 3 buttons like the below,
<button id="b1">0</button>
<button id="b2">0</button>
<button id="b3">0</button>
Instead of getting/ reading the value from the HTML, I need to store the value in the JS.
Each buttons, on click should be incremented by 1, when it reaches 3, again it should become 0.
The values [0, 1, 2, 3] should be from JS and not from HTML.
I used switch case to show If the value is "0" the color is "red", If the value is 1, the color is "blue", if the value is 2, the color is "green", If the value is 3, the color is "pink".
I tried the below code, but the switch is not working. It displays the default line of code.
$("button").click(function () {
buttonVal(this);
});
function buttonVal(ele) {
var v = [];
var val = +document.getElementById(ele.id).innerHTML;
var res = val >= 3 ? 0 : val + 1;
v[ele.id] = { intVal: res };
var colors = ["red", "blue", "green", "yellow", "cyan"];
var randColor = colors[Math.floor(Math.random() * colors.length)];
switch (v[ele.id]) {
case "0":
return document.getElementById(ele.id).innerHTML = "red";
case "1":
return document.getElementById(ele.id).innerHTML = "blue";
case "2":
return document.getElementById(ele.id).innerHTML = "green";
default:
return document.getElementById(ele.id).innerHTML = "no";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="b1">0</button>
<button id="b2">0</button>
<button id="b3">0</button>
How to make the code to work ?
I need an array to store the values of (0 ,1, 2, 3).
Could someone please help?
Many thanks
You are declaring the array inside the function, so it gets initialized each time you execute it. It's better to take it out the function so it can save the variables. For this case as you are summing variables is better to convert variables to Integer using parseInt().
Take a look to the following snippet:
$("button").click(function () {
buttonVal(this);
});
var v = [];
function buttonVal(ele) {
var val = parseInt(document.getElementById(ele.id).innerHTML);
var res = val >= 3 ? 0 : val + 1;
v[ele.id] = res;
var colors = ["red", "blue", "green", "yellow", "cyan"];
var randColor = colors[Math.floor(Math.random() * colors.length)];
switch (res) {
case 0:
document.getElementById(ele.id).style.background = randColor;
document.getElementById(ele.id).innerHTML = res;
break;
case 1:
document.getElementById(ele.id).style.background = randColor;
document.getElementById(ele.id).innerHTML = res;
break;
case 2:
document.getElementById(ele.id).style.background = randColor;
document.getElementById(ele.id).innerHTML = res;
break;
case 3:
document.getElementById(ele.id).style.background = randColor;
document.getElementById(ele.id).innerHTML = res;
break;
default:
document.getElementById(ele.id).innerHTML = "no";
document.getElementById(ele.id).innerHTML = res;
break;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="b1">0</button>
<button id="b2">0</button>
<button id="b3">0</button>
You have used v[ele.id] = { intVal: res }, definitely switch will not work with 0,1,2
Use res in switch
switch(res)
You don't really need to use array for that use case. You can just use .each and populate the index as text:
Edit
Added an array instead of index.
let btns = [0,1,2];
$("button").click(function () {
buttonVal(this);
});
$('button').each(function(index,ele){
$(ele).text( btns[index] );
});
function buttonVal(ele) {
var val = $(ele).text();
var colors = ["red", "blue", "green", "yellow", "cyan"];
var randColor = colors[Math.floor(Math.random() * colors.length)];
switch (val) {
case "0":
return document.getElementById(ele.id).innerHTML = "red";
case "1":
return document.getElementById(ele.id).innerHTML = "blue";
case "2":
return document.getElementById(ele.id).innerHTML = "green";
default:
return document.getElementById(ele.id).innerHTML = "no";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="b1">0</button>
<button id="b2">0</button>
<button id="b3">0</button>
Your fixed code
Logic
Get the button innerHTML
Check the value, if its 3 make it 0, or else increment it.
correct the colors array, so that it holds the value that you needs on each innerHTML value.
Update the style.backgroundColor for the innerHTML value.
$("button").click(function () {
buttonVal(this);
});
function buttonVal(ele) {
var val = +document.getElementById(ele.id).innerHTML;
val = val === 3 ? 0 : ++val;
document.getElementById(ele.id).innerHTML = val;
var colors = ["red", "blue", "green", "pink"];
switch (val) {
case 0:
document.getElementById(ele.id).style.backgroundColor = colors[0];
break;
case 1:
document.getElementById(ele.id).style.backgroundColor = colors[1];
break;
case 2:
document.getElementById(ele.id).style.backgroundColor = colors[2];
break;
default:
document.getElementById(ele.id).style.backgroundColor = colors[3];
break;
}
}
<button id="b1">0</button>
<button id="b2">0</button>
<button id="b3">0</button>
For this particular solution you dont need to have a switch case. You could just keep your colors array proper. You are handling the innerHTML logic correctly, so just access the values from colors array.
$("button").click(function () {
buttonVal(this);
});
function buttonVal(ele) {
let val = +document.getElementById(ele.id).innerHTML;
var colors = ["red", "blue", "green", "pink"];
val = val === 3 ? 0 : ++val;
document.getElementById(ele.id).innerHTML = val;
document.getElementById(ele.id).style.backgroundColor = colors[val];
}
<button id="b1">0</button>
<button id="b2">0</button>
<button id="b3">0</button>

i don't now how use background from js

I am a newbie to js and I would like to know how you can use background from javascript let's say I can set the color of a button by doing this:
const btnPulsado = (e) =>{
const btn= e.target;
btn.style.backgroundColor= 'red';
can I do it somehow with backgroundImage?
You can use
e.target.style.backgroundColor = __ANY_COLOR_CODE;
function genRanHex(size) {
return [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('')
}
const btn = document.querySelector("button");
btn.addEventListener("click", e => {
e.target.style.backgroundColor = `#${genRanHex(6)}`;
})
<button> click me to change color </button>

Categories