Random number within range with no uniques (bingo) [duplicate] - javascript

This question already has answers here:
How to randomize (shuffle) a JavaScript array?
(69 answers)
Closed 5 years ago.
I'm trying to create a sort of a bingo number generator, where I generate a unique number and display it alone.
I also want that number + all the next numbers I'm generating to display at the bottom in a line.
My issue here is that whenever it hits a duplicate it loops until it finds a unique number, but displays that number as many times as it looped in the bottom row. So if I generate the numbers [4, 6, 2] and then another 4 it would keep looping until it found another number that's not already in the array.
If it hits the numbers in the array 2 times then found a 5, it would display as [4, 6, 2, 5, 5, 5,]. Is there anything I can do to not make it display the first 2 5's?
window.onload = startup;
function startup() {
document.getElementById("button").onclick = newNumber1;
}
var number = 0;
var bingoNumber = [];
var i;
function newNumber1() {
number = Math.floor((Math.random() * 9) + 1);
clickME();
}
function clickME() {
for (i = 0; i < bingoNumber.length; i++) {
if (number === bingoNumber[i]) {
newNumber1();
}
}
bingoNumber.splice(0, 0, number);
document.getElementById("display").innerHTML = bingoNumber[0];
document.getElementById("row").innerHTML = bingoNumber;
}
<button type="button" id="button">Click</button>
<div id="display"></div>
<div id="row"></div>

Your clickMe calls newNumber1 before it finishes executing, which isn't the problem. The problem is that newNumber1 calls another instance of clickMe, and the loop continues. So by the time newNumber1 generates a unique number, the current and previous instances of clickMe finishes inserting the same new number every time.
Another problem is that, even if you get this working, the loop in clickMe will go on and on if bingoNumber contains all possible unique number that newNumber1 can generate.
Try this:
window.onload = startup;
var bingoNumber = []; // contains all generated numbers
function startup(){
document.getElementById("button").onclick = clickMe;
}
function newNumber(){
// generate a new number
return Math.floor((Math.random() * 9) + 1);
}
function clickMe(){
// if bingoNumber contains all possible values, don't run the rest
// change this to however you want to terminate it
if(bingoNumber.length==9){ return false; }
var num; // number to add to the array
// generate a new number until it is unique
for(num=newNumber();bingoNumber.indexOf(num)>=0;num=newNumber());
// add the unique number in the beginning of the array
bingoNumber.unshift(num);
// display last generated value
document.getElementById("display").innerHTML = bingoNumber[0];
// display all generated value
document.getElementById("row").innerHTML = bingoNumber;
}

Don't add the number to array and display stuff until you really found the unique number:
var found;
function clickME() {
found = true;
for (i=0; i < bingoNumber.length; i++) {
if (number === bingoNumber[i]){
newNumber1();
found = false;
}
}
if(found) {
bingoNumber.splice(0, 0, number);
document.getElementById("display").innerHTML = bingoNumber[0];
document.getElementById("row").innerHTML = bingoNumber;
}
}

This will give you all the numbers without running out of stack space. There is an alert at the end to let you know that all the numbers have been called and will also hide the button so you can't click it again. That one you don't need...but why not?
window.onload = startup;
var bingoNumber = [];
function startup(){
document.getElementById("button").onclick = newNumber1;
}
function newNumber1() {
clickME(Math.floor((Math.random() * 9) + 1));
}
function clickME(num) {
if(bingoNumber.length < 9){
if (bingoNumber.indexOf(num) !== -1){
newNumber1();
}else{
bingoNumber.splice(0, 0, num);
document.getElementById("display").innerHTML = bingoNumber[0];
document.getElementById("row").innerHTML = bingoNumber;
}
}else{
alert("All numbers have been picked");
document.getElementById("button").style.visibility = "hidden";
}
}

Related

How do I get Javascript to remember a variable that is reset in my function, yet initially defined outside of my function?

I'm creating a game where the computer tries to guess the user's number based on user feedback like too high or too low. I'm using a binary search. The functions work properly, however, every time the buttons are pressed, the code resets to make the original list from 1 to 100 making the guess 50 instead of remembering the new list and guess defined inside my functions.
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function(guess) {
while (list.includes(guess) == true) {
list.shift()
};
var guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function(guess) {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
var guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow(guess);"> Too Low</button>
<button id="TooHigh" onclick="toohigh(guess);">Too High</button>
your over use of the variable guess is causing all sorts of issues
no need to pass guess from onclick to the function
don't declare a var guess inside the functions
et voila - your code works now
var list = new Array();
for (i = 0; i <= 100; i++) {
list.push(i)
}
//console.log(list)
// List is intially an empty array (list). The
// for loop generates integers from
// 0 to 100 and pushes them into the array.
var guess = list[Math.floor((list.length / 2))];
console.log(guess);
var toolow = function() {
while (list.includes(guess) == true) {
list.shift()
};
guess = list[Math.floor((list.length / 2) - 1)];
console.log(list);
console.log(guess)
}
// toolow(guess)
var toohigh = function() {
var last = parseInt(list.length);
while (list.includes(guess) == true) {
list.pop()
};
guess = list[Math.round(list.length / 2)];
console.log(list);
console.log(guess)
}
// toohigh(guess)
<h1> Guess Your Number </h1>
<button id="TooLow" onclick="toolow();"> Too Low</button>
<button id="TooHigh" onclick="toohigh();">Too High</button>

When click print from 1 to 10, on the second click print from 10 to 20 etc

I'm trying to make a button where the user can click and that what will happen:
var score = 0;
document.getElementById('button').addEventListener('click', addScore);
function addScore() {
score += 5;
}
And now it's the step that I don't know how to make:
When the user click the button the function addScore should work, after this function worked, there is something need to be printed on the screen:
and it must be for the first click:
1
2
3
4
5
on the secound click the printed text must be
6
7
8
9
10
etc
You can add a loop and, with a bit of math, calculate the range of numbers that you need to add with each click.
var clicked = 0;
const div = document.querySelector('div');
document.querySelector('button').addEventListener('click', addScore);
function addScore() {
// Get the new range
// e.g initially this will be 1 (5 * 0) + 1
const range = (5 * clicked) + 1;
// Set up a new array to which we will add the numbers
let arr = [];
// Loop from range to range + 5 and push each
// number into the array
for (let i = range; i < range + 5; i++) {
arr.push(i);
}
// Join the array with a `<br/>` element and add it to before the
// end of your output div
div.insertAdjacentHTML('beforeend', `${arr.join('<br/>')}<br/>`);
// Increase the click value
++clicked;
}
<button>Click</button>
<div></div>
Use the following code:
var score = 0;
document.getElementById('button').addEventListener('click', addScore);
function addScore() {
var html = '';
for (var i=0; i<5; i++) {
html+=(score+1)+'<br>';
score++;
}
document.getElementById('#idofcontentdiv').innerHTML = html;
}
This increments score upto next 5 iterations and keeps its value into a variable 'html', then use the variable to put into a dom element content.
Add following inside addScore() method :
function addScore(){
for(var i = 0; i < 5; i++)
console.log(++score)
}
Variable score should be initialized to 0
Since you have not specified where exactly to print, I am assuming it is console.
Edit: i got working example here is fiddle: https://jsfiddle.net/apd0z7ho/
html
var score = 0;
<button id="button">click me</button>
<p id="results"></p>
javascript
var score = 0;
document.getElementById('button').addEventListener('click', addScore);
function addScore() {
score += 5;
for(var i = score-5; i < score; i++){
document.getElementById("results").innerHTML += i+1+"<br>";
}
}

Count amount of time a number appears in an Array

So I have a dice rolling function. I want to roll 2 dice 20 times, each time I roll, I want to add those numbers, and then I want to see how many times the sum appears, and put that number into an array.
function Dice() {
this.roll = function() {
var randomValue = Math.ceil(Math.random() * 6);
this.side = randomValue;
return this.side;
}
}
var dice1 = new Dice();
var dice2 = new Dice();
function getAmount() {
var finalArray = [];
function diceSum() {
var sum = dice1.roll() + dice2.roll();
return sum;
}
var trackSum = [];
for (var i = 1; i <= 20; i++) {
trackSum.push(diceSum());
}
var reduced = trackSum.reduce(function(acc, sum, i, arr) {
return acc.i += sum;
}, {});
return reduced;
}
so I get trackSum which has 20 numbers in an array which, each number is the sum of the 2 dice rolled. If sum = 2 and it appears 5 times, sum = 4, appears 2 times, sum = 3, appears 1 time, final array should look like
[5, 2, 1]
So far I tried a reduce method, filter, and forEach. I just can't figure out how to compare the numbers to see how many times it's appearing. Any help would be appreciated. Thanks!
Use an object whose keys are the sums, and values are the number of times the sum appears. Loop through trackSum and increment the value of the corresponding element.
var freq = {};
trackSum.forEach(function(sum) {
freq[sum] = freq[sum] ? freq[sum] + 1 : 1;
}
console.log(freq);
Apologies for answering my own question, but after some googling, I figured it out. So don't pay attention to the reduce method I have in my original post. This is what I did instead:
var countedSum = trackSum.reduce(function(emptyObj, sum, i, arr){
if (sum in emptyObj){
emptyObj[sum]++
} else {
emptyObj[sum] = 1
}
return emptyObj;
}, {});
This returns an object, with the sum value as the key, and the amount of times it happens as the value.
Then I learned a new method that grabs the values and puts it in an array.
Object.values(countedSum)
That solves it!
Thanks #Barmar for your help!

JS Recursive Function Issues

I can't seem to get this to repeat whenever past and current are the same (it's a new quote generator).
function random() { // random number 0-9
var number = Math.floor(Math.random() * 9);
return number;
}
var past = [0]; // array of past quotes
function writer() { // on button click for new random quote
var current = random();
past.push(current);
function checker() {
if (past[past.length - 2] === past[past.length - 1]) {
current = random();
checker();
}
}
checker();
}
Rekursiv geht meistens schief (sorry no English for that)
You did not change the last value if the condition is true:
var past = [-1]; // impossible value;
function writer() { // on button click for new random quote
var current = random(); // get a first random
past.push(current); // add this to past array
function checker() {
// check last two values
if (past[past.length - 2] === past[past.length - 1]) {
current = random(); // if equal, get a new random;
checker(); // re-call - BUT -
// as there' actually no change to past,
// we're in an infinite loop.
}
}
checker();
}
Change:
var past = [-1]; // impossible value;
function writer() { // on button click for new random quote
var current = random(); // get a first random
past.push(current); // add this to past array
function checker() {
// check last two values
if (past[past.length - 2] === past[past.length - 1]) {
current = random(); // if equal, set a new random even to past
past[past.length - 1] = current;
checker(); // re-call
}
}
checker();
}

Assigning value to id only once

I've a problem that has been bugging me for a while now.
I have 14 divs each which must be assigned a random ID (between 1 and 14) each time the page loads.
Each of these divs have the class ".image-box" and the format of the ID I'm trying to assign is 'box14'
I have the JS code working to assign random IDs but I'm having trouble not getting the same ID to assign twice.
JavaScript
var used_id = new Array();
$( document ).ready(function() {
assign_id();
function assign_id()
{
$('.image-box').each(function (i, obj) {
random_number();
function random_number(){
number = 2 + Math.floor(Math.random() * 14);
var box_id = 'box' + number;
if((box_id.indexOf(used_id) !== -1) === -1)
{
$(this).attr('id',box_id);
used_id.push(box_id);
}
else
{
random_number();
}
}
});
}
});
Thanks for your help,
Cheers
Mmm, random...
Instead of using a randomly generated number (which, as your experiencing, may randomly repeat values) just use an incrementally-updated counter when assigning IDs.
function assign_id() {
var counter = 0;
$('.image-box').each(function (i, obj) {
$(this).attr('id','image-box-' + counter++); }
});
}
I think this is what you want and DEMO
$(document).ready(function() {
assign_id();
});
function assign_id() {
var numberOfDiv = $('.image-box').length;
var listOfRandomNumber = myFunction(numberOfDiv);
$('.image-box').each(function(i, obj) {
$(this).attr("id",listOfRandomNumber[i]);
});
};
//Getting List Of Number contains 1 to the number of Div which is
//14 in this case.
function myFunction(numberOfDiv ) {
for (var i = 1, ar = []; i < numberOfDiv +1 ; i++) {
ar[i] = i;
}
ar.sort(function() {
return Math.random() - 0.5;
});
return ar;
};
I would suggest to have a global array like u have for user_id and push assigned div ids into array. Then you can check before assigning random id to div. If it is assigned use different one.
Hope this helps.
Cheers.
First how you'd use my implementation:
var takeOne = makeDiminishingChoice(14);
In this case, takeOne is a function that you can call up to 14 times to get a unique random number between 1 and 14.
For example, this will output the numbers between 1 and 14 in random order:
for (var i = 0; i < 14; i++) {
console.log(takeOne());
}
And here is the implementation of makeDiminishingChoice itself:
var makeDiminishingChoice = function (howMany) {
// Generate the available choice "space" that we can select a random value from.
var pickFrom = [];
for (var i = 0; i < howMany; i++) {
pickFrom.push(i);
}
// Return a function that, when called, will return a value from the search space,
// until there are no more values left.
return function() {
if (pickFrom.length === 0) {
throw "You have requested too many values. " + howMany + " values have already been used."
}
var randomIndex = Math.floor(Math.random() * pickFrom.length);
return pickFrom.splice(randomIndex, 1)[0];
};
};
It's better to use incremental values(or something like (new Date).getTime()) if all you want to do is assign unique values. But if, for some reason, you must have randomly-picked values(only from 1-14) then use something like this to pick unique/random values
var arrayId = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
function getRandomId(array) {
var randomIndex = Math.floor(Math.random() * (array.length));
var randomId = array.splice(randomIndex, 1);
return randomId[0];
}
Now getRandomId(arrayId) would return a randomly picked value from your array and then remove that value so that it is not repeated.

Categories