Home > Blockchain >  prompt() in a loop never shows writeln() content
prompt() in a loop never shows writeln() content

Time:03-27

I am new to javascript, having trouble with this assignment. My professor suggested the problem was due to needing to parseInt, but even after I added the parseInt, it still isn't working.

This displays fine in Firefox, and the "higher" and "lower" statements are displayed, but when I run it in Chrome or Edge, only the window asking for a number will render. I did look for help, but I cant see what I'm doing wrong. Most of the suggestions Ive seen online, don't address the code directly. Is this problem specific code related or something else?

function play() {

  let guess;
  let randNum = Math.floor(1   Math.random() * 999);
  let guessed = false;

  while (guessed == false) {
    guess = window.prompt("Enter a number from 1 to 1000");
    parseInt(guess);
    if (guess == randNum) {
      document.writeln("<li>"   "Congratulations! You guessed the correct number!</li>");
      guessed = true;
      document.writeln("</ol>");
      document.writeln("Your guess: "   guess);
      document.writeln("Actual number: "   randNum);
    } else if (guess > randNum) {
      document.writeln("<li>"   guess   " is Too High. Try Again.</li>");
      document.writeln("</ol>");
    } else if (guess < randNum) {
      document.writeln("<li>"   guess   " is Too Low. Try Again.</li>");
      document.writeln("</ol>");
    }
  }

}

window.addEventListener("load", play, false);

CodePudding user response:

As I understand it, JavaScript is single-threaded, meaning that it has only one execution thread. Methods like prompt() and alert() block that thread. As long as prompt() is called in a loop, writeln content will not be rendered on the page.

One way to address this with your existing code is to use setTimeout() to delay the next call to prompt(), which allows content to be rendered in the meantime.

That being said, I recommend a more asynchronous method that does not rely on prompt() or writeln().

var randNum = Math.floor(1   Math.random() * 999);

function ask() {
  let guess = parseInt(window.prompt("Enter a number from 1 to 1000"));
  if (guess == randNum) {
    document.writeln("<div>Congratulations! You guessed the correct number!</div>");
    document.writeln("<div>Your guess: "   guess   ". Actual number: "   randNum   "</div>");
  } else if (guess > randNum) {
    document.writeln("<div>"   guess   " is Too High. Try Again.</div>");
    setTimeout(ask, 50);
  } else if (guess < randNum) {
    document.writeln("<div>"   guess   " is Too Low. Try Again.</div>");
    setTimeout(ask, 50);
  }
}

window.addEventListener("load", ask, false);

CodePudding user response:

To ease the querying or creation of the desired DOM Elements — create two reusable functions:

// DOM utility functions:

const EL = (sel, par) => (par || document).querySelector(sel);
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

that can be used to cache your Elements and use them later in your game logic

// Cache your DOM elements!
const EL_number  = EL("#number"); 
const EL_check   = EL("#check");
const EL_answers = EL("#answers");

which will target and cache your three HTML elements by theri id attribute selector. As said above, instead of using prompt, use a better and less invasive UI (User interface) right into your App:

Enter a number from 1 to 10: <input id="number" type="text">
<button id="check" type="button">CHECK</button>
<ol id="answers"></ol>

Then create two let variables for the guessed state and one for the random number, so that when you start a new game you can change their values:

// Make available for multiple games!
let num_rand;
let isGuessed;

then, giving your specific game, you need two more functions, one to start (and restart) the game and one for your game logic:

// Call this function to start a new game!
const start = () => {
  // Reset old variables
  // Create a new random number!!
};

// Call this function on button CHECK click!
const check = () => {
  // Game logic goes here!
}

// Assign listener to button:
EL_check.addEventListener("click", check);

// Start a new game!
start(); 

Demo time:

// DOM utility functions:

const EL = (sel, par) => (par || document).querySelector(sel);
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);

// Task:

// Cache your DOM elements!
const EL_number = EL("#number"); // PS: remember, use const for constants!
const EL_check = EL("#check");
const EL_answers = EL("#answers");

// Make available for multiple games!
let num_rand;
let isGuessed; // Try to prefix boolean variables with "is*"


// Call this function to start a new game!
const start = () => {
  // Clear old answers:
  EL_answers.innerHTML = "";

  // Reset old guessed state
  isGuessed = false;

  // Generate a new random number:
  num_rand = Math.floor(1   Math.random() * 9);
};


// Call this function on button CHECK click!
const check = () => {

  // Start a new game if needed
  if (isGuessed) start();

  // Get the user entered value
  const num_user = Math.abs(parseInt(EL_number.value, 10)); // Use parseInt with radix 10 and Math.abs to prevent negative numbers

  // Do nothing if invalid value entered:
  if (!num_user) return;

  // Update isGuessed state
  isGuessed = num_rand === num_user;

  // Handle answer:
  const text_answer = `
        You guessed: ${num_user}.
        The number is ${isGuessed ? "correct!" : num_user > num_rand ? "too high." : "too low."}
        ${isGuessed ? "Congratulations!" : "Try again"}
    `;

  // Create a LI element with the answer text
  const EL_li = ELNew("li", {
    textContent: text_answer
  });

  // Append your LI element!
  EL_answers.append(EL_li);

  // Clear the current value from input:
  EL_number.value = "";
};


// Assign listener to button:
EL_check.addEventListener("click", check);

// Start a new game!
start();
Enter a number from 1 to 10: <input id="number" type="text">
<button id="check" type="button">CHECK</button>
<ol id="answers"></ol>

Additional learning resources:

  • Related