Javascript guessing game, defining onkeyup variable - javascript

Super new to javascript. I'm trying to make a psychic guessing game. Everything here works except the onkeyup function. When I open the console log and type letters, it tells me that the userGuess variable is undefined. How do I defined the userGuess variable to match the onkeyup function?
Thanks:
//Available choices
var letterChoices = ['a', 'b', 'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
//score
var wins = 0;
var losses = 0;
var guesses = 9;
var guessesLeft = 9;
var guessedLetters = [];
var letterToGuess = null;
//computer randomly chooses a letter
var computerGuess = letterChoices [Math.floor(Math.random()*letterChoices.length)];
//guesses left function
var updateGuessesLeft = function() {
document.querySelector('#guessLeft').innerHTML = "Guesses Left: " + guessesLeft;
};
//letter to guess function
var updateletterToGuess = function(){
this.letterToGuess = this.letterChoices[Math.floor(Math.random() * this.letterChoices.length)];
};
var updateGuessesSoFar = function(){
document.querySelector('#let').innerHTML = "Your guesses so far: " + guessedLetters.join(', ');
};
//reset
var reset = function(){
totalGuesses = 9;
guessesLeft = 9;
guessedLetters = [];
updateletterToGuess();
updateGuessesSoFar();
updateGuessesLeft();
};
updateGuessesLeft();
updateletterToGuess();
//user input key
document.onkeyup = function(event) {
guessesLeft--;
var userGuess;
console.log(userGuess)
guessedLetters.push(userGuess);
updateGuessesLeft();
updateGuessesSoFar();
if (guessesLeft > 0){
if (userGuess === letterToGuess){
wins++;
document.querySelector('#wins').innerHTML = 'Wins: ' + wins;
alert("How did you know!?!");
reset();
}
} else if (guessesLeft == 0){
losses++;
document.querySelector('#losses').innerHTML = 'Losses: ' + losses;
alert("Sorry, you're not a psychic!");
reset();
}
}

The variable userGuess is undefined because it is just declared. There is no assignment operation happening to this variable. I looked at the working sample, modified it in the browser, and it seems to be working as expected. The only change I did was to assign userGuess to the key pressed, as follows
var userGuess = event.key;
Here is the output I got by playing around a bit with your code
Since you have a list of characters that you want to allow, you could add the following code at the beginning, to make sure anything other than the allowed characters are not considered
if (letterChoices.indexOf(userGuess) === -1) return;

Related

(Javascript) Trying to allow a key press only once in hangman game when it is deemed to be incorrect

Please let me know if there is any additional information I can add to help make my problem more clear!
Im trying to get my hangman game to not allow another key press of the same kind if it is deemed to be incorrect. Once a key press is deemed incorrect it is shown on screen as an incorrect guess and I don't want it to be shown more than once or to count as another incorrect guess as guesses are limited.
Here's a link to my site: https://thy-turk.github.io/Word-Guess-Game/
Here is the code I've been trying to manipulate to allow this.
//if else comparing letter guessed with the current word
if (letterPos.length) {
for(i = 0; i < letterPos.length; i++) {
currentWord[letterPos[i]] = lettersGuessed;
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
} else {
// if (lettersGuessed.includes(letter)) {
// return;
// }
document.getElementById("letters-guessed").innerHTML += lettersGuessed + " ";
guessesLeft--;
document.getElementById("guesses-remain").innerHTML = guessesLeft;
}
The stuff I have commented out is the attempt I kept coming back to, but could never make work.
I know the way I've set this up is less than ideal. I've tried using functions throughout, but just ended up breaking everything.
Here is the entirety of the code for reference.
var currentWord = [];
var answerWord = [];
var lettersReset = "";
var i;
var guessesLeft = 15;
// Array for the word bank of possible answers
var wordAnswers = ["vapor", "wave", "keyboard", "javascript", "coding", "practice", "technology", "hangman", "retro", "internet", "lamborgini", "ferrari", "cellphone", "computer", "headphones", "speakers", "vinyl", "record"];
// Math function to randomly pick a word from the wordbank
var answer = wordAnswers[Math.floor(Math.random() * wordAnswers.length)];
// Variable that counts the number of guesses left
document.getElementById("guesses-remain").innerHTML = guessesLeft;
// Variable that counts the number of wins
var wins = 0;
document.getElementById("num-of-wins").innerHTML = wins;
// Loop that creates empty spaces for the words
for (i = 0; i < answer.length; i++) {
currentWord.push("_");
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
//Function that will evaluate the position of a letter in the word
function wordLetters(letter) {
var letterPos = new Array();
for (i = 0; i < answer.length; i++) {
if (answer[i] === letter)
letterPos.push(i);
}
return letterPos;
}
//Return letters that arent guessed still
function lettersToGuess() {
var i;
var toGuess = 0;
for (i in currentWord) {
if (currentWord[i] === "_")
toGuess++;
}
return toGuess;
}
//Function to capture user input
document.onkeyup = function(event) {
var letter = event.key.toLowerCase();
var lettersGuessed = letter;
var i;
var letterPos = wordLetters(lettersGuessed);
console.log(letter);
//if else comparing letter guessed with the current word
if (letterPos.length) {
for (i = 0; i < letterPos.length; i++) {
currentWord[letterPos[i]] = lettersGuessed;
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
} else {
// if (lettersGuessed.includes(letter)) {
// return;
// }
document.getElementById("letters-guessed").innerHTML += lettersGuessed + " ";
guessesLeft--;
document.getElementById("guesses-remain").innerHTML = guessesLeft;
}
// If user correctly guesses word the game is reset
if (lettersToGuess() == 0) {
guessesLeft = 15;
document.getElementById("guesses-remain").innerHTML = guessesLeft;
document.getElementById("letters-guessed").innerHTML = lettersReset;
answer = wordAnswers[Math.floor(Math.random() * wordAnswers.length)];
currentWord = [];
for (i = 0; i < answer.length; i++) {
currentWord.push("_");
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
wins++;
document.getElementById("num-of-wins").innerHTML = wins;
}
//Resets game if out of guesses
if (guessesLeft === 0) {
guessesLeft = 15;
document.getElementById("guesses-remain").innerHTML = guessesLeft;
document.getElementById("letters-guessed").innerHTML = lettersReset;
answer = wordAnswers[Math.floor(Math.random() * wordAnswers.length)];
currentWord = [];
for (i = 0; i < answer.length; i++) {
currentWord.push("_");
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
}
}
<h1>Press any key to get started!</h1>
<br />
<div class="container">
<p>Wins: </p>
<p><span id="num-of-wins"></span></p><br />
<p>Current Word: </p><br />
<p><span id="active-word"></span></p>
<p>Number of guesses remaining: </p><br />
<p><span id="guesses-remain"></span></p><br />
<p>Letters already Guessed: </p><br />
<p><span id="letters-guessed"></span></p>
</div>
Ok, so I'm gonna put my edited version of your code at the bottom and do the explaining up here.
First, you needed somewhere to keep track of the letters that you had already pressed. I added an array at the top of your script section to keep everything together. This is also important because it is outside the scope of the keyup event
Second, I actually added a little quality of life change in there. You weren't checking if the button pressed was actually a letter so I fixed that by wrapping everything in an if statement and then checking for the letter codes.
Then finally all were doing is using the includes() function. That's gonna check if the letter that was pressed has been seen already. If it has we do nothing. If it hasn't then we'll push that letter into the pastLetters array so that if we see it again we don't punish the user for it. Since the pastLetters array if in the parent scope of this it's persistent and won't be overridden if there's another keydown event.
Also important to note! I added that array to your reset pieces too so that when the game gets reset, the pastLetters array also gets reset.
var currentWord = [];
var answerWord = [];
// Making an array to put the letters that we've already seen into.
var pastLetters = [];
var lettersReset = "";
var i;
var guessesLeft = 15;
// Array for the word bank of possible answers
var wordAnswers = ["vapor", "wave", "keyboard", "javascript", "coding", "practice", "technology", "hangman", "retro", "internet", "lamborgini", "ferrari", "cellphone", "computer", "headphones", "speakers", "vinyl", "record"];
// Math function to randomly pick a word from the wordbank
var answer = wordAnswers[Math.floor(Math.random() * wordAnswers.length)];
// Variable that counts the number of guesses left
document.getElementById("guesses-remain").innerHTML = guessesLeft;
// Variable that counts the number of wins
var wins = 0;
document.getElementById("num-of-wins").innerHTML = wins;
// Loop that creates empty spaces for the words
for (i = 0; i < answer.length; i++) {
currentWord.push("_");
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
//Function that will evaluate the position of a letter in the word
function wordLetters(letter) {
var letterPos = new Array();
for (i = 0; i < answer.length; i++) {
if (answer[i] === letter)
letterPos.push(i);
}
return letterPos;
}
//Return letters that arent guessed still
function lettersToGuess() {
var i;
var toGuess = 0;
for (i in currentWord) {
if (currentWord[i] === "_")
toGuess++;
}
return toGuess;
}
//Function to capture user input
document.onkeyup = function(event) {
// Checking to make sure that the key pressed is actually a letter.
if ((event.keyCode >= 65 && event.keyCode <= 90) || event.keyCode >= 97 && event.keyCode <= 122) {
var letter = event.key.toLowerCase();
var lettersGuessed = letter;
var i;
var letterPos = wordLetters(lettersGuessed);
//if else comparing letter guessed with the current word
if (letterPos.length) {
for (i = 0; i < letterPos.length; i++) {
currentWord[letterPos[i]] = lettersGuessed;
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
} else {
// If the letter has already been seen don't do it again.
if (!pastLetters.includes(letter)) {
// Placing the letter into an array that we can reference outside the scope of the key up event.
pastLetters.push(letter);
document.getElementById("letters-guessed").innerHTML += lettersGuessed + " ";
guessesLeft--;
document.getElementById("guesses-remain").innerHTML = guessesLeft;
}
}
// If user correctly guesses word the game is reset
if (lettersToGuess() == 0) {
guessesLeft = 15;
document.getElementById("guesses-remain").innerHTML = guessesLeft;
document.getElementById("letters-guessed").innerHTML = lettersReset;
answer = wordAnswers[Math.floor(Math.random() * wordAnswers.length)];
currentWord = [];
pastLetters = [];
for (i = 0; i < answer.length; i++) {
currentWord.push("_");
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
wins++;
document.getElementById("num-of-wins").innerHTML = wins;
}
//Resets game if out of guesses
if (guessesLeft === 0) {
guessesLeft = 15;
document.getElementById("guesses-remain").innerHTML = guessesLeft;
document.getElementById("letters-guessed").innerHTML = lettersReset;
answer = wordAnswers[Math.floor(Math.random() * wordAnswers.length)];
currentWord = [];
pastLetters = [];
for (i = 0; i < answer.length; i++) {
currentWord.push("_");
}
document.getElementById("active-word").innerHTML = currentWord.join(" ");
}
}
}
<h1>Press any key to get started!</h1>
<br />
<p>Wins: </p>
<p><span id="num-of-wins"></span></p><br />
<p>Current Word: </p><br />
<p><span id="active-word"></span></p>
<p>Number of guesses remaining: </p><br />
<p><span id="guesses-remain"></span></p><br />
<p>Letters already Guessed: </p><br />
<p><span id="letters-guessed"></span></p>

Triggering a "Win" in a Vanilla JavaScript Hangman Game

So I've already asked a few questions regarding this Hangman game (and have gotten awesome answers), but I've been continually tripped up by my "score keeper". The game almost does everything I need it too, but a "win" will not be logged until after a random key is pressed AFTER the entire word has been filled in...
<!DOCTYPE html>
<html>
<head>
<title>Hangman</title>
</head>
<body>
<h1>Hangman!</h1>
<p>
<font size="+3"><span id="answer"></span></font>
</p>
<p>Lives: <span id="counter"></span></p>
<p id="wrongGuesses"></p>
<p>Wins: <span id="wins"></span></p>
<p>Losses: <span id="losses"></span></p>
<script type="text/javascript">
var word;
var guess; //user guess
var letters = []; //correctly guessed letters
var wrongLetters = []; //incorrectly guessed letters
var counter; //counts correct letters
var losses = 0;
var wins = 0;
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 the array and replaces letters with underscores
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);
}
//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(" ");
//every wrong guess subtracts one from the counter
counter--;
console.log(counter);
document.getElementById("counter").innerHTML = counter;
//when counter reaches 0 it's Game Over
//+1 to the losses if 7 words are missed
if (counter > 0 && letters.join("") === word) { //THE ISSUE
document.getElementById("wins").innerHTML = wins + 1;
console.log(wins);
confirm("YOU WIN! Play Again?");
wins++;
counter = 7;
letters = [ ];
wrongLetters = [ ];
start();
}
else if (counter === 0) {
document.getElementById("losses").innerHTML = losses + 1;
console.log(losses);
confirm("YOU LOOSE... play again?"); {
losses++;
counter = 7;
letters = [];
wrongLetters = [];
start();
}
}
}
}
}
start();
checkLetter();
</script>
</body>
</html>
Here's what I have so far and here is a jsfiddle link: https://jsfiddle.net/t57zfv3t/11/
I know the main issue is with the found bool and the return, but I can't seem to find a way to work around it. If anyone has any insight it would be greatly appreciated and I apologize in advanced to anyone who I have already bothered with this. THANKS!!
You return if the letter is found even if it's a whole word match, so just check that in the condition too
//wrong letters go into the wrongLetters array and are displayed
if (found && letters.join("") !== word) return;

Javascript Hangman - Replace Character In String

I've seen similar questions asked on Stack Overflow regarding this topic, but I haven't seen anything specific that would help me. My issue is that I can't seem to figure out how to replace a dash in hiddenWord with a correctly guessed letter while still retaining the dashes for un-guessed letters. Here is what I have so far and I'm not even sure if it's on the right track.
<script type="text/javascript">
// Declaration of Variables
var wordPool= ["Alf", "MarriedWithChildren", "Cheers", "MASH", "CharlesInCharge", "FmailyTies", "KnightRider", "MagnumPI", "MiamiVice"];
var lives = 6;
var myLetter;
var letter;
var wordChoice;
var hiddenWord;
var i;
var enter;
// Selects word randomly from wordPool[]. Then replaces the letters with "- ".
function selectedWord() {
var number = Math.round(Math.random() * (wordPool.length - 1));
wordChoice = wordPool[number];
for(i = 0; i < wordChoice.length; i++){
hiddenWord = wordChoice.replace(/./g,"- ");
}
console.log(hiddenWord);
}
// Gives myLetter a value of key pressed. If key is "Enter" selectedWord() initiates
document.onkeyup = function(event) {
var myLetter = event.key;
if(myLetter === "Enter"){
selectedWord();
}
console.log(myLetter);
}
</script>
I have seen some stuff with jQuery and PHP but I have to do it in javascript for class. Any help would be appreciated and if this has been addressed before please let me know.
You can check each character at the word string, compare it with the chosen character and replace it, if it is the same character.
I changed your code a bit to reflect what you are looking for.
Also make sure to lowercase all characters to make it easier for the player.
// Declaration of Variables
var wordPool= ["Alf", "MarriedWithChildren", "Cheers", "MASH", "CharlesInCharge", "FmailyTies", "KnightRider", "MagnumPI", "MiamiVice"];
var lives = 6;
var myLetter;
var letter;
var wordChoice;
var hiddenWord;
var i;
var enter;
// Change character to selected one
function checkCharacter(n) {
for(i = 0; i < wordChoice.length; i++){
console.log(wordChoice[i].toLowerCase() + "==" + n);
if(wordChoice[i].toLowerCase() == n.toLowerCase()){
hiddenWord = setCharAt(hiddenWord,i,n);
}
}
console.log("[" + hiddenWord + "]");
}
function setCharAt(str,index,chr) {
if(index > str.length-1) return str;
return str.substr(0,index) + chr + str.substr(index+1);
}
// Selects word randomly from wordPool[]. Then replaces the letters with "- ".
function selectedWord() {
var number = Math.round(Math.random() * (wordPool.length - 1));
wordChoice = wordPool[number];
hiddenWord = wordChoice.replace(/./gi,"-");
console.log(wordChoice + "[" + hiddenWord + "]");
}
// Gives myLetter a value of key pressed. If key is "Enter" selectedWord() initiates
document.onkeyup = function(event) {
var myLetter = event.key;
if(myLetter === "Enter"){
if(lives == 0){
selectedWord();
lives = 6;
}else{
lives--;
}
}
console.log(myLetter);
checkCharacter(myLetter);
}
//Select a random word at start
selectedWord();
I made a JSfiddle that is working and playable:
Check it out here...
Try
hiddenWord += "- "
Instead of replace
Or
hiddenWord += wordChoice[i].replace(/./g,"- ");
Here's an example:
var word = "do this";
var displayWord = [];
for (var i = 0; i < word.length; i++) {//build array
if (word[i] === " ") {
displayWord.push(" ");
} else {
displayWord.push("-");
}
}
function update(userGuess) {//update array
for (var i = 0; i < word.length; i++) {
if (word[i] === userGuess) {
displayWord[i] = userGuess;
} else {
displayWord[i] = displayWord[i];
}
}
}
//Guess letters
update("h");
update("o");
displayWord = displayWord.join('');//convert to string
alert(displayWord);
Check out the pen - https://codepen.io/SkiZer0/pen/VbQKPx?editors=0110

Check if inputs are empty or have text instead of numbers

as you can see here https://jsfiddle.net/kztnmm9o/ I am trying to check if the inputs are empty. If they are empty I want to display the div id="fehler", if every input has a value (must be a number, if not it shall display id="fehler" as well) I want to do the function. I am pretty new to javascript, might be a obvious mistake.
Thank you for your help!
This is the orignal javascript code without checking the inputs, which works:
var selectors = document.querySelectorAll("#eing1, #eing2, #eing3");
for (var i = 0; i < selectors.length; i++) {
selectors[i].addEventListener('keyup', function(event) {
event.preventDefault();
if (event.keyCode == 13) {
document.getElementById("button").click();
}
});
}
function ausgeben(){
var kostentisch = parseInt(document.getElementById("eing1").value)
var bruttogehalt = parseInt(document.getElementById("eing2").value)
var arbeitstage = parseInt(document.getElementById("eing3").value)
var stundenlohn = bruttogehalt/arbeitstage/8;
var arbeitszeit = arbeitstage*8;
var produktivitaetssteigerung = arbeitszeit*0.12;
var produktivitaetssteigerung2 = arbeitstage/produktivitaetssteigerung;
var gewinnprotag = produktivitaetssteigerung2*stundenlohn;
var amortisationszeit = Math.round(kostentisch/ gewinnprotag);
document.getElementById("arbeitszeit").innerHTML=arbeitszeit + " Stunden";
document.getElementById("produktivitaetssteigerung").innerHTML=produktivitaetssteigerung + " Stunden";
document.getElementById("amortisationszeit").innerHTML=amortisationszeit + " Tage";
}
updated fiddle: https://jsfiddle.net/kztnmm9o/3/
Changed the testing to this:
var test = document.querySelectorAll('input[type="text"]');
var error = false;
for (var i = 0; i < test.length; ++i) {
if (test[i].value == "")
{
test[i].style.borderColor = "red";
error = true;
}
}
I also made some minor changes following this logic, but it should be pretty simple to understand.
I also added this.style.borderColor = "transparent"; to keyup event but I'm not sure whether you like or not. So change on will.

I'm using raphael.js for a visual interface on my Battleship game. I'm having some problems

I'm using raphael.js as a visual interface of my Battleship game. I have a function called createCanvas() which creates a grid (10x10). That way the user can see where to aim. The problem is, the grid doesn't appear until after the code of the game (putting in coordinates etc) has finished. Anyone know how to solve this?
Here's the entire code. Below, the code of createCanvas() and of game().
function createCanvas() {
$(function() {
var canvas = Raphael(0, 0, 2000, 2000);
for(var i = 0; i != (BOARD_WIDTH); i++) {
canvas.text((60+70*i), 15, i+1);
}
for(var i = 0; i != (BOARD_HEIGHT); i++) {
canvas.text(15, (60+70*i), i+1);
}
for(var i = 0; i != (BOARD_WIDTH+1); i++) {
canvas.path( "M" + (25+(70*i)) + ",25 L" + (25 + (70*i)) + ",725" );
}
for(var i = 0; i != (BOARD_HEIGHT+1); i++) {
canvas.path( "M25," + (25+(70*i)) + " L725," + (25+(70*i)) );
}
});
}
function game(){
inputArray = [4,3,2];
var boats = randomBoats(inputArray);
var currentBoat = 0;
var sunkenBoat = 0;
var numberOfTurns = 0;
while(sunkenBoat !== inputArray.length ) {
var hit= false;
var target = "(" + prompt("Enter targetcoordinate (x,y)") + ")";
var targetString = target.replace(/\s+/g, '');
for(var i = 0; i !== inputArray.length; i++) {
for(var j = 0; j !== boats[i].usedPositions().length; j++) {
console.log(targetString)
if(targetString === boats[i].usedPositions()[j].toString()) {
hit = true;
boats[i].hits[j] = 1;
console.log(boats[i].hits);
currentBoat = boats[i];
fillSquare(targetString, "red");
break;
}
}
}
console.log(currentBoat.hits);
console.log(allEquals(currentBoat.hits, 1));
if(hit)
alert ("Hit!");
else {
fillSquare(targetString, "blue");
alert ("Miss!");
}
if(allEquals(currentBoat.hits, 1)) {
alert("Boat with length " + currentBoat.hits.length + " has sunken!");
sunkenBoat++;
}
numberOfTurns++
}
alert("You've won! You did it in " + numberOfTurns + " turns.")
}
In my code I call
createCanvas();
game();
so I would think the canvas is drawn first...
The issue is the While loop. You're not giving anything else a chance to get in and do anything. This will just keep going around and around as fast as possible until you're done.
You should take a stab at putting a Input box on the page and and detecting key events looking for the enter key with something like this.
document.onkeypress = function(evt) {
evt = evt || window.event;
var charCode = evt.keyCode || evt.which;
var charStr = String.fromCharCode(charCode);
alert(charStr);
};
That way the animations and other stuff your're going to need later can run without being blocked, you don't burn CPU cycles like crazy, and you only check for a hit when the user has actually entered a value
Then you will maybe even write some code display "Hit" or "Miss" on canvas (may be animated) and that way you can remove all the alert and message boxes that keep popping up.

Categories