Change an image using jquery - javascript

I have a game of hangman where if someone guesses an incorrect letter it adds the image changes. to accomplish this I created a variable that when an incorrect letter is guessed is incremented and I use Jquery .html to change the picture. The problem I have is that the first wrong guess changes the picture but subsequent guesses do not. Is this because Jquery's .html just adds another div? what is a good solution to this? Below is the code
var word;
var wrongGuess = 0;
var usedLetters = [];
$(document).ready(function () {
SetGameBoard();
});
//When guess button is clicked
$('#BtnGuess').click(function () {
CheckGuess();
});
function GetPhrase() {
word = ReturnWord();
alert(word);
}
function SetGameBoard() {
$('#WinLose').hide();
$('#controls').show();
GetPhrase();
wordToGuess = new Array(word.length);
// Place underscore for each letter in the answer word in the DivWord div
for (var i = 0; i < word.length; i++){
wordToGuess[i] = "_ ";
}
$('#DivWord').html(wordToGuess);
}
function CheckGuess() {
var pos = 0;
var posArray = [];
var guessLetter = $('#tbGuessLetter').val();
var picNum = 0;
//check to see if letter has been used
if(usedLetters.indexOf(guessLetter) != -1){
alert("You've already used this Letter!");
}
//populate array with indices of occurrences of guessed letter
while ((pos = word.indexOf(guessLetter, pos)) > -1) {
posArray.push(++pos);
}
//if the guessed letter is not in the word...
if (posArray.length == 0) {
picNum++;
alert(guessLetter + " is not in the word.");
$('#DivPic').html('<img src="images/h'+picNum+'.png" />');
}else{
//iterate over array of underscores (wordToGuess[]) and splice in guessed letter
for(i=0; i < posArray.length; i++){
wordToGuess.splice(posArray[i] - 1, 1, guessLetter);
}
//update DivWord
$('#DivWord').html(wordToGuess);
usedLetters.push(guessLetter);
}
$('#tbGuessLetter').val("");
}

You should move picNum to the top, to declare it as global:
var picNum = 0;
var word;
var wrongGuess = 0;
var usedLetters = [];
Because each time it goes to the CheckGuess() function it resets to zero, then if the user fails it will only increment to 1. That's why you are seeing the same image (first time)

Related

JavaScript word guessing game issue: the same letter won't populate multiple times once the letter key is pressed

I have my word guessing game setup so that when the user presses the correct letter, the corresponding underscore is replaced with the letter. However, I can't seem to get the same letter to populate multiple times. Example: the word "Pennywise" has two of the letter 'n', but when the letter is pressed only one 'n' will populate no matter how many times I press the letter.
// Global Variables
// ================================================================================================================================================
// Create an array of words
var word = [
"michael myers",
"freddy krueger",
"jason voorhees",
"xenomorph",
"pinhead",
"ghostface",
"hannibal lector",
"pennywise",
"leatherface",
"chucky",
"jack torrance"
]
var rightLetter = [];
var wrongLetter = [];
var underScore = [];
// Choose word randomly
var randNum = Math.floor(Math.random() * word.length);
var randWord = word[randNum];
console.log(randWord);
// DOM manipulation
var docUnderScore = document.getElementsByClassName("underscore");
var docRightGuess = document.getElementsByClassName("rightGuess");
var docWrongGuess = document.getElementsByClassName("wrongGuess");
// ================================================================================================================================================
// Main
// ================================================================================================================================================
// Create underscore based on length of word
var generateUnderscore = () => {
for ( var i = 0; i < randWord.length; i++) {
underScore.push("_");
}
return underScore;
}
// Get user guess
document.addEventListener("keypress", (event) => {
var keyWord = String.fromCharCode(event.keyCode);
// if user's guess is correct
if (randWord.indexOf(keyWord) === -1) {
// replace underscore with correct letter
underScore[randWord.indexOf(keyWord)] = keyWord;
docUnderScore[0].innerHTML = underScore.join(" ");
// check to see if user word matches guess
if (underScore.join("") === randWord) {
alert("You Survived!");
}
}
// if user's guess is incorrect
else {
wrongLetter.push(keyWord);
docWrongGuess[0].innerHTML = wrongLetter;
}
});
docUnderScore[0].innerHTML = generateUnderscore().join(" ");
The issue is that you won't proceed further using randWord.indexOf(keyWord) as each time it fetches the first occurence of the letter you want to find, instead you could maintain a counter and match letter each time keydown event is fired, if it doe match then increment it to proceed:
// Create an array of words
var word = [
"michael myers",
"freddy krueger",
"jason voorhees",
"xenomorph",
"pinhead",
"ghostface",
"hannibal lector",
"pennywise",
"leatherface",
"chucky",
"jack torrance"
];
var rightLetter = [];
var wrongLetter = [];
var underScore = [];
var counter = 0;
// Choose word randomly
var randNum = Math.floor(Math.random() * word.length);
var randWord = word[7];
console.log(randWord);
// DOM manipulation
var docUnderScore = document.getElementsByClassName("underscore");
var docRightGuess = document.getElementsByClassName("rightGuess");
var docWrongGuess = document.getElementsByClassName("wrongGuess");
// Create underscore based on length of word
var generateUnderscore = () => {
for (var i = 0; i < randWord.length; i++) {
underScore.push("_");
}
return underScore;
}
// Get user guess
document.addEventListener("keypress", (event) => {
var keyWord = String.fromCharCode(event.keyCode);
// if user's guess is correct
if (randWord[counter] == keyWord) {
// replace underscore with correct letter
underScore[counter] = keyWord;
docUnderScore[0].innerHTML = underScore.join(" ");
// check to see if user word matches guess
if (underScore.join("") === randWord) {
console.log("You Survived!");
}
counter++;
}
// if user's guess is incorrect
else {
wrongLetter.push(keyWord);
docWrongGuess[0].innerHTML = wrongLetter;
}
});
docUnderScore[0].innerHTML = generateUnderscore().join(" ");
<div class="underscore"></div>
<div class="rightGuess"></div>
<div class="wrongGuess"></div>

Score Counters and Reset Functions in Vanilla JavaScript Hangman

I've already had one questions regarding this game answered, but I keep getting stuck up on keeping track of my "wins" and "losses" and then reseting my random word after a win or a loss. Here is what I have so far:
var guess; //user guess
var letters = []; //correctly guessed letters
var wrongLetters = []; //incorrectly guessed letters
var counter = 7; //counts correct letters
var losses = 0;
var wins = 0;
document.getElementById("counter").innerHTML = counter;
document.getElementById("losses").innerHTML = losses;
document.getElementById("wins").innerHTML = wins;
var wordList = ["cat", "dog", "wolf", "laser", "apple"]; //FILL LIST LATER!!
//randomly chooses a word from wordList
var word = wordList[Math.floor(Math.random() * wordList.length)];
//choosen word is replaced with
function start() {
for (i = 0; i < word.length; i++) {
letters[i] = "__";
}
document.getElementById("answer").innerHTML = letters.join(" ");
console.log(word);
}
//checks if letter is in the word or not
function checkLetter() {
document.onkeyup = function(event) {
guess = event.key.toLowerCase();
var found = false;
for (i = 0; i < word.length; i++) {
if (guess === word[i]) {
letters[i] = guess;
document.getElementById("answer").innerHTML = letters.join(" ");
found = true;
}
}
//wrong letters go into the wrongLetters array and are displayed
if (found) return;
if (wrongLetters.indexOf(guess) < 0) {
wrongLetters.push(guess);
document.getElementById("wrongGuesses").innerHTML = wrongLetters.join(" ");
counter--;
console.log(counter);
//+1 to the losses if 7 words are missed
if (counter === 0) {
document.getElementById("losses").innerHTML = losses + 1;
console.log(losses);
confirm("play again?"); {
counter = 7;
letters = [];
wrongLetters = [];
start();
}
}
}
}
}
//need the counter to subtract 1 with every wrong guess
//when counter hits zero losses = losses + 1
//make a wins var that adds 1 when word is guessed
//reset if either are
start();
checkLetter();
<!DOCTYPE html>
<html>
<head>
<title>Hangman</title>
</head>
<body>
<h1>Hangman!</h1>
<span>Just start writing to play.</span>
<p>
<font size="+3"><span id="answer"></span></font>
</p>
<p id="counter"></p>
<p id="wrongGuesses"></p>
<p>Wins: <span id="wins"></span></p>
<p>Losses: <span id="losses"></span></p>
</body>
</html>
The counter is ALMOST working! It seems to be counting down from 7 and adding 1 to the losses when it reaches zero as it should; however, the count displayed is off (even though the count logged to the console seems right).
Another issue is that this "losses" count won't continue to add past 1 even if the counter resets and hits 0 again.
Also, when I try to grab a new random word after the player fails to answer the first, the game chooses the same word as it did before.
I feel like most of these issues have to deal with the scope of my variables, but none of the reworking I try seems to have any affect (if it doesn't make things worse). I know I'm asking a lot here, but if anyone could even point me in the right direction it would be greatly appreciated!
Lets start with fixing the random word.
The variable word needs to be accessed by several functions so it need to be defined on a scope outside the current functions. But you want to set it new each time inside the start() function. You can do that by declaring the variable outside of the function where it is now, but set it inside the function. You should also reset the counter here.
//randomly chooses a word from wordList
var word
//choosen word is replaced with
function start() {
word = wordList[Math.floor(Math.random() * wordList.length)];
counter = 7;
document.getElementById("counter").innerHTML = counter;
for (i = 0; i < word.length; i++) {
letters[i] = "__";
}
document.getElementById("answer").innerHTML = letters.join(" ");
console.log(word);
}
The counter isn't working, because it doesn't look like you're updating the html when the counter changes. You need something like this with each guess:
document.getElementById("counter").innerHTML = counter;
counter--;
console.log(counter);
The losses aren't incrementing because you are only changing the HTML but not the losses variable (kind of the opposite of the above). You need both:
losses++
document.getElementById("losses").innerHTML = losses;
There is also one subtly problem -- you are catching all the keyups including an enter keyup when you first start. You can catch only letters with something like this:
document.onkeyup = function(event) {
// don't catch numbers, punctuation, enter, etc.
if (!(event.which <= 90 && event.which >= 65)) return

Javascript: matching a dynamic string against an array

I'm attempting to teach myself javascript. I chose something I assumed was simple, but ran into problems relatively quickly.
I'm attempting to search a string for another string given by the user.
My code so far is:
var source = "XREs2qqAQfjr6NZs6H5wkZdOES5mikexRkOPsj6grQiYNZfFoqXI4Nnc1iONKVrA";
var searchString = []; //the users input
searchString = prompt("Enter search string");
var hits = [];
var one = 0;
var two = 0;
var k = 0;
var sourceSearch = function(text) {
for(i = 0; i < source.length; i++) { //for each character in the source
if(source[i] === searchString[0]) { //if a character in source matches the first element in the users input
one = source.indexOf(i); //confused from here on
for(p = searchString.length; p > 0; p--) {
}
}
}
};
sourceSearch(searchString);
My idea was:
check to see if the first loop finds a character that matches the first character in the user input
if it matches, check to see if the next X characters after the first match the next X characters in the source string
if they all match, push them to the hits array
My problem: I have no idea how to iterate along the arrays without nesting quite a few if statements, and even then, that wouldn't be sufficient, considering I want the program to work with any input.
Any ideas would be helpful. Thanks very much in advance.
Note: There are a few un-used variables from ideas I was testing, but I couldn't make them work.
You can try:
if (source.indexOf(searchString) !== -1) {
// Match!
}
else
{
//No Match!
}
As the other answers so far point out, JavaScript strings have an indexOf function that does what you want. If you want to see how it's done "by hand", you can modify your function like this:
var sourceSearch = function(text) {
var i, j, ok; // always declare your local variables. globals are evil!
// for each start position
for(i = 0; i < source.length; i++) {
ok = true;
// check for a match
for (j = searchString.length - 1; ok && j >= 0; --j) {
ok = source[i + j] === searchString[j];
}
if (ok) {
// searchString found starting at index i in source
}
}
};
This function will find all positions in source at which searchString was found. (Of course, you could break out of the loop on the first success.) The logic is to use the outer loop to advance to each candidate start position in source and use the inner loop to test whether that position actually is the position of a match to searchString.
This is not the best algorithm for searching strings. The built-in algorithm is much faster (both because it is a better algorithm and because it is native code).
to follow your approach, you can just play with 2 indexes:
var sourceSearch = function(text) {
j = 0;
for(i = 0; i < source.length; i++) {
if(source[i] === text[j]) {
j++;
} else {
j = 0;
}
if (j == text.length) {
console.log(i - j); //this prints the starting index of the matching substring
}
}
};
These answers are all pretty good, but I'd probably opt for something like this:
var source = "XREs2qqAQfjr6NZs6H5wkZdOES5mikexRkOPsj6grQiYNZfFoqXI4Nnc1iONKVrA";
var searchString = []; //the users input
searchString = prompt("Enter search string");
var hits = source.split(searchString);
var hitsCount = hits.length - 1;
This way you have all of the data you need to figure out where each hit occurred in he source, if that's important to you.

Javascript: "TypeError: $(...).html(...).html(...).css is not a function"

i'm trying to write a function which counts the number of syllables in a piece of text, i know it won't be that accurate, it's just a simple version I need at the moment which roughly counts the number of syllables.
whenkeydown = function(max_length) {
$("#my_text").unbind().keyup(function() {
//check if the appropriate text area is being typed into
if (document.activeElement.id === "my_text") {
//get the data in the field
var text = $(this).val();
function countSyllables(words) {
console.log(words);
for (var z; z < words.length; z++) {
word = word[z].toLowerCase();
if(word.length <= 3) { return 1; }
word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');
word = word.replace(/^y/, '');
syllables = word.match(/[aeiouy]{1,2}/g).length;
syllableCount += syllabes
}
return syllableCount
}
var syllableCount = countSyllables(text)
$("#noOfSyllables").html("").html(syllableCount).css("color", "#F7860C"); //orange
The error i get in the (aptana/firefox) debugger is "TypeError: $(...).html(...).html(...).css is not a function", does this mean my function does not return anything?
Your variable syllableCount is never set in your function countSyllables.
I expect to see a var syllableCount = 0;
function countSyllables(words) {
var syllableCount = 0;
...
second issue.
You are treating text() as if it returns an Array. It is a single string.

List Permutations

I'm trying to list all three letter permutations and this is the code I have -
window.permute = function(){
var alphabet = "abcdefghijklmnopqrstuvwxyz";
var searchTerm ="aaa";
var position = 2;
changeString(searchTerm, position);
}
window.changeString = function(searchTerm, position){
if (position <0){
alert(newString);
return;
}
var alphabet = "abcdefghijklmnopqrstuvwxyz"
for (j=0; j < 26;j++){
var newString = searchTerm.substr(0, position) + alphabet[j] + searchTerm.substr(position+1);
var newPosition = position -1;
changeString(newString,newPosition);
}
return;
}
It's not working and I'm not sure why- can anyone help?
var permutate = (function() {
var results = [];
function doPermute(input, output, used, size, level) {
if (size == level) {
var word = output.join('');
results.push(word);
return;
}
level++;
for (var i = 0; i < input.length; i++) {
if (used[i]) {
continue;
}
used[i] = true;
output.push(input[i]);
doPermute(input, output, used, size, level);
used[i] = false;
output.pop();
}
}
return {
getPermutations: function(input, size) {
var chars = input.split('');
var output = [];
var used = new Array(chars.length);
doPermute(chars, output, used, size, 0);
return results;
}
}
})();
for more information, visit http://jinwolf.tumblr.com/post/26476479113/draw-something-cheat
for an working example, check this jsfiddle http://jsfiddle.net/jinwolf/Ek4N5/31/
alert(newString);
newString is not defined right there. Instead, you should use the argument passed:
alert(searchTerm);
Edit: I'm not entirely sure of your approach. It seems overly complicated. This seems to work. I understand that you rather have your own code working, but perhaps this helps you in solving. I don't quite get your substr part.
http://jsfiddle.net/NUG2A/2/
var alphabet = "abc"; // shortened to save time
function permute(text) {
if(text.length === 3) { // if length is 3, combination is valid; alert
console.log(text); // or alert
} else {
var newalphabet = alphabet.split("").filter(function(v) {
return text.indexOf(v) === -1;
}); // construct a new alphabet of characters that are not used yet
// because each letter may only occur once in each combination
for(var i = 0; i < newalphabet.length; i++) {
permute(text + newalphabet[i]); // call permute with current text + new
// letter from filtered alphabet
}
}
}
permute("");
This will result in the following being called:
permute("");
permute("a");
permute("ab");
permute("abc"); // alert
permute("ac");
permute("acb"); // alert
permute("b");
// ...
I'm not sure from your question that you mean "permutations" because usually permutations do not include repeated elements where it looks like you want to include "aaa".
Here are several algorithms for listing permutations you can go check out. If it turns out you mean to have repetitions, it looks like pimvdb has you covered.
Edit: So you know what you are getting into run-time wise:
With repetition (aaa,aab,...): n^k = 26^3 = 17,576
Without repetition (abc,bac,...): n!/(n-k)! = 26!/(26-3)! = 15,600
for (j=0; j < 26;j++){
should be
for (var j=0; j<26; j++) {
Without the declaration, j is a global variable, so it only takes one iteration to get to 26 and then all the loops terminate.
For permutations a recursive algorith as pimvd showed is always nice but don't forget you can just brute force it with for-loops when N is small:
for(int x1=0; x1 < 26; x1++)
for(int x2=0; x2 < 26; x2++)
for(int x3=0; x3 < 26; x3++){
//do something with x1, x2, x3
}
In C#:
void DoPermuation(string s)
{
var pool = new HashSet<string>();
//Permute("", , pool);
pool = Permute(new List<char>(s));
int i = 0;
foreach (var item in pool) Console.WriteLine("{0:D2}: {1}", ++i, item);
}
HashSet<string> Permute(List<char> range)
{
if (range.Count == 1) return new HashSet<string>(new string[] { range[0].ToString() });
var pool = new HashSet<string>();
foreach (var c in range)
{
var list = new List<char>(range);
list.Remove(c);
foreach (var item in Permute(list)) pool.Add(c + item);
}
return pool;
}

Categories