javascript: clicking numerical boxes - increment not working - javascript

using the code below, I've created a grid of buttons, 5x5, with random 1-25 numbers assigned to each button. They are to be clicked in numerical order, each's background turns red when clicked in the correct order. I can't use a global variable for this prompt. Without a global variable, I can't figure out how to increment the correctNumbers function which checks whether the right number is clicked each time. I think I'm missing something, a js function or something that would enable an incrementing variable declared within the incrementing function. I'm not looking for the whole explanation, just tips on functions i might not know about, and whether or not what i'm trying to do just isn't logicly possible.
<div id="numbers" class="hidden"></div>
<div id="youWon" class="hidden">You Won!</div>
The relevant JS:
... /**
* Gives the numbers a random order
* the "Fisher-Yates shuffle" found at: https://www.frankmitchell.org/2015/01/fisher-yates/
* #param {*} array
*/
const shuffle = (array) => {
let i = 0,
j = 0,
temp = null
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1))
temp = array[i]
array[i] = array[j]
array[j] = temp
}
}
/**
* Generates an array of numbers 1-25
*/
const generateNums = () => {
document.getElementById("youWon").classList.toggle("hidden", "visible");
const numberArray = [];
for (let a = 1; a <= 25; a++) {
numberArray.push(a);
}
shuffle(numberArray);
let numEl = document.getElementById('numbers'); //write into html div id "numbers"
for (let b = 0; b <= 24; b++) { //loop to create button array
let newBtn = document.createElement('button'); //create buttons
newBtn.className = 'number'; //assign newBtns 'number' class
newBtn.innerText = numberArray[b]; //assign numbers to each button
numEl.appendChild(newBtn); //match with number elements in "numbers" array
newBtn.addEventListener("click", onNumberClick) //create function trigger
}
}
/**
* Creates a function to decide correct and incorrect clicks
* When a user clicks a number, if it is the next number in order, then it turns a different color for the remainder of the test
* If it is the wrong number, nothing happens
* #param {*} event
*/
const incrementNum = (correctNumber) => {
correctNumber++;
}
const onNumberClick = (event) => {
let correctNumber = 1; //start at 1
let numberVal = event.target; //apply it to clicks on the numbers
if (Number(numberVal.innerHTML) + 1 == incrementNum(correctNumber)) {
incrementNum(correctNumber);
numberVal.classList.add("red");
}
if (correctNumber == 26) {
document.getElementById("youWon").classList.toggle("visible"); //show win message if 25 is the last button and gets clicked
}
}

I would suggest that you count the number of elements in the DOM that have the class "red" and add 1... checking if the innerHTML is equal to that number to get the sequence right. So, instead of this:
if (Number(numberVal.innerHTML) + 1 == incrementNum(correctNumber)) {
incrementNum(correctNumber);
numberVal.classList.add("red");
}
You can have something like this:
if(Number(numberVal.innerHTML) == document.getElementsByClassName('red').length + 1) {
numberVal.classList.add("red");
}

Related

set input values in array and randomize content to display

I can't seem to find any solutions.
I want to create a form that collects 4 nicknames after submit a form and then displays them all randomly in html code using javascript
My 4 input values are now in an array.
I have to display them randomly in two different teams.
I'm trying to get a random index, and as long as it's different from the ones already assigned to avoid one person being on both teams.
This code works, but sometimes, one player is assigned to 2 teams. Then, the randomizer doesn't work... Do you have an idea ?
function getRandomNumber(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function getData() {
let joueur1 = document.querySelector("#player1").value;
let joueur2 = document.querySelector("#player2").value;
let joueur3 = document.querySelector("#player3").value;
let joueur4 = document.querySelector("#player4").value;
playerList.push(player1.value);
playerList.push(player2.value);
playerList.push(player3.value);
playerList.push(player4.value);
randomNumber1 = getRandomNumber(playerList.length);
last1 += randomNumber1;
random1.textContent = playerList[randomNumber1];
do {
randomNumber2 = getRandomNumber(playerList.length);
} while (randomNumber2 == last1 && last4 && last3);
last2 += randomNumber2
random2.textContent = playerList[randomNumber2];
do {
randomNumber3 = getRandomNumber(playerList.length);
} while (randomNumber3 == last1 && last2 && last4);
last3 += randomNumber3
random3.textContent = playerList[randomNumber3];
do {
randomNumber4 = getRandomNumber(playerList.length);
}while (randomNumber4 == last1 && last2 && last3)
random4.textContent = playerList[randomNumber4];
last4 += randomNumber4
}
Thanks for your help !
Here is a simple way of getting a random item from your array
Here you add your items into array
let joueur1 = document.querySelector("#player1").value;
let joueur2 = document.querySelector("#player2").value;
let joueur3 = document.querySelector("#player3").value;
let joueur4 = document.querySelector("#player4").value;
let playerList=[];
playerList.push(joueur1);
playerList.push(joueur2);
playerList.push(joueur3);
playerList.push(joueur4);
Then, Here is how you can get randomized content
let randomPlayer = playerList[Math.floor(Math.random() * playerList.length)];
Math.random() will never be 1. The largest index is always one less than the length of the array

Getting new colors randomly with loop

I am trying to randomize colors by generating random number, then applying
it to array to get an color array containing font-color and background-color.
At every "skill" I want to have unique color scheme. So each time I loop skill array I loop color array to fetch color scheme. If this color scheme number (which is same as the randomNumber) is already in use I random again. I do this with do/while loop. When color is not found it pushes it to usedColors array and paints the picture.
For some reason I am still getting same colors. I pasted two pictures to the bottom. Console.log image is about usedColors array (the randomly generated numbers)
var usedColors = [];
$.each(knowledges, (i, knowledge) => {
do {
var r = Math.floor(Math.random() * Math.floor(colors.length)),
rColors = colors[r];
} while ($.inArray(r, usedColors) == 0);
usedColors.push(r);
$("#knowledges div").append(
$("<p />").addClass("knowledge").text(knowledge).css({"background-color": rColors[0], "color": rColors[1]})
);
});
inArray gives position of the matching element. So compare against -1, to know that element is not present in the usedColors array.
var usedColors = [];
$.each(knowledges, (i, knowledge) => {
do {
var r = Math.floor(Math.random() * Math.floor(colors.length)),
rColors = colors[r];
} while ($.inArray(r, usedColors) != -1);
usedColors.push(r);
$("#knowledges div").append(
$("<p />").addClass("knowledge").text(knowledge).css({"background-color": rColors[0], "color": rColors[1]})
);
});
To generate array of unique numbers from certain interval you can do this.
In your case the range will be 0, arr.length - 1.
// function that will generate random unique random numbers between start
// and end, and store already generated numbers in closure
function generateUniqueRandom(start, end) {
const used = [];
function generateInner() {
let r;
while (!r) {
r = Math.floor(Math.random() * (end - start) + 1) + start;
if (used.includes(r)) {
r = null;
} else {
used.push(r);
}
}
return r;
}
return generateInner;
}
const random1 = generateUniqueRandom(0, 20);
const nums1 = [];
for (let i = 0; i < 10; i++) {
nums1.push(random1());
}
console.log(nums1);
const random2 = generateUniqueRandom(0, 20);
const nums2 = [];
for (let i = 0; i < 20; i++) {
nums2.push(random2());
}
console.log(nums2);
But you need to be careful not to generate more numbers that the specified range is, otherwise you will be stuck in an infinite loop.
In your while loop, are you checking if the array is unique? If so, it looks like you may not be using $.inArray correctly.
Put this in your while loop:$.inArray(r, usedColors) !== -1
jQuery.inArray(), how to use it right?
I think your loop method has many interactions, I mean your loop is traveling so much that it only ends until you find the random number that is not in the array (A short performance problem). An alternative method so that the array elements are random:
function shuffleArray(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
const colors = [["black","green"], ["white","blue"], ["pink","white"]];
let usedColors = shuffleArray(colors);
//You can now do this:
$.each(knowledges, (i, knowledge) => {
$("#knowledges div").append(
$("<p />").addClass("knowledge").text(knowledge).css({"background-color": usedColors[i][0], "color": usedColors[i][1]})
);
});

List array elements, one by one, with a click of a button

I am new to Javascript and working with the basics. I am wanting to create an array whose individual elements are randomly drawn, one at a time, with a click of a button, until all array elements are displayed on the screen. The code I have is almost there. But the issue is that when it runs, it always grabs 2 elements on the first button click, rather than 1. It runs well for the remaining elements. Sure would appreciate some insight to this problem. Thank you.
var myArray=['1','2','3','4','5','6','7']
var text = "";
var i;
function RandomDraw() {
for(i = 0; i < myArray.length; i+=text) {
var ri = Math.floor(Math.random() * myArray.length);
var rs = myArray.splice(ri, 1);
document.getElementById("showSplice").innerHTML = text+=rs;
//document.getElementById("showArrayList").innerHTML = myArray;
}
}
It "always" draws 2 elements because of the i+=text. Your array is small thus the loop needs 2 iteration (of cocatinating the strings to get the number i) to go over myArray.length.
First iteration:
i = 0 => 0 < myArray.length => true
prints number
Second iteration: (say '4' get choosen)
i = i + text and text = '4' => i = "04" => "04" < myArray.length => true
prints number
Third iteration: (say '3' get choosen)
i = i + text and text = '43' => i = "0443" => "0443" < myArray.length => false
loop breaks
So there is a possibility that two elements get printed. Depending on the length of the array, there could be more.
You don't need the loop, just choose a number and print it:
function RandomDraw() {
if(myArray.length > 0) { // if there still elements in the array
var ri = Math.floor(Math.random() * myArray.length); // do your job ...
var rs = myArray.splice(ri, 1);
document.getElementById("showSplice").textContent = rs; // .textContent is better
}
else {
// print a message indicating that the array is now empty
}
}
Another solution is to shuffle the array and then, on each click, pop the element from the shuffled array.
function shuffle(array) {
return array.sort(function() { return Math.random() - 0.5; });
}
var button = document.getElementById('button');
var origin = ['1','2','3','4','5','6','7'];
var myArray = shuffle(origin);
var currentValue = null;
button.onclick = function() {
currentValue = myArray.pop();
if(!!currentValue) {
console.log(currentValue);
}
}
<button id='button'>
get element
</button>
You can shuffle the array again on each click, but I think it is not necessary whatsoever...
If you're wondering about Math.random() - 0.5:
[...] Math.random is returning a number between 0 and 1. Therefore, if you call Math.random() - 0.5 there is a 50% chance you will get a negative number and 50% chance you'll get a positive number.
If you run a for loop and add these results in an array, you will effectively get a full distribution of negative and positive numbers.
https://teamtreehouse.com/community/mathrandom05
I would do it this way:
let myArray=['1','2','3','4','5','6','7']
function RandomDraw(){
const selectedIndex = Math.floor(Math.random() * myArray.length);
const selected = myArray[selectedIndex]
myArray = myArray.slice(0, selected).concat(myArray.slice(selected + 1));
return selected;
}
Every time you call RandomDraw it will return a random number, without repeating.
The way I understand it, you want to draw every items from the array after a single click. So the loop is needed.
As others have said, there are several issues in your for loop :
that i+= text makes no sense
you are looping until i reaches the length of your array, but you are splicing that array, hence reducing its length
You could correct your for loop :
function RandomDraw() {
var length = myArray.length;
var ri = 0;
for (var i=0;i<length;i++) {
ri = Math.floor(Math.random() * myArray.length);
console.log("Random index to be drawn : " + ri);
// removing that index from the array :
myArray.splice(ri, 1);
console.log("myArray after a random draw : ", myArray);
}
}
Or, you could use a while loop :
function RandomDraw() {
var ri = 0;
while (myArray.length > 0) {
ri = Math.floor(Math.random() * myArray.length);
console.log("Random index to be drawn : " + ri);
// removing that index from the array :
myArray.splice(ri, 1);
console.log("myArray after a random draw : ", myArray);
}
}

Javascript - How do I clear out a previous value in a DIV?

i'm making a game where 2 players are fighting one another.
I have it setup where the document writes the objects hp out (100). However, when I make a event where the player suffers 10 damage, it should write out 90 in the hp bar. Instead it writes out 10090.
How can I get it where the previous value gets updated, rather than it continuing to write beside the previous value?
function player (hp, mana, stamina){
this.hp = hp;
this.mana = mana;
this.stamina = stamina;
}
function npc (hp, mana, stamina) {
this.hp = hp;
this.mana = mana;
this.stamina = stamina;
}
var alistar = new player (100, 50, 30);
var dragon = new npc (100, 50, 30);
document.getElementById("hp").innerHTML += alistar.hp;
if ( 0 < 1) {
alistar.hp = alistar.hp - 10;
document.getElementById("hp").innerHTML += alistar.hp;
}
Doing the = sign works, but it removed any HTML words I had in there. I suppose I can make a 2nd div box for my HTML needs and keep the value seperate.
Just put = symbol instead of +=:
The = operator overwrite the previous value. On the other hand, the += is the union between the + operator and the = operator, and is the "shortway" to achieve the next:
For example, if you want to add a value to a variable you can do this:
var a = 3,
value = 10; /* Your value, i.e. 10 */
a = a + value; /* a values 13 */
BUT, you can get the same result using the += operators:
var a = 3,
value = 10; /* Your value, i.e. 10 */
a = += value; /* This adds the value of a to the value of value variable. */
As you can think, the value of a is 13, too as the below example.
Regarding to your code...
CODE:
if ( 0 < 1) {
alistar.hp = alistar.hp - 10;
document.getElementById("hp").innerHTML = alistar.hp; /* UPDATE */
}
if ( 0 < 1) {
alistar.hp = alistar.hp - 10;
document.getElementById("hp").innerHTML = alistar.hp;
}
+= is concatenating the values and adding them together (seemingly in string format). Instead, you want to use "=" to assign the value of the hp to the hp element, overwriting the existing innerHTML.

javascript - generate a new random number

I have a variable that has a number between 1-3.
I need to randomly generate a new number between 1-3 but it must not be the same as the last one.
It happens in a loop hundreds of times.
What is the most efficient way of doing this?
May the powers of modular arithmetic help you!!
This function does what you want using the modulo operator:
/**
* generate(1) will produce 2 or 3 with probablity .5
* generate(2) will produce 1 or 3 with probablity .5
* ... you get the idea.
*/
function generate(nb) {
rnd = Math.round(Math.random())
return 1 + (nb + rnd) % 3
}
if you want to avoid a function call, you can inline the code.
Here is a jsFiddle that solves your problem : http://jsfiddle.net/AsMWG/
I've created an array containing 1,2,3 and first I select any number and swap it with the last element. Then I only pick elements from position 0 and 1, and swap them with last element.
var x = 1; // or 2 or 3
// this generates a new x out of [1,2,3] which is != x
x = (Math.floor(2*Math.random())+x) % 3 + 1;
You can randomly generate numbers with the random number generator built in to javascript. You need to use Math.random().
If you're push()-ing into an array, you can always check if the previously inserted one is the same number, thus you regenerate the number. Here is an example:
var randomArr = [];
var count = 100;
var max = 3;
var min = 1;
while (randomArr.length < count) {
var r = Math.floor(Math.random() * (max - min) + min);
if (randomArr.length == 0) {
// start condition
randomArr.push(r);
} else if (randomArr[randomArr.length-1] !== r) {
// if the previous value is not the same
// then push that value into the array
randomArr.push(r);
}
}
As Widor commented generating such a number is equivalent to generating a number with probability 0.5. So you can try something like this (not tested):
var x; /* your starting number: 1,2 or 3 */
var y = Math.round(Math.random()); /* generates 0 or 1 */
var i = 0;
var res = i+1;
while (i < y) {
res = i+1;
i++;
if (i+1 == x) i++;
}
The code is tested and it does for what you are after.
var RandomNumber = {
lastSelected: 0,
generate: function() {
var random = Math.floor(Math.random()*3)+1;
if(random == this.lastSelected) {
generateNumber();
}
else {
this.lastSelected = random;
return random;
}
}
}
RandomNumber.generate();

Categories

Resources