How to make my bot respond to someone after an initial response? - javascript

I'm making a bot command so when you type ,num-guess the bot says '[username] guess a number between 1 and 10, you have 3 guesses.'
which works but it also says '[username] you have not correctly guessed it, you have 3 guesses left' 3 times right after. Instead, I want it so when you guess it wrong it says '[username] you have not correctly guessed it, you have 2 guesses left,' then 1 guesses left, then 1 more wrong guesses it would say 'Sorry [username] you did not guesses they number', but it does not work
Here is my code:
module.exports = {
name: 'num-guess',
description: 'User has to guess a number between 1 - 10',
async execute(Client, message, args, Discord) {
NumberToChoose = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const Number = NumberToChoose[Math.floor(Math.random() * NumberToChoose.length)];
message.channel.send(`${message.author.username} guess a number from 1 - 10`);
var MaxGuess = 3
var CorrectAnswer = Number
var GuessesLeft = MaxGuess
var Guess = message.author.message
for (i=0; i<MaxGuess; i++){
if(CorrectAnswer == Guess){
message.channel.send(`${message.author.username} you have guessed the number correctly`);
break;
}
else {
var GuessesLeft = GuessesLeft--
message.channel.send(`${message.author.username} you have not correctly guessed it, you have ${GuessesLeft} left`)
}
}
}
}
Here is what the bot says:
[username] guess a number from 1 - 10
[username] you have not correctly guessed it, you have 3 left
[username] you have not correctly guessed it, you have 3 left
[username] you have not correctly guessed it, you have 3 left
What I want it to say:
[username] guess a number from 1 -10
[user]: 1
(if correct number) [username] you have guessed the number correctly
(if not the correct number) [username] you have not correctly guessed the number, you have [number of more tries] left
(repeat until lose or win)

The postfix decrement operator (n--) has a bit of a confusing feature that makes it more confusing than just using the subtraction assignment operator (n -= x). When using this operator, it will increment the variable, but return the original value. Here's an example:
let number = 1;
const increment = number--;
// number was decremented correctly and is now zero
console.log(`Number: ${number}`);
// but increment takes the value of the original number
console.log(`Increment: ${increment}`);
Since you're assigning n-- to a variable and using that, the number isn't actually going to change, since it's using the original value each time. There are many ways to prevent this:
The easiest way by far would just be not to reassign GuessesLeft to another variable by the same name. This operator will edit values in place, so there's no need to do anything but use the operator.
// original:
// var GuessesLeft = GuessesLeft--
GuessesLeft--
Use the prefix decrement operator (--n). It does the same thing, but this time actually returns the modified number.
Use the subtraction assignment operator. GuessesLeft -= 1. It might not be as short and sweet, but it's much easier to understand, and none of the confusing "post"/"pre" curveballs come into effect.
Also, I'm pretty sure that you'll never be able to guess the number correctly. message.author.message is not a thing, so Guess will be undefined, and it doesn't look like it's actually prompting you for further answers.

Related

Having problems with a while counter

well this is the problem: """For this task you'll need to gain access to a target's account, which is password protected. We know the password is only four characters long, but we have no idea of what it looks like.
With today's computing power, brute-forcing weak passwords is not that hard and, as in any brute-force technique, it only requires time and luck.
Instructions
You know that your target's password is 4 characters long, so you'll just have to brute force 1 character at a time. We already declared the variable correctGuesses which you should use to keep track of how many characters you have guessed so far.
Bear in mind that your program does not need to guess the password, that is not your goal!
You need to create a loop that only stops when all 4 characters have been guessed. On each loop iteration you need to calculate a random number between 1 and 3, which will correspond to each of the bellow scenarios:
You guessed one character correctly, which increases correctGuesses by 1 and prints the message 'Found X characters' (where X is replaced with the current number of correct guesses).
You guessed incorrectly and your target's terminal has detected too many attempts, which resets correctGuesses to 0 and prints the message 'Starting over' to the console.
You guessed incorrectly, but have not been detected yet, correctGuesses is kept with the same value.
Once the password is cracked (that is, correctGuesses has a value of 4) you should print the message 'Terminal hacked!'.
Make sure all the messages in your code are in the correct format in order to advance!""""
And this is my code :
var correctGuesses = 0;
var randomNumber = Math.ceil(Math.random()*3);
console.log(randomNumber);
while (correctGuesses < 4){
console.log(correctGuesses);
if (correctGuesses === 4){
console.log('Terminal hacked!');
break;
}
if (randomNumber === 1){
correctGuesses = correctGuesses +1;
console.log('Found' + ' '+ correctGuesses+'characters');
break;
}
if (randomNumber === 2){
correctGuesses = 0;
console.log(correctGuesses);
break;
}
if (randomNumber === 3){
console.log(correctGuesses);
break;
}
}
so i am having a hard time to make my correctGuesses var to add 1 each time randomNumber var gives us 1. already tried out to the change the order of the comands lines, i am making instead of Math.random method put 1 and simply dont add that plus 1, what i am doing wrong if someone could help me i would be very glad

Get every possible combination of numbers (fastest possible method)

I am trying to get every single combination of elements into an array. Now I can use the method below, and remove the duplicates, but this way is far to slow for my use.
The code below would find every possible combination for 2 digits below 4. Now in the code I actually want to use this for, the least possible code would be 6 for loops (within each other) with the amount being 18 (rememeber this is the minimum).
The code below would execute amount^[amount of for loops], or amount^2 which in this case is 16. That means that in the code I want to use this for, it executes 18^6 times, or 34 million times. And this is the minimum, which would get much higher.
After trying to run my code (with 6 foor loops in which amount = 18), it crashed my browser... My question is: Is there any faster and more efficient (not elegant. I don't care how elegant it is) in which my browser won't crash?
Note: This question is not a duplicate question. All the other questions simply ask for a way to do this, however I already have a way. I am just trying to make it more efficient and faster so that it actually works correctly.
let combinations = [];
let amount = 4;
for (let a = 0; a < amount; a++) {
for (let b = 0; b < amount; b++) {
combinations.push(`${a}${b}`);
}
}
console.log(combinations);
Below is a snippet providing a possible example for how my code would work.
let possibilities = [];
let amount = 6; //Amount is set by me, so don't worry about it being incorrect
for (let a = 0; a < amount; a++) {
for (let b = 0; b < amount; b++) {
possibilities.push(a + b);
}
}
possibilities = [...new Set(possibilities)]; //Removes duplicates
possibilities.sort((a, b) => b - a); //Sorts in descending order
possibilities = possibilities.slice(0, 3); //Gets top 3 values
console.log(possibilities);
Ok, as discussed in the comments, if you need top 3 values for a particular amount, you could just do something simple like below:
let amount = 6;
let highest = amount - 1,second_highest = amount - 2,third_highest = amount - 3;
let possibilities = [
highest + highest,
highest + second_highest,
highest + third_highest
];
console.log(possibilities);
I don't know the any better solution for this, but yes there are some conditions you need to check first.
If(amount <= 0) return 'Invalid amount, Please enter a valid amount"
So if somebody enters a negative or zero value your loop will goes into infinite loop, and make the situation more worst.
if(amount === 1) return '1 possible combination'
As amount less than 1 is 0 only and combinations for 0 is 1 only, you need not to parse whole loop for 6 digits or n digits for 0 so it will get solve in complexity of 1 instead of N(no. of digits).
And for amount greater then 1 you can create manual loops, like here you created 2 loops for 2 digits, you create 6 loops for 6 digits, better create dynamic logic for this to create number of loops automatically.
You need to consider 1111, 1112 this type of combinations as well right?
Or if only 1234, 2134, 2314 this kind of scenarios are required? This can be done in very less complexity.
For duplication you can store combinations as a key value pair. and then Object.Keys will be your combinations.

Tracking Number Guessing Attempts using JavaScript

I'm trying to build a simple number guessing game numberGuess() that tracks the # of attempts a player takes, but does not track an attempt if the player guesses a number that has already been guessed.
The only bug that keeps happening is if the player guesses the 1st number he guesses more than once - the game then logs that attempt when it shouldn't. However, if the player guesses any other number, but the first one more than once, it works perfectly.
For example, if player guesses in this order: 2, 5, 2, 3, the total attempts SHOULD show 3, but it shows 4.
However, if player guesses in this order 2, 5, 5, 3, the total attempts correctly shows 3.
I have hours and hours tinkering with this code and trying to figure this out before asking here, but have hit a wall. It seems to be a simple fix that I cannot figure out. Please let me know if you have spotted the error to fix this small bug!
function numberGuess () {
var number = Math.floor(Math.random() * 100 + 1); // Generates a random number between 0 and 100
var totalGuesses = []; // Array to stores all the guesses
var guess = Number(prompt("Welcome to number guess! Guess a number between 1 and 100")); // Prompts guessor to guess first number
while (guess != number) { //loop runs while user has not guessed the number
if (!guess) { // User cancels prompts
return;
}
else if (totalGuesses.indexOf(guess) >= 0) { // Checks to see if guess has already been guessed
guess = prompt ("You already guessed that number before. Give me another guess.");
}
else {
totalGuesses.push(guess);
if (guess > number) {
guess = prompt ("Your number is too high. Try Again. Don't give up!");
}
else {
guess = prompt ("Your number is too low. Try Again. I know you can do it!");
}
}
}
// Guess is correct!
alert("Congratulations! You guessed the number! It took you " + (totalGuesses.length +1) + " attempts!");
};
numberGuess();
The problem is with the following branch of your if statement:
else if (totalGuesses.indexOf(guess) >= 0) { // Checks to see if guess has already been guessed
guess = prompt ("You already guessed that number before. Give me another guess.");
}
In this code, you're not adding the guess to the totalGuesses array because it has already been guessed. As a result, the number of items in the totalGuesses array remains the same even though the number of guesses has increased by one.
A hacky solution would be to add the guess to the totalGuesses array anyway. But a better solution would be to use the totalGuesses as a set (unique values only) and make use of a counter variable which starts at 0 to track the number of guesses a user has made.
Furthermore, although you're correct in assuming that indexes in an array begin at 0, the length property of the array returns the number of items in the array, which, even if the index starts at 0, will always return the correct number of items. Therefore you don't need to add 1 to the result.
alert("Congratulations! You guessed the number! It took you " + totalGuesses.length + " attempts!");
Something that I've also noticed is that if the user enters something other than a number on his/her first guess, the code will correctly convert it to a number, however if the user then enters something that isn't a number after his/her first guess, it will remain as a string.

Check if a word is within various sub-intervals of an array

I have an array of words (25 of them, 0-24) and I want to do tests in a for loop that checks whether the randomly chosen word is within the interval 0-4, 5-9, 10-14 etc..
How do I do this?
else if (words[i > 4 && <= 9]){}
I tried that line in a for loop, but it gives me a syntax error.
Uncaught SyntaxError: Unexpected token <=
You're missing a left comparison in your condition. Use this as a condition:
i > 4 && i <= 9
However, note that you're not doing anything useful with the condition. Your result will be akin to words[true] or words[false].
Update
You've now elaborated a little more. If I understand you correctly, you want to pick a random word from your array, and then work out which interval of 5 it resides at within the array.
In the below example, the interval is indexed; so 0 = 0-4, 1 = 5-9, 2 = 10-14 and so on...
var words = [ "Synergetic", "unsteeped", "goldcup", "coronach", "swamper", "rehearse", "rusty", "reannotation", "dunne", "unblenched", "classification", "interpolation", "toper", "grisliest.", "Rechart", "imbower", "reilluminating", "glucagon", "interassuring", "parallelepipedon", "doyenne", "neenah", "tetragram" ];
function pickARandomWordAndCheckTheInterval(){
var randomIndex = Math.floor(Math.random() * words.length);
var word = words[randomIndex]
var interval = Math.floor(randomIndex / 5);
console.log('The random word is:' + word);
console.log('The interval is:' + interval );
}
pickARandomWordAndCheckTheInterval();
To explain it really really simple way you just forgotten to tell the language what needs to be less than or equal 9.
You assumed it processes logic condition like humans do (we would assume that after && operator you're still thinking about i, but that's not what JS interpreter would do).
What comes after && needs to be an expression that can be evaluated. <= 9 doesn't evaluate to value (it is not treated as valid expression because <= is kind of binary operator which requires two operands, one before and one after).
For JS interpreter it just means "less than or equal to 9". But what is "less than or equal to 9"? You need to tell it "i is less than or equal to 9".
i > 4 && i <= 9 is the correct way to write that.

How to compare a number string and it's reverse to find the next highest palindrome?

I am trying to build a function that takes a price with 2 decimal points and finds the next highest palindrome. I know there are several other ways to approach this, but I am curious why my method is not working. I am new to JS so this might be a simple one. Any advice would be great.
I broke it into smaller chunks with explanations of what I want it to do below:
var ask = prompt("Enter a price");
var reverseIt = function (x) {
x = (parseFloat(x) * 100).toString();
for (var i = (x.length - 1); i >= 0; i--) {
x.substr(i, 1);
}
return
};
The reverseIt function takes an argument removes the decimal (* 100) and reverses the number.
var removeDec = function (j) {
return (parseFloat(j) * 100).toString();
}
The removeDec function takes an argument, removes the decimal point (* 100), and converts it back to a string. Is this redundant for comparing two "number" strings? Should I use the Number() and String() functions instead?
var findDrome = function (i) {
for (var i; removeDec(i) != reverseIt(i); i += (1 / 100)) {
if ((removeDec(i) + 1).toString() == reverseIt(i)) {
document.write(i + (1 / 100));
}
} return
};
findDrome(ask);
The findDrome function takes the ask prompt at the start as an argument. If the number without a decimal doesn't match the reverse without a decimal, then increments it by 0.01. Right before the loop ends, I wanted it to check if the number prior +1 (since it is * 100) is equal to the reverse and if so write the next number.
It wasn't working, so I tried adding parseFloat and toString to specify stricter/more explicit conversions. I also used the loose equality operators, but it's still not working.
My questions: Is this a conversion or syntactical problem or can you not compare the output of 2 functions? Should I instead compare 2 variables and if so how do I assign the for loop in the reverseIt function to a variable?
Your program has a number of issues. First, your reverseIt function never returns a reversed value. The variable x is passed in but it's never updated in the for loop - x.substr() creates a new string instance but it's never assigned back to x so its value never changes. As it is, your for loop in findDrome goes infinite since reverseIt returns undefined.
Another - possible - problem is that you're incrementing a floating-point number by 1/100 but floating point values have no exact representation. I don't know if this is actually affecting your code (since it currently never returns a proper value) but it's something you may have to worry about. This would likely affect parseFloat (which may return a slighly different floating-point value than the string it parses).
Using toFixed() would truncate the number to 2 decimal digits. You could then turn the number to a string and remove the decimal dot character, rather than converting the number back and forth between string and number.
You may want to read up on floating-point arithmetic (if you're not already familiar with it).
As a last comment, you should never, ever rely on Javascript terminating your statements - you should always use ; to terminate a statement like in other proper C-style languages. Leaving out ;-s (even if Javascript lets you get away with it) is considered very poor practice.
I figured it out thanks to the help above! Here is how the fixed program works:
var ask = prompt("Enter a price to find the next palindromic price");
var removeDec = function (j) {
return parseInt(j * 100);
};
var c = removeDec(ask);
This prompts a price and multiplies it by 100 to remove the decimal point and avoid floating point arithmetic. The parseInt removes any decimals smaller than the hundredths place.
var reverseIt = function (x) {
var a = ""
x = x.toString();
for (var i = (x.length - 1); i >= 0; i--) {
a = (a + String(x.substr(i, 1)));
}
return Number(a);
};
var b = reverseIt(c);
The reverseIt function takes an argument, converts it to string and adds each character in reverse to an empty string (a=""). Var a is then returned as a number. The empty string is important for storing the reverse number and is a big reason why my code wasn't working before.
var e = Math.pow(10, (String(c).length - 1));
Var e was added to take into account varying place values to left side of the decimal. Later this helps check if a number is equal to its reverse by adding a 1 to both sides of the number. Var e counts the length of var c (entered value with decimal removed) and finds the appropriate power of 10 to add later. So if you entered 14.40 * 100 then later it will check if 1440 + 1 is equal to 0441 + 1000.. or 10^3. This test is important later in order to exit the loop. This is where my code was failing before because I didn't take adding a number to the reverse into account and I was trying to add decimals which aren't as predictable.
if (c == b) {
document.write("$" + (c / 100) + "... This price is already palindrome!")
} else {
for (c; c !== b; c++) {
b = reverseIt(c);
if ((c + 1) == (b + e)) {
document.write("The next palindromic price is $" + ((Number(c) + 1) / 100));
break;
}
}
}
Here, If the original number and it's reverse are not equal then a loop begins that increments the value by 1 until the entered number + 1 is equal to the reversed number + e. So effectively the loop finds the number right before the loop ends, writes it and then breaks out of the loop. This palindrome finder seems to work smoothly with values big and small, no matter where you put the decimal point. Glad I got it working... it was a great learning experience figuring it out!

Categories