Check letter in word [hangman] - javascript

I'm new in programming.I have to write hangman game i javascript and have a big problem :D This is my function.The problem is : when user enter right letter it is appears in Wrong Guess too and I don't know why.
function IsLetterInWord(letter)
{
for(i = 0; i< Word.length; i++)
{
if(letter == Word[i])
{
secretword[i] == letter;
RightGuess += letter;
var el = document.getElementById("right");
el.innerHTML = "Your right guesses are:" + RightGuess;
win();
}
}
if (letter != Word[i]){
WrongGuess += letter;
var e = document.getElementById("wrong");
e.innerHTML = "Your wrong guesses are:" + WrongGuess;
}
}

You should use of the indexOf() method.The method returns the first index at which a given element can be found in the array, or -1 if it is not present.
Link to docs
"string".indexOf("r") > -1;
You also need to use single equals on line #7:
secretword[i] = letter; // instead of ==

You've got a problem with your logic: you're treating a letter as wrong if it doesn't match every letter in the target, whereas it should only count as wrong if it doesn't match any letter. Also, a wrong letter should only count once, whereas a right letter should count for each match.
Just as a matter of developing good habits (though it makes no real difference in something as small as this), try not to repeat DOM operations unnecessarily since they're fairly slow. Things like
var el = document.getElementById("right");
should be done before a loop rather than inside it (the identity of the element plainly isn't going to change) and things like
el.innerHTML = "Your right guesses are:" + RightGuess;
should only be done after the loop finishes (the browser has to redraw part of the screen each time it's called).

Related

How do I skip a variable value that occurs before user input in javascript?

For my assignment I am supposed to be able to take user inputted text and reverse it. My code works for the most part, but my inverted string starts with NaN. I'm pretty sure this is because my loop does an initial run before user input is collected. I tried to fix this with an if statement:
if (typeof length == 'number') {
//myLoop
}
This only made things worse however. I need to find a work around so that my inverted string does not start with NaN.
var userName = prompt("Enter your first and last name in lower case");
var length = userName.length;
var reverse;
for (var i = length; i >= 0; i--) {
reverse += userName[i];
}
I have tried enclosing my loop within the if statement, and placing my if statement inside the loop; neither works.
Firstly, you need to start reverse with an empty string. Secondly, you have to bear in mind that the index pointer on a string is zero-based, so the last character's position is always one less than the length of the string.
Thus,
var userName = prompt("Enter your first and last name in lower case");
var len = userName.length;
var reverse = "";
for (var i = len - 1; i >= 0; i--) {
reverse += userName[i];
}
console.log(reverse);
Your loop is incorrect. You're starting at an index equal to length, when actually the index range is 0 to length-1
In JS, you can reverse a string in a single line of code.
var userName = prompt("Enter your first and last name in lower case");
var reverse = userName.split('').reverse().join('')
console.log(reverse);

Write a JavaScript function to find longest substring in a given a string without repeating characters

"Write a JavaScript function to find longest substring in a given a string without repeating characters."
Here's what I tried, but it doesn't print anything
function sort(names) {
let string = "";
let namestring = names.split("");
for(let i = 0; i < namestring.length; i++) {
for(let j = 0; j < string.length; j++) {
if(string[j] != namestring[i]) {
string = string + namestring[i];
}
}
}
return string;
}
console.log(sort("google.com"));
What's wrong?
function sort(names)
{
string="";
ss="";
namestring=names.split("");
for(j=0;j<namestring.length;j++) {
for(i=j;i<namestring.length;i++) {
if(string.includes(namestring[i]))
break;
else
string+=namestring[i];
}
if(ss.length<string.length)
ss=string;
string="";
}
return ss;
}
console.log(sort("google.com"));
It's o(n^2) complexity but try this(may be o(n^3) if contains function take o(n) complexity)
function sort(names)
{
string="";
ss="";
namestring=names.split("");
for(j=0;j<namestring.length;j++) {
for(i=j;i<namestring.length;i++) {
if(string.includes(namestring[i])) // if contains not work then
break; //use includes like in snippet
else
string+=namestring[i];
}
if(ss.length<string.length)
ss=string;
string="";
}
return ss;
}
console.log(sort("google.com"));
What are you expecting the answer to be here? Should it be "ogle.com" or "gle.com"? If the first, the below should get you there, if the latter, update the tested = name.charAt(i) in the else to tested = "".
So a few things to note, though you're more than welcome to do as you wish:
1) the function name. This isn't doing a "sort" as far as I can tell, so if this is for your use (or any reuse. Basically, anything more than a one off homework assignment), you may want to rename it to something you'd actually remember (even the example I give is probably not completely best as "pick longest substring" is non-descriptive criteria).
2) variable naming. string and namestring may mean something to you here, but considering we're trying to find the longest substring (with the no double characters) in a string, I felt it was better to have the one we're checking against (tested) and the one we're storing to return later (longest). It helps make sense as you're reading through the code as you know when you are done with a checked string (tested), you want to compare if it is greater than the current longest substring (longest) and if it is bigger, you want it to be the new longest. This will save you a ton of headache to name variables to things that'll help when designing your function as you can get it as close to requirements written down as possible without trying to do some form of substitution or worse, forgetting which variable holds what.
I don't know what you want the result to be in the event that tested length is the same as longest length. Currently I have it set to retain, if you want the most recent, update the check to >=.
Beyond that, I just iterate over the string, setting to the currently tested string. Once double characters are met, I then see if what I just generated (tested) is larger than the current longest and if it is, it is now the longest. Once I finish looping across the string, I have to do the current vs longest check/set again as otherwise, it'd make the final tested meaningless (it went outside the loop before another double character situation was hit).
function pickLongestSubstring(name) {
let tested = "";
let longest = "";
for (let i = 0; i < name.length; i++) {
if (tested.length == 0 || tested.charAt(tested.length - 1) != name.charAt(i)) {
tested += name.charAt(i);
}
else {
if (tested.length > longest.length) {
longest = tested;
tested = "";
}
}
}
if (tested.length > longest.length) {
longest = tested;
}
return longest;
}
console.log(pickLongestSubstring("google.com"))
console.log(pickLongestSubstring("example.com"))
This is a recursive loop that should get the longest string. Uses sort to determine longest string. Works, even if multiple instances of same repeat char.
function longestWithoutRepeat(testString, returnString){
var returnString = returnString || "";
for(var i = 0; i < testString.length; i++) {
if(i > 0){
if(testString[i] == testString[i-1]) {
var testStringArray = testString.split(testString[i] + testString[i-1]);
testStringArray.sort(function(firstString, nextString){ return nextString.length - firstString.length})
returnString = testStringArray[0];
longestWithoutRepeat(testStringArray[0], returnString);
}
} else {
returnString = testString
}
}
return returnString;
}
console.log(longestWithoutRepeat("oolong"));
console.log(longestWithoutRepeat("google.com"));
console.log(longestWithoutRepeat("diddlyougotoofarout"));

Recursion and Loops - Maximum Call Stack Exceeded

I'm trying to build a function that adds up all the numbers within a string... for example, 'dlsjf3diw62' would end up being 65.
I tried to be clever and put together a recursive function:
function NumberAddition(str) {
var numbers='1234567890';
var check=[];
str=str.split[''];
function recursive(str,check) {
if (str.length==0)
return check;
else if (numbers.indexOf(str[0])>=0)
{
for (i=0;i<str.length;i++){
if (numbers.indexOf(str[i])<0)
check.push(str.slice(0,i));
str=str.slice(i);
return recursive(str,check);
}
}
else
str.shift();
return recursive(str,check);
}
You'll see that I'm trying to get my numbers returned as an array in the array named check. Unfortunately, I have a maximum call stack size exceeded, and I'm not sure why! The recursion does have a base case!! It ends once str no longer has any contents. Why wouldn't this work? Is there something I'm missing?
-Will
You can achieve the same thing with a far easier solution, using regular expressions, as follows:
var str = 'dlsjf3diw62';
var check = str.match(/\d+/g); // this pattern matches all instances of 1 or more digits
Then, to sum the numbers, you can do this:
var checkSum = 0;
for (var i = 0; i < check.length; i++) {
checkSum += parseInt(check[i]);
}
Or, slightly more compact:
var checkSum = check.reduce(function(sum, num){ return sum + parseInt(num) }, 0);
The reason your recursion doesn't work is the case where you do enter the for loop, because you've found a digit, but the digits continue to the end of the string. If that happens, the return inside the for loop never happens, and the loop ends. After that, the .shift() does not happen, because it's in that else branch, so you return re-process the same string.
You shouldn't solve this particular problem that way, but the code makes a good example of the anti-pattern of having return statements inside if bodies followed by else. Your code would be clearer (and would work) if it looked like this:
function recursive(str, check) {
if (str.length == 0)
return check;
if (numbers.indexOf(str[0]) >= 0) {
// Find the end of the string of digits, or
// the end of the whole thing
for (var i = 0; i < str.length && numbers.indexOf(str[i]) >= 0; i++);
check.push(str.slice(0, i));
str = str.slice(i);
return recursive(str, check);
}
// A non-digit character
str.shift();
return recursive(str, check);
}
In that version, there are no else clauses, because the two if clauses always involve a return. The for loop is changed to simply find the right value of "i" for the subsequent slicing.
edit — one thing this doesn't fix is the fact that you're pushing arrays into your "check" list. That is, the substring "62" would be pushed as the array ["6", "2"]. That's not a huge problem; it's solved with the addition of a .join() in the right place.

Codecademy lesson troubles

I am learning JavaScript through Codecademy, but I have an issue. The code below is supposed to search through the text variable for my name in the myName variable and then push all of the individual letters to the hits array. The code that I have written is not correct but Codecademy says that it is correct and is going to let me move on in the lesson.
I have been trying to solve the issue that I am having with no luck. The problem is that when I run the hits.push(text); line it will output the entire variable but I have tried hits.push(text[i]); and get undefined for the result. Can someone please help me understand where I have made the mistake?
/*jshint multistr:true */
var text = "XsddfasASSFABrandonSFsdfdasBrandonsddfadfaBrandon";
var myName = "Brandon";
var hits = [];
for (i=0; i<=text.length;i++){
if (text[i]===myName[i]){
for(var x=i; x<i+myName.length;x++){
hits.push(text);
}
}
}
if (hits.length===0){
console.log("Your name wasn't found!");
} else {
console.log(hits);
}
The best way I can think to explain your mistake is simply by walking through a bit of the logic of what you have written.
for (i=0; i<=text.length;i++){
Your for loop will iterate i for as many characters as there are in your text variable, so: 49 times.
if (text[i]===myName[i]){
The first run through your for loop, where i=0, you are checking to see if text[0] is strictly equal to myName[0]. text[0] = X and myName[0] = B. The strictly equals condition is not met, so the loop proceeds to increment i repeat: text[1] = s and myName[1] = r. This continues 47 more times, and the condition is never met. myName[i] is undefined after the first 7 loops.
Normally you would do this kind of thing using indexOf, match, search, substr or substring, which are all string methods.
However for the purpose of this exercise you can do:
var text = "XsddfasASSFABrandonSFsdfdasBrandonsddfadfaBrandon";
var myName = "Brandon";
var hits = [],
namePosition = 0;
for (var i = 0; i < text.length; i++) {
if (text[i] === myName[namePosition]) {
hits.push(text[i]);
namePosition ++;
if (hits.length === myName.length) {
break;
}
}
else {
namePosition = 0;
hits = [];
}
}
if (hits.length === 0) {
console.log("Your name wasn't found!");
} else {
console.log(hits);
}​
(See it working at http://jsfiddle.net/wCWxr/1/). The problems with your original code include:
you try to compare text[i] to myName[i] but the indices of the two strings won't match up.
you try to push the entire string text into hits instead of one character at a time
your logic doesn't deal with the possibility that the beginning but not the end of myName is in text, e.g. if text was aerwerBrasdfsgars
My suggestion fixes this by recording (with namePosition) what position we are currently at within the string myName, and incrementing that when we find a character in text that matches the relevant character in myName. If the characters do not match then it's not a true hit, so we reset hits = [] and namePosition = 0. If the characters all match then hits eventually reaches the length of myName and so we break out of the loop.
If you are trying to find if myName is in text here is what you do:
RegExp:
var pattern = new RegExp(myName);
if (pattern.test(text)){
console.log(myName);
}else {
console.log("Your name wasn't found!");
}
indexOf:
if (text.indexOf(myName) != -1){
console.log(myName);
}else {
console.log("Your name wasn't found!");
}
if (text[i]===myName[i]){
this line should create an error, because myName[i] is not the first letter of myName.
if (text[i]===myName[0]){
Change to this line should work.

Removing a string return after a function has been processed

I'm a beginner and a student and I'm hoping someone can help me out. I have an assignment where I need the program to be broken up into 3 functions. The first takes a sentence from the user, the second converts the sentence into a new "pig language" depending on the length of each word, and the third displays the results in the console. I have the heart of this program done, but I have a problem with clearing out the return string. Specifically, once the user has gone through all 3 steps, I don't want them to be able to enter into the 3rd part of the program and see the results again. I want them to have to go back to the beginning. Sorry for drawing this out so much, but I'm just not sure of how else to explain it.
Here's my code:
function prog1(){
var userLang = prompt("Type in your sentence");
//If the user enters an empty string
if(userLang == ""){
console.log("You must enter a sentence");
}
//If the user presses cancel
else if(userLang == null){
wantToQuit = true;
}
//If the user enters in a good string
else {
console.log("Thank you, now go to program 2");
been2prog1 = true;
return userLang;
}
}
function prog2(){
//sets newLang = userLang and splits the string
var newLang = prog1Lang.split(" ");
//enters loop to find length of each split word
var x = 0;
for( x = 0; x < newLang.length; x++ ){
//if it's 5 or less words, add -oink
if ((newLang[x].length) <= 5){
newLang[x] += "-oink";
}
//if it's more than 5 words, add -a
else {
newLang[x] += "-a";
}
}
**newLang.join(" ");**
//put the string back together
console.log("String converted");
been2prog2 = true;
return newLang;
}
function prog3(){
var endLang = prog2Lang;
console.log(endLang);
**delete prog2Lang;**
}
I was thinking "delete" might work, as seen above, but I didn't do anything all all. Then I was thinking a Boolean, but I am not sure how to go about doing so. Any help would be much appreciated.
One last thing, I am also stuck on how to join my string back together. Currently it logs it in the console as being a part of the array and separates each word with quotes and a comma. I've looked up the .join(); and I thought it would do the trick, but it doesn't seem to work either. I put it inside of the if else statements in function 2 but, it just freaks out when I do that, so pointers on this issue would also be much appreciated.
Thank you!
Try assigning the newLang.join to itself..
newLang = newLang.join(" ");
I wasn't sure what the other bit was that you were having trouble with was, I was a bit confused.
if all you are trying to do is clear out a string variable then..
prog2Lang = null;
or
prog2Lang = "";
null is a null object and "" is an empty string.
Is that what you were after?

Categories