2 errors in my javascript random number-guessing game - javascript

This is the first app I have ever written. I have seen a million random number-generating games here, javascript and otherwise, but none had the problems I'm having. I apologize for my ignorance, but when I know what I'm doing wrong, this will go a long way toward my understanding of javascript and coding in general. I'm just playing in the browser console as of now.
I've done this with a for loop, but I wanted to try another option and use a decrement counter. I've tried using the if/else stuff from the inner function inside the while loop. The code looks right to me.
const guessingGame = (tries) => {
const answer = Math.floor(Math.random() * 11)
let guess = null
let status = "playing"
function makeGuess() {
if (guess === answer) {
status = "won"
} else if (tries === 0) {
status = "lost"
} else {
tries--
if (tries === 1) {
console.log(tries + ' guess left')
} else {
console.log(tries + ' guesses left')
}
}
}
while (status === "playing") {
if (!guess) {
guess = prompt('Guess a number between 1 and 10')
makeGuess()
} else if (guess > answer) {
guess = prompt('Lower')
makeGuess()
} else if (guess < answer) {
guess = prompt('Higher')
makeGuess()
} else {
break
}
}
console.log("Game Over. You " + status + "! The answer was " + answer + ".")
}
This game should invoke/launch with one argument, the number of tries allowed. If I correctly guess the answer, the console log at the end should include status = "won". But when I win, it includes status = "playing".
When I guess wrong "tries" number of times, I should lose. But when I see "0 guesses left" in the console, the game gives one more guess, and I can take it, effectively making tries -1, I think. When I make one additional wrong guess, status correctly changes to "lost" and the final console message is correct.

You checked tries === 0 before tries--, that's why you get 0 guesses left. You should decrement before checking.
The guess is actually a string not a number, so guess === answer never true. The next iteration after you guessed correctly, it falls into else{break} with the status still playing. You either want Number(guess) === answer or just guess == answer.
By Math.floor(Math.random() * 11) you are actually generating 0-10. You want Math.floor(Math.random() * 10) + 1 for 1-10. Just remember Math.floor(Math.random() * n) gives you n possible outcomes, which happens to be an integer in the range [0,n). Then do whatever calculation you want to map it to your desire output value.
const guessingGame = (tries) => {
const answer = Math.floor(Math.random() * 10) + 1
let guess = null
let status = "playing"
function makeGuess() {
tries--;
if (guess === answer) {
status = "won"
} else if (tries === 0) {
status = "lost"
} else {
if (tries === 1) {
console.log(tries + ' guess left')
} else {
console.log(tries + ' guesses left')
}
}
}
while (status === "playing") {
if (!guess) {
guess = Number(prompt('Guess a number between 1 and 10'))
makeGuess()
} else if (guess > answer) {
guess = Number(prompt('Lower'))
makeGuess()
} else if (guess < answer) {
guess = Number(prompt('Higher'))
makeGuess()
} else {
break
}
}
console.log("Game Over. You " + status + "! The answer was " + answer + ".")
}
guessingGame(5);

The result of prompt is a string; thus, guess is a string. The result of Math.floor is a number, so answer is a number.
> and < are coercing operators: if one of the operands is a number, the other is converted into the number, as well. This means guess < answer and guess > answer work as you hope it does.
However, you've apparently heard people say "never use ==, always use ===" and taken it to heart. The reason for the saying is == is also a coercing operator, and as a consequence sometimes things that don't look equal end up being equal. However, here you actually needed to use the coercing ==, because 1 == '1' (even though 1 and '1' are different types), but the strict 1 === '1' ends up being false!
Thus, you first check if guess is strictly equal to answer. Since their types are different, it is impossible, so you move on. You check if guess is above the answer, then you check whether it is below the answer, both of those return false as well. The only remaining option is to break from the loop - and "winner" never gets printed.
Beside this, your biggest problem is actually logic. The placement of different tests and actions is somewhat questionable. For example, one would expect that testing whether guess is equal to the answer would be right next to the test to see if it is bigger or smaller. The test for tries would be most at home right at the while loop; but you have an infinite loop, and an independent test for tries. You enter the first guess with a unique prompt, but it is inside an infinite loop, despite the fact it can only ever happen once. You have a function called makeGuess, but the function does two or three different things, none of which is actually making a guess.
Rather than start working on code right away, then fixing problems as they pop up, try to imagine first what the flow would be. How would a human do it? Then write code.
Here's the basic idea for the same game:
answer = imagineAnswer()
guess = askForFirstGuess()
status = "lost"
while (--tries) {
if (guess > answer) {
guess = askForHigherGuess()
} else if (guess < answer) {
guess = askForLowerGuess()
} else {
status = "won"
break
}
}
reportGameEnd(status)

Related

Cannot find the fault in my JAVASCRIPT number guessing game

I created a small number guessing game in JAVASCRIPT but the program only runs correctly if I get the answer right on the first attempt, if I get it right on any other attempt then it just stops prompting me and the page loads infinitely till it reaches an error, even though I do not see any infinite loop situation in my code. Basically, It should stop loading once I guessed the number right , but again, it only does this if I get it correctly on the first try (btw I am using VS code Live Server so I am suspecting something might be off with it). Would really appreciate if someone can find any faults:
let maximum = parseInt(prompt("Enter a maximum number"));
const targetNum = Math.floor((Math.random() * maximum) + 1);
while (!maximum) {
maximum = parseInt(prompt("Enter a valid number"))
}
console.log(targetNum);
let guess = parseInt(prompt("Enter your first guess"));
let attempts = 1;
while (guess !== targetNum) {
console.log(new Date());
attempts++;
if (guess > targetNum) {
guess = prompt("TOO HIGH! Try again")
} else if (guess < targetNum) {
guess = prompt("TOO LOW! Try again")
}
}
console.log(`You got it! it took you ${attempts} attempts`);
You could also simplify your code by changing while (guess !== targetNum) { ... } to while (guess != targetNum) { ... }, as this comparison would do the type conversion implicitly for you. (Write less - do more ;-)).

Javascript if else conditionals not returning the desired output [duplicate]

This question already has answers here:
if statement always return true even for simple integer values
(3 answers)
Closed 2 years ago.
I've been teaching myself how to code in new languages and might be asking a couple of silly questions here for a while.
Trying to put this to work but, when the output pops out and the grade I've typed into is higher than 50, it was supposed to show the word "PASS". Instead, I'm still getting "FAIL" - the amount doesn't matter.
I am pretty sure it has to do with the conditionals, but I've been stuck on this for a long time now.
Here is my code:
var input = Number(prompt("Enter a grade between 0 and 100.")); //enter grade
if (input > 100 || input < 0) {
alert("Grade not valid. Enter a grade between 0 and 100."); //validate grade
} else {
if (input < 50); //result FAIL
{
result = "Fail";
alert("FAIL");
}
/*
if (input > 50); //result PASS - This part doesn't work
{
result = "Pass";
alert("PASS");
}
*/
total = total + input;
entrys = entrys + 1; //show inputed grades
document.write("<br>" + "Grade " + entrys + " = " + input + " = " + input / 100 + "%" + " " + result); // Every inputed result is considered "Fail"
}
The semicolon after the if (input < 50) turns the if statement into a one line if with an empty expression, followed by a code block that always runs. You can fix your issue by getting rid of the semicolon.
if (input < 50); //result FAIL
// ^ this is bad
As others have already pointed out, you need to remove the ; from the line if you want the rest of the statements to execute. The reason why is because, traditionally, in compiler languages the semicolon(;) is used to mark the end of the line. In javascript, they are also used for that purpose, but they are optional in javascript.
So if your code spans multiple lines, avoid using it unnecessarily. Definitely don't use it after a for or while loop(unless for certain use cases where you want that), or after an if-else statement, because execution will get stopped at that line and the next line will be executed like it is an unrelated code and not part of the loop/statement. Hope this makes sense

How can I get add and subtract functions in javascript calculator to work correctly?

I am making a basic calculator in javascript. My addition and multiplication buttons work well. However, my subtraction and division functions are not working.
When I click subtract, for some reason that I can't figure out (I've been scratching my head forever), it automatically converts the number in the output to a negative number.
And for division, I can't seem to get the logic down to divide the first number I enter by the second number I enter.
Here is my basic calculate function:
function calculate() {
if (operator == 'add') {
runningSum += windowNum;
} else if (operator == 'subtract') {
runningSum -= windowNum; // automatically converts windowNum to negative, unclear why
} else if (operator == 'multiply') {
if (runningSum == 0) {
runningSum = 1;
}
runningSum *= windowNum;
} else if (operator == 'divide') {
// ever mutation tried comes up with wrong result
}
outputWindow.textContent = Number((runningSum).toFixed(5));
operatorClicked = true;
numClicked = false;
document.querySelector('#btnAdd').classList.remove('operatorClicked');
console.log('windowNum: ' + windowNum);
console.log('runningSum: ' + runningSum);
}
Because my project is rather big, I've included a link to it in codepen here: https://codepen.io/CDLWebDev/pen/mdJgbeG
I checked your codepen and changed a few things. Mainly, you were performing calculations whenever a click to the operation signs was made, which is not really something you want to do, since you can't perform operations when you don't know what number will come next. On calculators, calculations are actually performed when you press the "equals" sign.
What really has to happen and what I've done in the code below is keep the number you just pressed as your runningSum and choose the operation, then when you press equal you have all the info you need.
https://codepen.io/VPR/pen/poJBzXP
function clickOperatorBtn() {
if (numClicked) {
if (target == document.querySelector("#btnDivide")) {
operator = "divide";
runningSum = windowNum;
clearWindow();
} else if (target == document.querySelector("#btnMultiply")) {
operator = "multiply";
runningSum = windowNum;
clearWindow();
} else if ...
I assume this is a learning exercise, so keep it up, but I think the logic behind your code could improve, when you're done try googling some tutorials on calculators, you'll find many which walk you through the steps performed and the logic behind it.
I tried your code and the function calculate is ran every time you change the operator. That means that when, initially, click on the '-' sign you will trigger that function. Bear with me:
else if (operator == 'subtract') {
// windowNum == 3 - for example
// runningSum == 0
runningSum -= windowNum;
// result will be 0 - 3 == -3
This means that if you do the same with say, 7. You'll be doing -3 - 7 == -10
About the division:
This is also happening, so when you do something like clicking 8 and then division, what you're doing is 0 / 8 (which apparently results in 1).
Hope this helps!

Guessing game, 1 to 100 using do/while loop and if/ese if conditional statement

I am trying to make a guessing game with simple java script. the professor gave us a guide, but i am still a bit confused. Based on the guide, we are to use a do/while loop, and within that loop, use the if/else if conditional statement, here is what i have so far.
i've tried changing it so many times, and all i end up with is a never ending loop, even after the number is guessed, it doesnt stop
<body>
<p>
I'm thinking of a number between 1 and 100, try to guess it! </br>
<script>
var number = Math.floor(Math.random() * 100 + 1)
//guess variable to store the guessed number by user
var guess
//output to store output to the user
var output
//if the user guessed the number or not, initialize it to false
var guessed = false
//do/while loop, while condition is based on if the user NOT guessing the number (e.g. guessed == false)
do {
guess = prompt ("Think of a number between 1 and 100, what is your number?");
document.write ("You guessed the number " + guess + "<br/>");
if (guess > number) {
document.write ("You guessed too high, think smaller" + "<br/>");
guessed = false
}
else if (guess < number){
document.write ("You guessed too low, think bigger" + "<br/");
guessed = false
}
else {
alert("You guessed the right number!")
guessed = true}
}
while (guessed = false)
</script>
</p>
</body>
You're missing a ton of semi-colons which should be added though your code will still run without them. And like everyone else said you are assigning guessed to false at the end of your do while loop, therefore it will never break out. To check a condition you should use 3 equal signs (this is strict comparison). More on that here. It is debatable if document.write should be used. Reason for that can be found here. Also, when testing your code it worked intermittently, so I added a div with the id of hints. Then I grabbed that element with var elHints = document.getElementById('#hints'); Then to add content to the element hints simply do elHints.textContent += .... The plus equals (+=) adds content to the element without overwriting existing content. In css I added a style to #hints: white-space: pre-line; this allows line breaks (\n) to the div when adding content using textContent. More on that here.
Here is the full javascript code:
var number = Math.floor(Math.random() * 100 + 1);
//guess variable to store the guessed number by user
var guess;
//output to store output to the user
var output;
//if the user guessed the number or not, initialize it to false
var guessed = false;
var elHints = document.getElementById('hints');
//do/while loop, while condition is based on if the user NOT guessing the number (e.g. guessed == false)
do {
guess = prompt("Think of a number between 1 and 100, what is your number?");
elHints.textContent += "You guessed the number " + guess + '\n';
if (guess > number) {
elHints.textContent += "You guessed too high, think smaller" + '\n';
guessed = false;
} else if (guess < number) {
elHints.textContent += "You guessed too low, think bigger" + '\n';
guessed = false;
} else {
alert("You guessed the right number!")
guessed = true;
}
}
while (guessed === false);
And here's the jsfiddle.
I believe that you are missing a semi-colon here :
while(guessed == false);
This is just an requirement specific to the do-while loop and does not occur in the syntax for other loops.
In your condition at while(guessed = false) you use one equal-signe (=), witch is forever true. you must write (guessed == false) or (guessed === false). for trying i would do ist so:
I'm thinking of a number between 1 and 100, try to guess it!
<script type="text/javascript">
var number = Math.floor(Math.random() * 100 + 1);
// Just for Test
document.getElementById('test').innerHTML += '<br />' + number;
//guess variable to store the guessed number by user
var guess;
//output to store output to the user
var output;
//if the user guessed the number or not, initialize it to false
var guessed = false;
//do/while loop, while condition is based on if the user NOT guessing the number (e.g. guessed == false)
do {
guess = prompt("Think of a number between 1 and 100, what is your number?");
document.getElementById('test').innerHTML += '<br />' + "You guessed the number " + guess;
if (guess > number) {
document.getElementById('test').innerHTML += '<br />' + "You guessed too high, think smaller";
guessed = false;
}
else if (guess < number) {
document.getElementById('test').innerHTML += '<br />' + "You guessed too low, think bigger";
guessed = false;
}
else {
alert("You guessed the right number!")
guessed = true;
}
}
while (guessed == false)
</script>
Your code has some issues.
First of all you need to change while (guessed = false) into while (guessed === false) because it should be a comparision, hence you have to use a comparator.
Secondly, you are using document.write(). This will not work, because the HTML won't change until the user breaks out of the loop. It would be a good idea to use alert() instead. Here is a working example:
var number = Math.floor(Math.random() * 100 + 1)
//guess variable to store the guessed number by user
var guess
//output to store output to the user
var output
//if the user guessed the number or not, initialize it to false
var guessed = false
//do/while loop, while condition is based on if the user NOT guessing the number (e.g. guessed == false)
do {
guess = prompt("Think of a number between 1 and 100, what is your number?");
if (guess > number) {
alert("You guessed too high, think smaller");
guessed = false
} else if (guess < number) {
alert("You guessed too low, think bigger");
guessed = false
} else {
alert("You guessed the right number!")
guessed = true
}
}
while (guessed === false)

Use only the first number generated with Math.random

I'm a student creating a 3-guess game with JavaScript. My game doesn't work properly, I believe Math.random is generating a new number at every stage of the game. I would be most grateful if somebody helps me define a single number for the variable randomNumber.
Here's the JavaScript:
function game()
{
var randomNumber = Math.floor(Math.random()*11);
var userGuess = prompt ("Guess what number I'm thinking of? (It's between 0 & 10)");
if (userGuess === randomNumber)
{
alert ("Good Guess, you must be psychic!");
}
else
{
var userGuess2 = prompt ("Dohhh! You got it wrong. You have 2 more chances.");
}
if (userGuess2 === randomNumber)
{
alert ("Good Guess, you must be psychic!");
}
else
{
var userGuess3 = prompt ("Dohhh! You got it wrong. You have 1 more chance.");
}
if (userGuess3 === randomNumber)
{
alert ("Good Guess, you must be psychic!");
}
else
{
alert ("Bad luck. The number was: " + randomNumber);
}
}
prompt returns a string. You are using the strict equality operator, ===, to compare strings with numbers. They will never be equal.
Use the abstract equality operator, ==, or convert the strings to numbers before comparing with the strict equality operator.
Also, your function should probably return after a correct guess, rather than prompting for more guesses.
Here's a suggestion for a cleaned-up version of your code:
function playGame(guesses)
{
// By default, give the player 3 guesses.
guesses = guesses || 3;
var randomNumber = Math.floor(Math.random()*11);
var userGuess = prompt("Guess what number I'm thinking of? (It's between 0 & 10)");
// Repeat the following logic whenever the user guesses incorrectly.
while (userGuess !== randomNumber.toString())
{
--guesses;
if (guesses === 0)
{
alert("Bad luck. The number was: " + randomNumber);
return false;
}
userGuess = prompt("Dohhh! You got it wrong. You have " + guesses + " more chance(s).");
}
alert("Good Guess, you must be psychic!");
return true;
}
Notice that it's now more flexible (you can give the user a configurable number of guesses) while also reducing code duplication: instead of repeating the same block of logic (with small differences), there is really just one bit of logic that can be repeated as many times as you like.

Categories

Resources