Beginner - document.write in while loop - javascript

I'm trying to make a program where the user guesses a number from 1 to 100. You get 10 guesses and, the program should tell the user if his/hers guess is too high or too low along the way, however the program does not write on the document until all 10 guesses are used. How can I get around this?
Here is my code:
var a = Math.random();
var b = a * (101 - 1) + 1;
var c = Math.floor(b);
document.write(b + "<br>");
document.write(c + "<br>");
var d = 1;
while (gjett != c && d <= 10) {
var gjett = Number(prompt("Gjett på et tall fra 0 til 100"));
if (gjett < c) {
document.write("Tallet er høyere enn " + gjett + ".<br>");
}
if (gjett > c) {
document.write("Tallet er lavere enn " + gjett + ".<br>");
}
d = d + 1;
}

Pro-tip: don't use document.write.
Now, the reason you aren't seeing anything is, basically, the browser is either in JavaScript mode or rendering mode. As long as some JavaScript is running, the DOM is not going to be rendered. That way if you make multiple changes to the DOM, the browser doesn't waste resources on rendering all of the little changes in between.
A better way of handling this would be with a button and some kind of input.
// Wait for the user to click on the button
document.querySelector('button').addEventListener('click', function() {
// Get the value the user put in
var inputEl = document.querySelector('input');
// Make sure it's an integer
var value = parseInt(inputEl.value);
// Get the output element
var outputEl = document.getElementById('output');
// Tell the user what they guessed
outputEl.innerHTML = 'You guessed ' + value;
});
<input type="text" />
<button>Try</button>
<br />
<p id="output"></p>
You can figure out the actual logic of the guessing game yourself ;)

As others have suggested, you should avoid using document.write() in real-world applications, as there are more effective ways of adding elements to a page.
To answer your question: you don't see the page update while you're repeatedly submitting your guesses because the browser is still evaluating your while() loop, and deferring the re-rendering of the visible page until the while loop terminates.
The most direct way to achieve what you're asking, without changing much of your code, would be to substitute your while loop with an interval, such that your code executes asynchronously and doesn't block the browser from updating the rendered page. (Because of its blocking nature, confirm() (like other methods like alert()) is probably not the best choice for this interaction.)
var a = Math.random();
var b = a * (101 - 1) + 1;
var c = Math.floor(b);
document.write(b + "<br>");
document.write(c + "<br>");
var d = 1;
var interval = setInterval(function() {
if (gjett != c && d <= 10) {
var gjett = Number(prompt("Gjett på et tall fra 0 til 100"));
if (gjett < c) {
document.write("Tallet er høyere enn " + gjett + ".<br>");
}
if (gjett > c) {
document.write("Tallet er lavere enn " + gjett + ".<br>");
}
} else {
clearInterval(interval);
}
}, 0);

Related

JS - Prevent long loop javascript from "crash" browser implementation

I have a long loop that takes maybe 10 mins or more, and I want to set always a new time to avoid it to continue. But it dosen't works.
function problem3(){
var img = document.getElementById('p_3');
img.style.display = img.style.display === 'block' ? 'none' : 'block';
var number=600851475143;
var t = new Date();
for(var i=3;i*i<=number;i+=2){
if(isPrime(i) && number%i==0){
var maxPrime = i;
}
setInterval(function(){time(t)},5000);
}
document.getElementById("p3").innerHTML = 'Il più grande divisiore primo di <span>'+number+"</span> è <span>" + maxPrime+"</span>";
}
function time(t){
return console.log(Date() - t);
}
If I put console.log(Date() - t);in the problem3() function it works, but I can't do Date()-t every 5 seconds, something like setInterval(Date()-t,5000)
This is a case where you might consider using the workers API. Instead of freezing the browser, let the job be done in the background and call back to the main thread when it's done.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
JavaScript is not multithreaded. So we think of setInterval() as running a piece of code every n ms (5000 in your example). But that's not quite true. If there's already script running when the interval elapses, the best that can happen is the bit of code gets added to a queue to be executed - but nothing from that queue is going to run until the already-running script finishes.
So in rough terms that's why it's not working, but what to do? Well, if you want anything to happen before problem3() returns, then problem3() is going to have to make it happen in a synchronous way.
For example, you could create a lastOutputTime variable, initialize it to the current time, and on each iteration through the for loop compare the current time to the stored value. If 5 seconds have passed, output to console and update lastOutputTime.
Your algorithm should be improved to something like this:
function maxPrimeFactor(number) {
if (number == 0 || !Number.isInteger(number) ||
number > Number.MAX_SAFE_INTEGER) return NaN;
number = Math.abs(number);
while(number % 2 == 0) number /= 2;
for (var i = 3; i * i <= number; i += 2) {
while(number % i == 0) number /= i;
}
return number;
}
var number = 600851475143;
console.log('maxPrimeFactor(' + number + ') == ' + maxPrimeFactor(number));
If for some numbers you need too much time, then break the loop into smaller chunks and asynchronize. But never use setInterval for this, and especially never use setInterval inside a long loop. setInterval schedules some task to run every n milliseconds, so if you use it in a loop, after i iterations, the task will run i every n milliseconds! And setInterval is so problematic because it can freeze the browser if the task takes more than n milliseconds. You should use setTimeout instead.
However, this would be useless in this case. The algorithm above can detect that 304250263527209 (15 digits) is a prime almost instantly. Given that the maximum safe integer is 9007199254740991 (16 digits), I don't think you will have problems for any number.
If you say the algorithm takes so long, it may be because you are trying it with bigger numbers. But be aware JS numbers are 64-bit floating point numbers, and thus integers can't be represented accurately above Number.MAX_SAFE_INTEGER. You will get a wrong result anyways, so do not even try to calculate that.
In the case of the Project Euler #551, a brute-force approach would be
function sumOfDigits(n) {
var sum = 0;
while(n != 0) {
sum += n % 10;
n = Math.floor(n/10);
}
return sum;
}
function sumDigitsSeq(n) {
return new Promise(function(resolve) {
var i = 1;
var chunkSize = 1e5;
var sum = 1;
(function chunk() {
chunkSize = Math.min(chunkSize, n-i);
for (var j=0; j<chunkSize; ++j, ++i) {
sum += sumOfDigits(sum);
}
if (i >= n) return resolve(sum);
console.log('Please wait. sumDigitsSeq(' + i + ') == ' + sum);
setTimeout(chunk, 60);
})();
});
}
var number = 1e6;
sumDigitsSeq(number).then(function(result) {
console.log('Done! sumDigitsSeq(' + number + ') == ' + result);
});
Of course brute-force is not the appropriate way to solve the problem.

JavaScript OnClick Method

I was having trouble with the OnClick method I was learning while creating a game. Every time I enter the value and click the button, it is stuck in a loop, I tried document.write and it works using that, but than it opens a new page instead of showing up on screen.
I am new to the programming community, so any help would be nice.
<body>
<p>Enter an integer between 1-100 here:
<input id="number" type="text" />
</p>
<p>
<button onclick="onclickFunction()" type="button">Enter</button>
</p>
<p id="result"></p>
<script type="text/javascript">
function onclickFunction() {
var a = Math.random();
var b = a * 100;
var c = Math.ceil(b);
var intNumber;
var count = 0;
var bool = false;
do {
do {
intNumber = document.getElementById("number").value;
}
while (intNumber > 100 || intNumber < 0);
if (intNumber > c) {
document.getElementById("result").innerHTML = "Too High " + "</br>";
bool = false
} else if (intNumber < c) {
document.getElementById("result").innerHTML = "Too Low " + "</br>";
bool = false
} else if (intNumber == c) {
document.getElementById("result").innerHTML = "You Win!" + "<br>" + " It took you " + count + " tries";
bool = true
}
count = count + 1
} while (bool !== true);
document.getElementById("result").innerHTML = "Win!";
}
</script>
</body>
Updated:
<script type="text/javascript">
// Declare all your functions first
// These functions expect no parameters and return values.
function onclickFunction()
{
var a = Math.random();
var b = a * 100;
var c = Math.floor(b);
// Input from text box.
var randomNumber = document.getElementById("number").value;
// Output to paragraph.
if (randomNumber < c && randomNumber != c)
{
document.getElementById("result").innerHTML = "Too Low " + "</br>";
}
else if (randomNumber > c && randomNumber != c )
{
document.getElementById("result").innerHTML = "Too High" + "</br>";
}
else if (randomNumber == c)
{
document.getElementById("result").innerHTML = "Win!";
}
// Clear text box for further input.
document.getElementById("name").value = "";
}
</script>
<p>Enter an integer between 1-100 here: <input id="number" type="text" /></p>
<p><button onclick="onclickFunction()" type="button">Enter</button></p>
<p id="result"></p>
</body>
First of all, it is always useful to create a fiddle.
That way people who are reading your question can run your code immediately.
Let's break down the code
var a = Math.random();
var b = a * 100;
var c = Math.ceil(b);
This can be done in a single line, to save variables.
do
{
intNumber = document.getElementById("number").value;
}
while (intNumber > 100 || intNumber < 0);
I'm not a big fan of using do/while loops this way, although it can come handy when you want to run the do code at least once, like now.
This loop keeps running when the number is bigger than 100, or smaller than 0. So if I pick an incorrect number that means my browser crashes.
if (intNumber>c){
document.getElementById("result").innerHTML = "Too High " + "</br>";
bool = false
}else if (intNumber<c){
document.getElementById("result").innerHTML = "Too Low " + "</br>";
bool = false
}else if (intNumber == c){
document.getElementById("result").innerHTML = "You Win!" + "<br>" + " It took you " + count + " tries";
bool = true
}
First you are checking if the guess is bigger than the answer, than if it's smaller. That means that the last check if it's equal is unnecessary, since that is the only option left. You can just use an else here.
Also try to be consistent with your spacing and where you place your curly brackets.
do{
//Stuff
}
and
do
{
//Stuff
}
Are both valid ways to use brackets, but stick to one style or your code will get too confusing.
count = count + 1
A small oversight here is that the count starts at 0. So when you guess the number in a single try, it will say you have done it in 0 tries.
while (bool !== true);
document.getElementById("result").innerHTML = "Win!";
}
All the previous code will be done until bool becomes true. The problem here is that if I entered a wrong number (or an invalid number). The program will keep running the if statement which requires a lot of computer power since it never stops. It is impossible to change your guess and the page crashes, because the browser is stuck in the while loop.
The simplest solution for this is to calculate if the new guess was correct when the player inputs a new number. So when onClickFunction is called again.
That way you never have to use a while loop. Although you have to calculate the random number somewhere else.
I hope that helped, if you have any question let me know!

Error:prompt is not defined. There's a bug while trying to generate a phone number

I am trying to create a simple program that takes an area code input from the user, generates a random phone number for them and log the full 10 digits to the console. I am getting a 'prompt is not defined error', and nothing logs after the prompt box pops up. I'm not sure why I get the prompt error since it works in the browser, but it's obvious that I have another error in my code since it isn't working in the first place.
Can anyone point out to me what I'm doing wrong? Thanks in advance for the help!
function yourNum() {
var yourNumber = '';
var n = 0;
var loc = parseInt(prompt('what is your area code?', 773), 10);
if (loc.length === 3) {
loc = '(' + loc + ')';
}
while (n < 7) {
yourNumber[n] = Math.floor(Math.random() * (9));
n++;
}
return loc + ' ' + yourNumber;
}
yourNum();
yourNum() returns a number, but never prints to console or alerts. I made 3 changes to your code, and it seems to do what you want:
function yourNum() {
var yourNumber = '';
var n = 0;
var loc = parseInt(prompt('what is your area code?', 773), 10);
if (loc.toString().trim().length === 3) {
loc = '(' + loc + ')';
}
while (n < 7) {
yourNumber += Math.floor(Math.random() * (9));
n++;
}
console.log(loc + ' ' + yourNumber);
alert(loc + ' ' + yourNumber);
return loc + ' ' + yourNumber;
}
yourNum();
It seemed like you're trying to access yourNumber based on index yourNumber[n]. I changed it to append the number to the String through each iteration in the loop.
I added a console.log and alert() to print to console, and create a dialog box with the new number. Alertanvely, you could also console.log(yourNum()); and remove the two lines from inside the function.
I changed loc.length to loc.toString().trim().length. loc is an int currently.

Javascript issues?

So here is what I have so far. I am trying to create a button that calculates percentages of test scores then displays onto the page when you press a button. Bear in mind i'm a VERY new programmer with less than 3 weeks experience and I could really use the help.
var sam = 9;
var sally = 8;
var donald = 4;
function go(){
function percentage();
alert("Sam's score on the test is " + samp + "%\nSally's score on the test is "
+ sallyp + "%\nDonald's score on the test is " + donaldp + "%")
}
function percentage(){
var samp = sam / 10 * 100;
var sallyp = sally / 10 * 100;
var donaldp = donald / 10 * 100;
}
To invoke the percentage function, remove the function keyword. The next issue is that samp, sallyp, and donaldp are scoped to the function percentage, so they're not accessible in the go function. You should make percentage take an argument
function percentage (score) {
return score / 10 * 100;
};
Then, in go:
function go () {
console.log("Sam: " + percentage(sam) + ", Sally: " + percentage(sally) +
", Donald: " + percentage(donald));
};
You can write your script as:
<script> /*writing <script type="text/javascript"> is not mandatory
as by default it will take javascript as type
Semicolon is not mandatory in JS, but it's good practice to use it
*/
var sam = 9;
var sally = 8;
var donald = 4;
function go(){
//there are different ways to print on page (alert, document.write, etc...)
alert("Sam's score: " + percentage(samp) + "Sally's score: "
+ percentage(sally) + "Donald's score: " + percentage(donald));
}
function percentage(calc){
return score / 10 * 100;
}
</script>
Other ways to print may include:
--By getting element ID:
Suppose you have a HTML element as
or
in your script, you can use:
var el_info = document.getElementById("abc"); // to get the element information
Then, you can use:
el_info.innerHTML = "Sam's score: " + percentage(samp) + "Sally's score: "
+ percentage(sally) + "Donald's score: " + percentage(donald);
or, you can directly use:
document.getElementById("abc").innerHTML = "Sam's score: " +percentage(samp)+
"Sally's score: "+ percentage(sally) + "Donald's score: " + percentage(donald));
Your variables scope is not proper.....
You have two ways to declare them. First make them global so you can access them in both functions.
Another way is to declare them inside the Go function.
According to me you should declare them into GO function.
Note : as you are working on javasceipt .you can debug your code from Console in browser when you inspect element.

Generate multiple random numbers in JavaScript

I'm trying to write a script for roulette system and I want the script to run until the bank variable reaches 0 or 11,000, and produce three pieces of data after each spin.
I have left parts of the code out for simplicity. The code in the if else statement is not the problem. Running the script until the variable reaches a certain point is where I'm stuck.
Would anyone be able to help me rewrite this script please? Thanks in advance.
(function() {
var bank = 10000;
var bet = 1;
function spin() {
var number = Math.floor(Math.random() * 36);
if ( number == 0 ) {
document.write("<p>The number " + number + " is neither high nor low.</p>");
// removed
}
else if ( number > 18 ) {
document.write("<p>The number " + number + " is a high number.</p>");
// removed
}
else {
document.write("<p>The number " + number + " is a low number.</p>");
// removed
}
};
spin();
document.write("<p>Total bank is now " + bank + ".</p>");
document.write("<p>The next bet is " + bet + ".</p>");
})();
If you're calling this loop within a page (i.e. you don't want the page to hang up for the duration, or want to display results) you should use requestAnimationFrame:
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
Then set up your loop to only call itself if the bank is within your accepted range:
function spinLoop() {
spin();
//perform your UI updates here
if (bank >= 0 && bank <= 11000) requestAnimFrame(spinLoop);
}
You will, of course, need to call this function initially to start the loop:
spinLoop();

Categories