Reputation: 816
Here is a quick background on project goals: I'm trying to build a simple math game that provides random math problems when you click on a button. Later, I'll figure out a way to check whether the answers are correct. I started this process by creating an input form.
I'm trying to call a random function in a javascript array using a button in HTML. The button calls a random function that is decided when I refresh the page. Once I refresh the page, the a function is randomly selected and the button continues to give the results of that function over and over. The button only calls a different function if I refresh the page.
I would prefer to have the button call a random function in my array each time the button is clicked. Anybody know how I could achieve this?
Here's my code:
const btn = document.querySelector('#START')
const randomFunc = [
multiplication,
division,
addition,
subtraction,
]
btn.addEventListener(
'click', randomFunc[Math.floor(Math.random() * randomFunc.length)]
)
function multiplication(params) {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 13);
let problemResult = num1 * num2;
console.log(num1, '*', num2, '=', problemResult);
document.getElementById('mathProblem').innerHTML = (`${num1} * ${num2} =`);
}
function division(params) {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 12) + 1;
let problemResult = (num2 * num1) / num2;
console.log(num1, '/', num2, '=', problemResult);
document.getElementById('mathProblem').innerHTML = (`${num1} / ${num2} =`);
}
function addition(params) {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 13);
let problemResult = num1 + num2;
console.log(num1, '+', num2, '=', problemResult);
document.getElementById('mathProblem').innerHTML = (`${num1} + ${num2} =`);
}
function subtraction(params) {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 13);
let numList = [num1, num2];
numList.sort(function(a, b) {
return b - a
});
let problemResult = numList[0] - numList[1];
console.log(numList[0], '-', numList[1], '=', problemResult);
document.getElementById('mathProblem').innerHTML =
(`${numList[0]} - ${numList[1]} =`);
}
<div>
<button type="button" class="btn btn-primary btn-lg" id="START">Press here for your first problem</button>
<script src={% static 'js/game_logic.js' %}></script>
<p id="mathProblem">Your problem will appear here</p>
<form action="">
<input type="text" placeholder="Type your answer here">
</form>
</div>
Upvotes: 2
Views: 1946
Reputation: 65806
Your code of:
randomFunc[Math.floor(Math.random() * randomFunc.length)]
is not stored inside of a function, so as soon as the page loads and the script
is initially parsed, that statement is executed and your random function name is retrieved from the array and that code will be replaced with whichever function name was gotten, so for the rest of that page's use, the code will actually be static and be evaluated like this:
// showing multiplication here, but will be whichever random name was initially returned
btn.addEventListener('click', multiplication)
But, once it's gotten, the initial randomizing code won't be executed again, because it will have already been replaced by the result of the first pass through parsing the script
. So, in the end, you get one call for a random function reference and that result is what you stick with until the page is reloaded.
What you need is for that randomizing code to be executed every time the button is clicked, so by wrapping it in another function (which localizes the statement), that will happen:
btn.addEventListener(
'click', function() { randomFunc[Math.floor(Math.random() * randomFunc.length)](); }
)
Now, every time you click the button, randomFunc[Math.floor(Math.random() * randomFunc.length)]
will get a new function name and ()
after it will cause it to be invoked because the whole expression is inside of an anonymous function expression, which will become the event handler.
Upvotes: 2
Reputation: 3444
The function addEventListener()
adds one function to an HTML-Element when executed.
This means, when your addEventListener()
-line is executed (which it only is once, when your script is executed for the first time), it selects one of your functions and adds only that.
To be able to select one of you functions repeatedly on click, you would need to instead add a function that selects on of yours, instead of adding one of yours directly. That way, the "selection"-function runs every time your button is clicked.
Here is an example:
var funcToSelect = [func1, func2, func3];
document.querySelector('button').addEventListener('click', () => {
funcToSelect[Math.floor(Math.random() * funcToSelect.length)]();
});
function func1() {
console.log('First output');
}
function func2() {
console.log('Output from second');
}
function func3() {
console.log('Yet a third output');
}
<button>Run a random function!</button>
Upvotes: 1
Reputation: 423
Have you tried using a arrow function, like so
btn.addEventListener(
'click', () => randomFunc[Math.floor(Math.random() * randomFunc.length)];
)
This will also execute the function on each click
Upvotes: 1
Reputation: 675
Wrap with another function so that it gets executed on each click
btn.addEventListener('click', function () {
randomFunc[Math.floor(Math.random() * randomFunc.length)]()
})
Your code set the random function only once (on page Load) so it's always the same when clicking the button
btn.addEventListener('click', randomFunc[Math.floor(Math.random() * randomFunc.length)])
Upvotes: 1
Reputation: 1094
it's because you're already generated a function and assigned it here
btn.addEventListener(
'click', randomFunc[Math.floor(Math.random() * randomFunc.length)]
)
in order to randomize it you have to make a callback that generates a random function instead
btn.addEventListener(
'click', function() {
const a = randomFunc[Math.floor(Math.random() * randomFunc.length)];
a();
}
)
it should now work. https://jsbin.com/duyosiluna/edit?html,js,console,output
Upvotes: 1
Reputation: 781058
Wrap it in another function that selects a random function each time the click happens.
Also, your functions don't use params
, so it's not needed.
const btn = document.querySelector('#START')
const randomFunc = [
multiplication,
division,
addition,
subtraction,
]
btn.addEventListener(
'click',
function() {
randomFunc[Math.floor(Math.random() * randomFunc.length)]();
}
)
function multiplication() {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 13);
let problemResult = num1 * num2;
console.log(num1, '*', num2, '=', problemResult);
document.getElementById('mathProblem').innerHTML = (`${num1} * ${num2} =`);
}
function division() {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 12) + 1;
let problemResult = (num2 * num1) / num2;
console.log(num1, '/', num2, '=', problemResult);
document.getElementById('mathProblem').innerHTML = (`${num1} / ${num2} =`);
}
function addition() {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 13);
let problemResult = num1 + num2;
console.log(num1, '+', num2, '=', problemResult);
document.getElementById('mathProblem').innerHTML = (`${num1} + ${num2} =`);
}
function subtraction() {
let num1 = Math.floor(Math.random() * 13);
let num2 = Math.floor(Math.random() * 13);
let numList = [num1, num2];
numList.sort(function(a, b) {
return b - a
});
let problemResult = numList[0] - numList[1];
console.log(numList[0], '-', numList[1], '=', problemResult);
document.getElementById('mathProblem').innerHTML =
(`${numList[0]} - ${numList[1]} =`);
}
<div>
<button type="button" class="btn btn-primary btn-lg" id="START">Press here for your first problem</button>
<script src={% static 'js/game_logic.js' %}></script>
<p id="mathProblem">Your problem will appear here</p>
<form action="">
<input type="text" placeholder="Type your answer here">
</form>
</div>
Upvotes: 5