I am currently trying to create a Guess the Number game using Javascript. I have set the code to display a different output depending on the number entered.
However, I would like to add range to this. For example, if the guess is within 10, above or below, the output should read "Almost". However, if the user is out of this range, it should read something different.
What operation should I use? Currently I'm just using:
if(userGuess < randomNumber) {
lowOrHi.textContent = 'Your guess is out by 10 – please guess again!';
But this doesn't reflect the range as I'd like it to.
you can use absolute value to get the distance between the userGuess and the randomNumber
you can get it with Math.abs
const randomNumber = 4 // chosen by fair dice roll.
// guaranteed to be random.
let userGuesses = [42, -15, 2]
for (let guess of userGuesses) {
if (Math.abs(guess - randomNumber) <= 5) {
// the guess is in the range [random - 5; random + 5]
console.log(`guess ${guess} is very close`)
} else if (Math.abs(guess - randomNumber) <= 20) {
// the guess is in the range [random - 20; random + 20]
console.log(`guess ${guess} is not that far`)
} else {
console.log(`guess ${guess} is pretty far`)
}
}
as you can see it works if you're under the wanted number or over it
You should check if the difference between guessed number and random number is within range of 10.
var difference = Math.abs(userGuess - randomNumber);
if(difference > 10) {
lowOrHi.textContent = 'Your guess is out by 10 – please guess again!';
} else {
lowOrHi.textContent = 'Your guess is almost correct!';
}
Try the following
if((userGuess-randomNumber)<-10||(userGuess-randomNumber)>10) {
console.log('Your guess is out by 10 – please guess again!');}
else {
console.log("Almost");
}
Related
Im in the process of learning javascript and I cant seem to understand why the break statement isnt functioning :( Can someone please tell me what I've done wrong?
let maximum = parseInt(prompt("Enter the maximum number"));
while(!maximum){
maximum = parseInt(prompt("Enter a valid number"));
}
const randomNum = Math.floor(Math.random() * maximum) + 1;
console.log(randomNum);
let guess = parseInt(prompt(`Enter your guess for the generated number between 1 and the maximum number of ${maximum}.`));
let attempts = 1;
while (parseInt(guess) !== randomNum){
if (guess === 'q') break;
attempts++;
if(guess > randomNum){
guess = prompt("Too high, guess again.");
} else{
guess = prompt("Too low, guess again.");
}
}
if (guess === 'q'){
console.log("Quitting.")
} else {
console.log(`It took you ${attempts} amounts of guesses!`)
}
if (guess === 'q')
You are parsing the value to an integer and are comparing it to a string. Which is always false
So when you type 'q' in your prompt and try parseInt on it you will get NaN which stands for not a number. And NaN is not equal with q obviously
EDIT:
as #axic correctly pointed out the condition from above cannot be fulfilled if q was typed before the iteration begins. But that brings another problem:
On the third iteration you will get another prompt saying "Too low, guess again." even if you guessed the right number, because guess is string and compared to a number which will return false in all cases.
You are parsing the value to an integer and are comparing it to a string.
let maximum = parseInt(prompt("Enter the maximum number"));
while (!maximum) {
maximum = parseInt(prompt("Enter a valid number"));
}
const randomNum = Math.floor(Math.random() * maximum) + 1;
console.log(randomNum);
let guess = prompt(`Enter your guess for the generated number between 1 and the maximum number of ${maximum}.`);
let attempts = 1;
while (parseInt(guess) !== randomNum) {
if (guess === 'q') break;
attempts++;
if (guess > randomNum) {
guess = prompt("Too high, guess again.");
} else {
guess = prompt("Too low, guess again.");
}
}
if (guess === 'q') {
console.log("Quitting.")
} else {
console.log(`It took you ${attempts} amounts of guesses!`)
}
The break statement works totally fine, the issue is in a different location of your logic. You are parsing the integer of guess when displaying the first prompt to enter a guess for the number but when entering anything that isn't a number the value will simply be NaN.
Line 7 is:
let guess = parseInt(prompt(`Enter your guess for the generated number between 1 and the maximum number of ${maximum}.`));
but should be:
let guess = prompt(`Enter your guess for the generated number between 1 and the maximum number of ${maximum}.`);
I'm not entirely sure if this is what you want to achieve but based on the little information you gave I assumed that this would be what you're trying to get.
I'm trying to make a simple rolling the dice mechanic with probabilities, if pass the level increase, if fail it decrease and if destroyed usually it resets to a certain level, but I'm having a hard time getting the right results, I am not sure if the outcome is supposed to be like this and just my intuition is wrong or something is actually messing it up.
Basically I am making a while loop that while below certain level it will roll the dice and given the results it will do something accordingly to the rates I input (40% for pass, 59.4% for fail and 0.6% to destroy). But when I do a test with 1000 tries, it always return me an average of destroyed way higher than 0.6%. I don't know if my test function is wrong, if the way I'm testing is wrong, if something on my loop is messing up the probabilities outcome.
function checkPass(successRate, failRate, destroyRate) {
let number = Math.random();
if (number < successRate) {
return 1;
} else if (number < failRate) {
return 0;
} else {
return 2;
}
}
function starforceSim(itemLevel) {
let newObj = {"level": 10, "totalMeso": 0, "destroyed": 0};
while (newObj.level < 11) {
if (newObj.level == 10) {
let passOutcome = checkPass(0.4, 0.994, 1)
if (passOutcome == 1) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.level = newObj.level + 1;
} else if (passOutcome == 0) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
//newObj.level = newObj.level - 1;
} else {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.destroyed = newObj.destroyed + 1
}
}
}
return newObj;
}
let counter = 0;
for (i=0; i<1000; i++) {
let n = starforceSim(140);
if (n.destroyed > 0) {
counter++
}
}
console.log(counter);
I disabled the decrease level when it fails just to focus on the destroy rates.
Is there a better way to code probabilities or to test them? Is there something wrong with my code?
Math.random is only pseudo-random1
1Source
This means you may not get a perfectly uniform distribution. In my own fiddling, it seems like randomness might get worse if you generate many values in rapid succession [citation needed].
If you want a better source of randomness, check out Crypto.getRandomValues.
I don't see anything wrong with your code. I think your expectations are just off. To verify that this is caused by lame randomness, take David Tansey's advice and study just the randomness output.
You may also notice different randomness quality in different browsers (or, different Javascript engines).
I am very noob at coding and I keep having the same error over and over. The loop is supposed to be run until correctGuesses reaches the value of 4, and then break the cycle and print 'terminal hacked'. I am running this in a private platform and I keep getting the same error "Your loop needs to stop when all 4 characters have been guessed". Does someone know why? Thank you so much in advance!
var correctGuesses = 0;
var randNum;
while (correctGuesses!==4) {
randNum=Math.floor(Math.random()*3);
if(randNum===1) {
correctGuesses=correctGuesses+1;
console.log("Found "+correctGuesses+ " characters");
} else if (randNum===2) {
correctGuesses=0;
console.log('Starting over');
} else if (randNum===3) {
correctGuesses=0;
}
} console.log('terminal hacked');
So I finally found the error. I had to put a if (correctGuesses===4){break;} right after the correctGuesses++ reached 4, because the goal was the cycle to be broken when correctGuesses===4. It was a school exercise and it clearly said that the cycle should end afater 4 correct guesses but I did not fully understand that before writing the code. Thank you all.
Given how the assignment is worded and the fact that random numbers are, well, random, my guess is that the platform you're writing this code for has overridden Math.random to supply a specific sequence of numbers and then they check the output you produce matches.
This means means that you simply need to follow the specifications and the outcome is not based on luck. There are two problems here
Generating an number between 1 and 3
You currently only generate a number between 0 and 2, since you're rounding down.
var randNum = Math.floor(Math.random() * 3);
console.log(randNum);
To get output between 1 and 3, the traditional way is to just add 1 to the output. Or more generally, you add the minimum to the output and generate between 0 and max - min:
function randomBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
console.log("random between 2-5:", randomBetween(0, 2));
console.log("random between 1-3:", randomBetween(1, 3));
Keep correctGuesses the same value when randNum is 3
Cight now you're resetting correctGuesses to 0 when randNum === 3. So, if you fix the problem with being able to generate a 3, then this will be incorrect as per the requirement. The assignment doesn't have any other requirement for what happens when that number is generated, so since you have to keep the number unchanged, it's very simple - you don't do anything. Simply remove the entire if and your code would work as the requirement asks.
Conclusion
You code should look like this after you've made the changes:
var correctGuesses = 0;
var randNum;
while (correctGuesses !== 4) {
randNum = Math.floor(Math.random() * 3) + 1; //add 1 to generate numbers 1-3
if (randNum === 1) {
correctGuesses = correctGuesses + 1;
console.log("Found " + correctGuesses + " characters");
} else if (randNum === 2) {
correctGuesses = 0;
console.log('Starting over');
}
//don't do anything for randNum === 3
}
console.log('terminal hacked');
I'm working on a game where you have to guess a number, and if it matches the number that is randomly generated then you win. I've got most of the game completed apart from the part where you have to check if the guessed number is within the range of 30 or 10 of the randomly generated number. To give an example, if the random number is 50 and the guessed number is 60 then this is within a range of 10 of the random number and this should therefore cause the screen to turn to the colour red, because they are 'hot' but iv'e been having trouble working out the calculation for it. Any ideas?
This is the code I'm using to calculate if the number is correct or not.
function guessFunction() {
counter++;
document.getElementById("guessNumber").innerHTML = counter;
if (!checkEqual(document.getElementById("randomNumber"), random)) {
document.body.style.background = "orange";
} else {
document.body.style.background = "green";
document.getElementById("another").style.visibility = "hidden";
}
if (!checkHigher(document.getElementById("randomNumber"), random)) {
return true;
} else {
return false;
}
if (!checkGreater(document.getElementById("randomNumber"),
random)) {
return true;
} else {
return false;
}
}
function checkHigher(element1, element2) {
if (element1.value > element2) {
document.getElementById("highOrLow").innerHTML = "Too High";
} else if (element1.value == element2) {
document.getElementById("highOrLow").innerHTML = "got it";
} else {
document.getElementById("highOrLow").innerHTML = "Too low";
}
}
Basically subtract the two and get the absolute value to find the difference. On another note I see you have multiple functions for testing different cases. You could write one function to handle all cases and only pass the generated number and guess in instead of the elements themselves. Then it is more stand alone. Something like this:
function checkNumber(number, guess) {
// Gets difference by subtracting and finding absolute value
var diff = Math.abs(number - guess);
// Assumes guess is too low and checks if its higher
var highlow = " and too low";
if (guess > number) {
highlow = " and too high";
}
// Checks range for hot and cold while adding in high or lowness, else its exact so ignores adding high or lowness
// Off by more than 20 cold, off by under 20 hot.
if (diff >= 21) {
document.getElementById("highOrLow").innerHTML = "Cold" + highlow;
} else if (diff >= 1 && diff <= 20) {
document.getElementById("highOrLow").innerHTML = "Hot" + highlow;
} else {
document.getElementById("highOrLow").innerHTML = "Got it";
}
}
Fiddle: https://jsfiddle.net/bohxapdw/2/
I'm pretty awful at Javascript as I've just started learning.
I'm doing a Luhn check for a 16-digit credit card.
It's driving me nuts and I'd just appreciate if someone looked over it and could give me some help.
<script>
var creditNum;
var valid = new Boolean(true);
creditNum = prompt("Enter your credit card number: ");
if((creditNum==null)||(creditNum=="")){
valid = false;
alert("Invalid Number!\nThere was no input.");
}else if(creditNum.length!=16){
valid = false;
alert("Invalid Number!\nThe number is the wrong length.");
}
//Luhn check
var c;
var digitOne;
var digitTwo;
var numSum;
for(i=0;i<16;i+2){
c = creditNum.slice(i,i+1);
if(c.length==2){
digitOne = c.slice(0,1);
digitTwo = c.slice(1,2);
numSum = numSum + (digitOne + digitTwo);
}else{
numSum = numSum + c;
}
}
if((numSum%10)!=0){
alert("Invalid Number!");
}else{
alert("Credit Card Accepted!");
}
</script>
The immediate problem in your code is your for loop. i+2 is not a proper third term. From the context, you're looking for i = i + 2, which you can write in shorthand as i += 2.
It seems your algorithm is "take the 16 digits, turn them into 8 pairs, add them together, and see if the sum is divisible by 10". If that's the case, you can massively simplify your loop - you never need to look at the tens' place, just the units' place.
Your loop could look like this and do the same thing:
for (i = 1; i < 16; i +=2) {
numSum += +creditNum[i];
}
Also, note that as long as you're dealing with a string, you don't need to slice anything at all - just use array notation to get each character.
I added a + in front of creditNum. One of the issues with javascript is that it will treat a string as a string, so if you have string "1" and string "3" and add them, you'll concatenate and get "13" instead of 4. The plus sign forces the string to be a number, so you'll get the right result.
The third term of the loop is the only blatant bug I see. I don't actually know the Luhn algorithm, so inferred the rest from the context of your code.
EDIT
Well, it would have helped if you had posted what the Luhn algorithm is. Chances are, if you can at least articulate it, you can help us help you code it.
Here's what you want.
// Luhn check
function luhnCheck(sixteenDigitString) {
var numSum = 0;
var value;
for (var i = 0; i < 16; ++i) {
if (i % 2 == 0) {
value = 2 * sixteenDigitString[i];
if (value >= 10) {
value = (Math.floor(value / 10) + value % 10);
}
} else {
value = +sixteenDigitString[i];
}
numSum += value;
}
return (numSum % 10 == 0);
}
alert(luhnCheck("4111111111111111"));
What this does is go through all the numbers, keeping the even indices as they are, but doubling the odd ones. If the doubling is more than nine, the values of the two digits are added together, as per the algorithm stated in wikipedia.
FIDDLE
Note: the number I tested with isn't my credit card number, but it's a well known number you can use that's known to pass a properly coded Luhn verification.
My below solution will work on AmEx also. I submitted it for a code test a while ago. Hope it helps :)
function validateCard(num){
var oddSum = 0;
var evenSum = 0;
var numToString = num.toString().split("");
for(var i = 0; i < numToString.length; i++){
if(i % 2 === 0){
if(numToString[i] * 2 >= 10){
evenSum += ((numToString[i] * 2) - 9 );
} else {
evenSum += numToString[i] * 2;
}
} else {
oddSum += parseInt(numToString[i]);
}
}
return (oddSum + evenSum) % 10 === 0;
}
console.log(validateCard(41111111111111111));
Enjoy - Mitch from https://spangle.com.au
#Spangle, when you're using even and odd here, you're already considering that index 0 is even? So you're doubling the digits at index 0, 2 and so on and not the second position, fourth and so on.. Is that intentional? It's returning inconsistent validations for some cards here compared with another algorithm I'm using. Try for example AmEx's 378282246310005.