I joined few days ago this forum. I am trying to learn JavaScript and, as a “real case” exercise, I chose a simple MathGame I coded in VBA a while ago and I try to “translate” it in JavaScript.
Now I bumped into a new obstacle and I request your kind advice. I describe the issue:
- Desired behavior: Two random numbers are generated (integers, between 0-10, sum < 11) and their the addition is displayed. The player has to input the result in a textbox and press ENTER. The result has to be evaluated by the script (if it is the correct addition result) … and for the moment let’s stop here. - What I achieved: The two numbers are generated and displayed, the textbox is displayed and make the refresh for each new addition. [COLOR=“#FF0000”]- Where I got stuck: I failed to pass the user input (addition result) for evaluation.[/COLOR]
I read tens of pages of information but I still cannot figure the proper method (or maybe correct syntax) for using the value input by user.
For complete info, here is the code up to this moment:
<!DOCTYPE html>
<html>
<body>
<p id=“calc”></p>
<button onclick=“Add()”>CLICK HERE for a new addition</button>
<script>
function Add()
{
var y = Math.floor((Math.random()*11)+0)
var x = Math.floor((Math.random()*11)+0)
while ((x+y)>10)
{
var y = Math.floor((Math.random()*11)+0)
var x = Math.floor((Math.random()*11)+0)
}
var display = document.getElementById(“calc”)
display.innerHTML = x + " + " + y + " = <input type=‘text’ name=‘result’ id=‘result’ size=‘4’ autofocus>"
}
</script>
</body>
</html>]
I thank you in advance for any suggestion you might have.
Of course that for regular JS users the problem should be elementary. But please keep in mind I am totally new to JS and i am striving for better results.
What you’re looking for is either evaluation or parsing.
Here’s a simple parse, where we assume the user entered the right sequence:
var sumString = "1+2+3+4",
sumArray = sumString.split("+"),
sum = 0;
for (var i = 0; i < sumArray.length; i++) {
sum = sum + sumArray[i]*1;
};
console.log(sum);
It get’s gradually complicated as the user input diversifies.
Why does this seem more like a homework assignment than anything else? I’m a bit rusty in my javascripting, but I figured it out in about five minutes, but I think your problem is more with your logic flow than anything.
Since it’s always better to try and figure out things on your own, here are some hints for you…
Your basic page logic is flawed. You’re generating the form on the button click, which is not what you want. Your basic logic flow should be -> When the page is loaded, the number should be generated (and saved in memory), and the input box (which shouldn’t require scripting to create) available for the user to enter the value. The button click should then compare the entered number with the randomly generated value. Knowing this, how would you accomplish these two separate pieces of functionality?
FYI - your randomizer is pulling in numbers from 0-11, not 0-10.
Your loop logic is inefficient in recalculating BOTH numbers every time - how can you improve that logic?
I feel this is not what I am looking for. Maybe I expressed something wrong. I will try again:
The addition is generated by the script and displayed (x + y = )
After “=” sign I placed a textbox where the user (small child) inputs his guess about the addition result and press ENTER.
[COLOR=“#FF0000”]And here comes my obstacle:
I don’t succeed to transfer user input (the number in the textbox) to the script for validation as a correct result of the addition.[/COLOR]
I’m fiddling around with all kind of solutions, but nothing works. Is very possible that I made also syntax mistakes. That’s why i needed a small hint to put me on the right track.
I don’t know why it seems like a homework. This was your assumption, so only you can clarify it. I’ve done the initial VBA script as a game for my child (when he was 7 yo). It was a huge support for fast-learning elementary math. Now I’m trying to learn JS, and I used the same script idea as a project in JS.
Is not necessary that all of us should have a brilliant mind. Maybe I am a less intelligent and for sure I am infinite less experimented in programming than you and most members of this forum. But I have no problem in asking support on a public platform dedicated to this scope.
(1) How do I generate then a new pair of random numbers to add, if not by a button? Reloading the page???
(2) You have my script. Try it! If you get any 11 value, you deserve a prize
(3) For the moment I lack very basic JS skills, maybe is a little too early to dream about optimizing the script?. You can optimize something ONLY when you understand what you’ve done (wrong). This is not my case. For the moment at least
In any case I thank you for the time you invested in reading my post and for the useful advice.
The function is very inefficient - and it does give eleven possible values - between 0 and 10.
function Add() {
var y = Math.floor((Math.random()*11)+0)
var x = Math.floor((Math.random()*11)+0)
while ((x+y)>10) {
var y = Math.floor((Math.random()*11)+0)
var x = Math.floor((Math.random()*11)+0)
}
If the sum of the two random numbers is supposed to be less than 11 then you can do it as:
function Add() {
var y = Math.floor((Math.random()*11)+0)
var x = Math.floor((Math.random()*(11-y))+0)
You could also leave off the +0 as that doesn’t actually do anything useful given that the smallest value is going to be zero if you don’t add anything.
Sorry for the assumption, but this REALLY looks like a homework assignment, but if you say it’s not, then I’ll believe you. Part of the problem is you’re trying to treat a client side concept like a server side concept - won’t work. vbScript (asp classic) CREATES the generated HTML markup. Javascript works AGAINST the generated markup. In other words, one is before the markup, one is after.
To be honest, I missed that part of your assignment, but all your code does is display the initial problem - it doesn’t allow for anyway to check the answer (or save the answer for that matter)
True, as your loop weeds those out - I’m just pointing out a basic flaw - why check that something is over a threshold if the inputs can be invalid in the first place? How many times will either x or y in your example have 11 as the value in them? With that small of a random window to work from, pretty often.
It has nothing to do with code optimization - it’s basic logic and design patterns, which if you can get locked down, will allow you to transition from one language to another. Languages are only syntax - the logic and thought processes are essentially the same.
To show I’m accepting your answer to #1, I’ll show my quick and dirty script. It does exactly what your requirements ask for. I tried to comment it where I thought woud be helpful and appropriate.
Some caveats:
The scripting isn’t necessarily “best practice” - the onload and onclick methods aren’t the always the best methods to handle these pieces of functionality - it just works quick and dirty.
I’d probably also set the math.floor into a function as well to allow you to change that 1-10 value just once. Not a big deal, just a comment… - felgalls approach above is even better (and makes more sense). Changed to match that thought process…
<!DOCTYPE html>
<html>
<body onload="setValues()">
<p><span id="x"> </span> + <span id="y">&nsbp;</span> = </p>
<input type="text" id="myValue" name="myValue" />
<button onclick="CheckAnswer()">Try it</button>
<p id="answer"> </p>
<script>
var totalValue = 99; // to create a "global" value which is saved to memory....
// Create the problem to be resolved.....
function setValues() {
totalValue = 99; // to reset the counter.....
var x = Math.floor((Math.random()*10)); // see the *10? Only generates a random number between 1-10, not 11.
var y = Math.floor((Math.random()*(11 - x)));
totalValue = x + y;
// display the values to be added together...
document.getElementById("x").innerHTML = x;
document.getElementById("y").innerHTML = y;
}
// check the answer added by the user
function CheckAnswer() {
var myValue = document.getElementById("myValue"); // get the value entered by the user...
if (myValue.value == totalValue) {
// show that the user is correct, and get a new problem to solve.....
document.getElementById("answer").innerHTML = "Correct";
setValues();
} else {
// show that the user is incorrect and allow them to enter a new value....
document.getElementById("answer").innerHTML = "Incorrect";
}
}
</script>
</body>
</html>
Math.random produces a number >= 0 and < 1 (note it can never return exactly 1)
Math.floor rounds down to the nearest integer
So Math.floor(Math.random()*11) will produce the following eleven values with each occurring approximately 1/11th of the time - 0,1,2,3,4,5,6,7,8,9,10
Note that 11 does not appear in the list of possible results as .9999999999… times 11 (no matter how many extra 9s you add to the end of the first number) rounded down is never going to be greater than 10.
Well, seems this forum is very motivating for me Again, it was sufficient to post my problem and I found the solution myself in a few hours.
My solution, just for info:
It’s not necessary to create the group of selected functions, … etc.
Simply generate the random number and validate it against the checked boxes.
If no match, generate a new number (WHILE). If match then, problem solved.
I am aware that my solution is probably the most inappropriate considering the JavaScript Best Practices. But still, I succeeded to discover it myself after only one week of studying JavaScript.
Practically the exercise-game is completed now. Still, I’d like to bring some nice improvements to it. And to get the chance to gain more experience in JavaScript.
The first action of the user on site is actually to select (between radio buttons) what operation wants to practice - addition, subtraction, multiplication or division (remember the users are elementary school children).
I want to find a way of remembering, for each user, the selection he made at the last visit. To avoid re-selection of the same radio button if they come repeatedly during the day for a new session.
The first thought I had was to do it with cookies. I have zero experience with cookies, so I ask you to validate my “strategy”:
At browser (or page) closing the script collects the state of the buttons with getElementById
Creates the respective cookie(s)
At beginning of a new session gets from cookie(s) the previous value of the radio buttons
Changes the value of the radio buttons accordingly, also using getElementById
Of course instead of asking I could simply test the script. But my problem is that after only 2 weeks of JavaScript I am still “at the will” of some tiny inherent syntax mistakes, therefore I will not know if it’s one of my mistakes or the script idea is wrong.
You will need to use some kind of persistent storage and cookies seem like a good choice.
This will not work. There is no reliable “onPageClose” event to hook into that works across browsers.
You will need to hook into the onChange event of the radio button and update the cookie every time the user selects something different.
This all sounds entirely reasonable.
Not at all. We’re happy to help and it is nice to see someone who is asking for advice on how to solve a problem, as opposed to asking for the solution.
Depending on how quickly the page unloads you might get that to run one or possibly two statements before the script unloads to the point where the next statement no longer is there to run.
If trying to write a cookie the data to be written would almost certainly be unloaded before the save of the cookie was able to run.
<!DOCTYPE html>
<html>
<head>
<script>
var OptCalc
function setCookie()
{
var cname = "OptCalc"
for (var i = 0; i < 3; i++)
{
if (OptCalc == i)
{
var cvalue = i
}
}
var d = new Date();
d.setTime(d.getTime() + (30 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
function getCookie()
{
var cname = "OptCalc"
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++)
{
var c = ca[i].trim();
document.getElementById("cval").innerHTML=c.substring(name.length,c.length) // used this workaround to visualise if the cookie is identified at onload
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
}
return "";
}
function checkCookie()
{
var x=getCookie();
document.getElementById(x).checked=true
}
</script>
</head>
<body onload="checkCookie()">
<form name="F0" id="F0" onsubmit="return false">
<INPUT TYPE="Radio" Name="OpType" Value="Add10" id="0" onclick="OptCalc=0, setCookie()">
<INPUT TYPE="Radio" Name="OpType" Value="Add20p" id="1" onclick="OptCalc=1, setCookie()">
<INPUT TYPE="Radio" Name="OpType" Value="Add20" id="2" onclick="OptCalc=2, setCookie()">
</FORM>
<p id="cval"></p>
<SCRIPT>
</SCRIPT>
</body>
</html>
Still your observations are welcome. The code does what I wanted, but I am pretty sure it is ugly, breaks some important JS good practices, it’s awkward … anyway I am glad I did not give up
Now I have the ambition to adapt this solution to other form elements, to have a complete “personal” add-on for restoring forms.
One thing that could easily be improved is the use of inline event handlers (e.g. onclick=“…”).
It makes for cleaner code and better maintainability to use unobtrusive event listeners.