javascript hot and cold game - javascript

I'm making an app that compares a randomly generated number to a number input by the user. From there the app guides the user via "hotter" and "colder" prompts. I'm close, but right now my issue is that the prompts disappear after being displayed for about 1 second. I want the "hotter" or "colder" prompt to stay visible until the user inputs another number.
Here is a link to the app: http://dl.dropboxusercontent.com/u/91499081/HotOrCold/HotOrCold.html?guess=&submit=Submit
Here is my javascript code:
$(document).ready(function () {
var answer = Math.floor((Math.random() * 100) + 1);
console.log("The secret number is: " + answer);
var numberOfGuesses = 0;
var guesses = [];
var distance = null;
var previousDistance = null;
function getGuess() {
$("#submit").click(game);
$("#guess").keydown(function (enter) {
if (enter.keyCode == 13) {
game();
}
});
}
getGuess();
function game() {
var guess = parseInt($('#guess').val());
if (guess !== null && $.isNumeric(guess) && (1 < guess < 101)) {
$('#guess').val('');
numberOfGuesses += 1;
guesses.push(guess);
distance = Math.abs(answer - guess);
previousDistance = Math.abs(answer - guesses[guesses.length - 2]);
if (guess === answer) {
$('#hint').html('Congrats! You got it in ' + numberOfGuesses + ' attempts! The secret number was ' + answer);
} else {
console.log(guess, answer, previousDistance, distance);
if (isNaN(previousDistance)) {
if (guess > answer) {
$('#hint').html('Guess lower! Last guess: ' + guess);
} else if (guess < answer) {
$('#hint').html('Guess higher! Last guess: ' + guess);
}
} else if (distance > previousDistance) {
if (guess > answer) {
$('#hint').html('You\'re getting colder, guess lower! Last guess: ' + guess);
} else if (guess < answer) {
$('#hint').html('You\'re getting colder, guess higher! Last guess: ' + guess);
}
} else if (distance < previousDistance) {
if (guess > answer) {
$('#hint').html('You\'re getting hotter, guess lower! Last guess: ' + guess);
} else if (guess < answer) {
$('#hint').html('You\'re getting hotter, guess higher! Last guess: ' + guess);
}
} else if (distance === previousDistance) {
if (guess > answer) {
$('#hint').html('You\'re on fire, guess lower! Last guess: ' + guess);
} else if (guess < answer) {
$('#hint').html('You\'re on fire, guess higher! Last guess: ' + guess);
}
} else {
$('#hint').html('ERROR: Your guess must be a number between 1 and 100').css({
color: 'red'
});
}
}
}
$('#newgame').click(function (e) {
e.preventDefault();
answer = Math.floor((Math.random() * 100) + 1);
console.log(answer);
numberOfGuesses = 0;
guesses = [];
distance = null;
previousDistance = null;
$('#hint').html('');
$('#guess').val('');
});
}
});

The actual issue is in your HTML. You have a submit button that is part of a form. When you click submit, it is looking for a form action which isn't specified so it is reloading the page.
Change your <form> tag to keep you on the same page by changing it from this:
<form id="myform">
to this:
<form id="myform" action="#">
Or even better, make it so the JS function returns false so that the submit won't go through.

Don't use a <input type="submit" /> button. When it's clicked, your form will attempt to fire off whatever is in the action attribute, which is reloading your page.
You have many options.
I would just use <input type="button" /> or Submit. Then fire off the event when the button or link is clicked.

Your form performs its normal behaviour: post its data to the server. You need to disabled that action. You can either change your 'submit' button to be a normal button so it won't behave as submit:
<input type="button" name="submit" id="submit" class="button"/>
Or add a onsubmit to your form:
<form id="myform" onsubmit="return false">.

Your form is submitting regularly. Since you do not have any action attribute in your form, it will submit your form to the current page. What you want, is to handle the submit with javascript:
<form id="myform">
and in your javascript:
$('#myform').on('submit', game);
function game(event) {
// your code goes here
event.preventDefault();
}
in this way also enter will trigger a post which is handled by javascript, instead of only clicking a submit button.

Related

Get value of variable inside .each() function jQuery

I have code below.
The code works fine, but if I uncomment the "if" statement, alert will show up as soon as I enter something to input field.
I want the "sum" value to be checked (alert shows up) only after I entered all 3 input fields.
Please help me to fix it. Thanks.
<apex:inputField styleClass="Weight" value="{!EvaluationInformation__c.val1__c}" />
<apex:inputField styleClass="Weight" value="{!EvaluationInformation__c.val2__c}" />
<apex:inputField styleClass="Weight" value="{!EvaluationInformation__c.val3__c}" />
$(document).ready(function() {
$(document).on("input", ".Weight", function(e) {
var sum = 0;
$('.Weight').each(function() {
var num = $(this).val();
if (num != null && !isNaN(num)) {
sum += parseFloat(num);
} else {
alert("Accept number only");
}
});
//if (sum != 1){ // sum !=1 doesn't work
// alert("The total of Weight must be 1");
//}
});
});
You can use a status flag that will tell if all inputs are valid, see my example code below.
Also, AFAIK val() for an <input> element never returns null, it returns "" if there is no input. This is why I used if (num && ... instead, which in this situation means "only proceed if num contains text".
$(document).ready(function() {
$(document).on("change", ".Weight", function(e) {
var sum = 0;
var allInputsValid = true; // <-- flag variable
$('.Weight').each(function() {
var num = $(this).val();
if (num && !isNaN(num)) {
sum += parseFloat(num);
} else {
allInputsValid = false;
}
});
if (allInputsValid) {
console.log("All inputs have numbers.");
if (sum != 1) {
console.log("The total of Weight must be 1, but it is: " + sum);
} else {
console.log("The total of Weight is 1.");
}
} else {
console.log("Not all input have numbers yet.");
}
});
});
.Weight { width: 50px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
#1: <input class="Weight" /> #2: <input class="Weight" /> #3: <input class="Weight" />
PS - Even then, you may have trouble making this work because of how Floating Point math works. Due to internal rounding, a sum of numbers that you would expect to be 1 will not always produce exactly 1:
var x = parseFloat("0.34") + parseFloat("0.56") + parseFloat("0.10");
console.log(x);
console.log(x === 1);

How do I use inner.HTML in a function?

I tried to create a Html / Js money counter but if i update, it updates one tick and then it resets itself to an old value. I tried creating a function named update and let it run every time the money value changes, but that did not work either.
<html>
<head>
<title>Betting Simulator Test!</title>
</head>
<body>
<br/>
<p id="p1">You have 500$</p>
<br/>
<form name="CoinFlip" action="" onsubmit="Create()" method="post">
Coins: <input type="text" name="Csubmit">
<input type="submit" value="Flip the Coin">
</form>
<script type="text/javascript">
Balance = 500;
function Game() {
if(Balance >= 1) {
var Coin = confirm("You have put " + sub + "$ in the CoinFlip!");
if(Coin == true) {
var flip = true
if(flip == true) {
alert("You won " + sub + "$");
Balance = Balance + sub*2 - sub;
Update = document.getElementById("p1").textContent="You have " + Balance + "$";
} else {
alert("You lost " + sub + "$");
Balance = Balance - sub;
Update = document.getElementById("p1").textContent="You have " + Balance + "$";
}
} else {
}
} else {
alert("You ran out of Money");
}
}
function Create() {
sub = document.forms["CoinFlip"]["Csubmit"].value;
if(sub <= Balance && sub > 0) {
Game();
} else {
alert("value does not make any sense!");
}
}
</script>
</body>
You have multiple problems. The first one is that you submit a form each time you play, so the page refreshes, and everything is lost. You could find a workaround to avoid this (see this), but in this case, a form is really not needed.
Also, the user is always going to win because you always set flip to true. You can simulate a random win by using this snippet:
var win = Math.round( Math.random() ); // 1 or 0 (truthy or falsy)
Here is a working example:
var balance = 500;
document.getElementById('flip').addEventListener('click', play);
function play(){
// parseInt() converts a String to an integer (10 is for decimal base)
var bet = parseInt(document.getElementById('bet').value, 10);
if(bet <= balance && bet > 0)
{
var accepted = confirm("Do you really want to bet " + bet + "$?");
if(accepted)
{
var win = Math.round( Math.random() ); // Random win
if(win)
{
alert("You won " + bet + "$!");
balance += bet;
}
else
{
alert("You lost " + bet + "$...");
balance -= bet;
}
if(!balance){ alert('You ran out of money...'); }
document.getElementById('p1').textContent = "You have " + balance + "$";
}
document.getElementById('bet').value = 0;
}
else
{
alert("Your bet makes no sense!");
}
}
<p id="p1">You have 500$</p>
<p>Coins: <input type="number" value="0" id="bet"> <button id="flip">Flip the coin</button>

How to force loop to wait until user press submit button?

I have simple function which checks if entered pin code is valid. But i don't know how to force for-loop to wait until i enter code again to check again it's validity.
So how it should be - i type PIN code, then click OK button and it checks whether it's correct (if it is, i can see my account menu; if it's not i have to type it again and i have 2 chances left). My code fails, because PIN when code is wrong program should wait until i type new code and press OK button again.
I tried setTimeout(), callback(), but it doesn't work. This is what i have - a function with for-loop that just runs 3 times (as it is suppose to, but not instantly) without giving a chance to correct the PIN code.
That's whole, unfinished yet, code: http://jsfiddle.net/j1yz0zuj/
Only function with for-loop, which checks validity of PIN code:
var submitKey = function(callback)
{
console.log("digit status" + digitStatus);
if (digitStatus == 0)
{
correctPIN = 1234;
var onScreen = document.getElementById("screen");
for (i=0; i<3; i++)
{
if (onScreen.innerHTML.slice(15, onScreen.innerHTML.length) == correctPIN)
{
setTimeout(accountMenu, 1250);
//break;
}
else
{
onScreen.innerHTML += "<br> Błędny kod PIN! Wpisz PIN ponownie. <br> Pozostało prób: " + (2-i);
callback();
//cardInserted = function(function(){console.log("Ponowne wpisanie PINu");});
}
if (i=2) console.log("blokada");
}
}
else if (digitStatus == 1)
{
}
}
Your approach is wrong. You should not make the user wait!!! You need 2 more variables at the top of your programm pincount=0 and pininputallowed. Increase pincount in the submit key function by 1 and then check if pincount<3.
Here is a corrected version of your code.
http://jsfiddle.net/kvsx0kkx/16/
var pinCount=0,
pinAllowed=true;
var submitKey = function()
{
console.log("digit status" + digitStatus);
if (digitStatus == 0)
{
correctPIN = 1234;
var onScreen = document.getElementById("screen");
pinCount++;
if(pinCount >= 3) {
pinAllowed = false;
onScreen.innerHTML = "<br>blokada";
}
if(pinAllowed){
if (onScreen.innerHTML.slice(15, onScreen.innerHTML.length) == correctPIN)
{
setTimeout(accountMenu, 1250);
//break;
}
else
{
onScreen.innerHTML += "<br> Błędny kod PIN! Wpisz PIN ponownie. <br> Pozostało prób: " + (3-pinCount);
inputLength = 0;
document.getElementById("screen").innerHTML += "<br>Wpisz kod PIN: ";
//callback();
//cardInserted = function(function(){console.log("Ponowne wpisanie PINu");});
}
}
}
else if (digitStatus == 1)
{
}
}
You need to create much more variables to control your machine. Your add/delete digit function had conditions that were badly written and only worked if the text on the screen was short enough.
var inputLength = 0;
addDigit = function(digit){
//numKeyValue = numKeyValue instanceof MouseEvent ? this.value : numKeyValue;{
if (inputLength < pinLength) {
onScreen.innerHTML += this.value;
inputLength++;
}
//if (onScreen.innerHTML == 1234) console.log("PIN został wprowadzony");
},
delDigit = function(){
if (inputLength >= 0) {
onScreen.innerHTML = onScreen.innerHTML.slice(0, -1);
inputLength--;
}
};
If you want to empty the screen at any moment you can insert onScreen.innerHTML = ''; anywhere
ps: Thanks for the exercise and nice automat you made there.

Cant figure out why my div output isn't working

I have a basic hangman program. Click on the letter, it then tells you if its right or wrong by coloring the letter red or green. If its green, it replaces a dash in the hidden word with the letter. That part of my code works. The part that doesn't work is that I have an output section to a div that is supposed to tell you if you got the guess correct or not, and upon 6 failed guesses, you lose and it resets. It's currently not doing any of that. It's not even displaying anything in the div at all.
TY ahead of time. If you have questions about something I didn't explain well enough, ill be back in about 1 hour to answer them. Thanks!
Jsfiddle - http://jsfiddle.net/25b3fr4u/
HTML -
<body>
<form id="form" name="form" method="post" action="">
<input type="button" id="but" value="Start"/>
<div id="hangman-jquery">
<div id="word"></div>
<div id="alpha"></div>
</div>
</form>
<div id="win">
</div>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="hangman.js"></script>
</body>
JS -
function hangman(word) {
var trys = 0;
var guess = 0;
var alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$.each(alpha.split(''), function(i, val) {
$('#alpha').append($('<span class="guess">' + val + '</span>'));
});
$.each(word.split(''), function(i, val) {
$('#word').append($('<span class="letter" letter="' + val + '">-</span>'));
});
$('.guess').click(function() {
var count = $('#word [letter=' + $(this).text() + ']').each(function() {
$(this).text($(this).attr('letter'));
}).length;
$(this).removeClass('guess').css('color', (count > 0 ? 'green' : 'red')).unbind('click');
if (guess > 0) {
$('#win').text("Correct Guess");
} else if (guess < 0) {
$(this).html(++trys);
$('#win').text("You have tried to guess the word and failed " + trys + " times");
}
if (trys == 6) {
alert("You have guessed six times, you lose");
trys = 0;
$("#win").text("");
}
});
}
$(document).ready(function() {
$('#but').click(function() {
var options = new Array("DOG", "CAT", "BAT", "HORSE", "TIGER", "LION", "BEAR", "LIGER", "DOOM", "SPIDER", "TREES", "LAPTOP");
var random = 1 + Math.floor(Math.random() * 12);
hangman(options[random]);
});
});
Code fixed :http://jsfiddle.net/25b3fr4u/1/. The trys where not incremeted properly and you have to check the count instead of guess in your condition. guess was set to 0 and never use.
var count = $('#word [letter=' + $(this).text() + ']').each(function() {
$(this).text($(this).attr('letter'));
}).length;
$(this).removeClass('guess').css('color', (count > 0 ? 'green' : 'red')).unbind('click');
if (count > 0) {
$('#win').text("Correct Guess");
} else if (!count > 0) {
trys++;
$('#win').text("You have tried to guess the word and failed " + trys + " times");
}
if (trys == 6) {
alert("You have guessed six times, you lose");
trys = 0;
$("#win").text("");
}
I'm sure you can handle the rest. Have fun.

validation only working if all text inputs are blank, not any text input is blank

I want to produce a validation message in an alert for when any text input within a question is empty. So for example if I have 2 blank text inputs for question 1, if both text inputs are blank, it displays the validation message You have not entered in a value in all the Indivdiaul Marks textbox.
But the problem is that for question 1 for example, if 1 text input is blank but the other is not blank, it does not display the validation message, even though it should do as not all text inputs have been filled for question 1.
My question is that how can I get the validation message to appear if there is any blank text input per question?
Here is a fiddle so you can test it: http://jsfiddle.net/cbyJD/87/
Below is the validation() function code:
function validation() {
// only keeping track of the final message
var alertValidation = "",
// toggle for showing only one error
showOnlyOneError = true;
$("input[data-type='qmark']").each(function(i) {
var questions = $(this).attr("data-qnum");
var marks = parseInt($("[class*=q" + (i+1) + "_ans_text]").text());
var txtinput = $(this).val();
// the message for this question
var msg = '';
if (txtinput == '') {
msg += "\n\u2022 You have not entered in a value in all the Indivdiaul Marks textbox \n";
}
if (marks < 0) {
msg += "\n\u2022 Your Total Marks Remaining does not equal 0 \n - You Need To Remove " + Math.abs(marks) + " Marks";
} else if (marks > 0) {
msg += "\n\u2022 Your Total Marks Remaining does not equal 0 \n - You Have " + marks + " Marks Remaining";
}
// if there is an error for the question, add it to the main message
if (msg.length) {
alertValidation += alertValidation.length ? '\n\n' : '';
alertValidation += "You have errors on Question Number: " + questions + "\n";
alertValidation += msg;
// stop if we only care about the first error
return !showOnlyOneError;
}
});
// show the error messages
if (alertValidation != "") {
alert(alertValidation);
return false;
}
return true;
}
First, add a hidden variable num_groups with the total number of groups.
<p>
<input type='hidden' id='num_groups' name='num_groups' value='2'>
<input id="submitBtn" name="submitMarks" type="submit" value="Submit Marks" />
</p>
Second, change the validate function to work on a single group of questions:
function validation(group) {
var msg = [];
var nb = 0; // Number of blank values
$("input[data-qnum='" + group + "']").each(function() {
if ($(this).val() == '') {
nb++;
return false;
}
});
if (nb != 0) {
msg.push("\u2022 You have not entered in a value in all the Individual Marks textbox");
}
var marks = parseInt($("[class*=q" + group + "_ans_text]").text());
if (marks != 0) {
msg.push("\u2022 Your Total Marks Remaining does not equal 0");
if (marks < 0) {
msg.push("- You Need To Remove " + -marks + " Marks");
} else if (marks > 0) {
msg.push("- You Have " + marks + " Marks Remaining");
}
}
if (msg.length > 0) {
alert("You have errors on Question Number: " + group + "\n\n" + msg.join("\n"));
return false;
} else {
return true;
}
}
Third, change the myClickhandler function to validate all the groups:
myClickHandler = function(e) {
var ng = $('#num_groups').val();
for (var group = 1; group <= ng; group++) {
if (!validation(group)) return false;
}
if (confirm("Are you sure you want to Proceed?")) {
$.ajax({
url: "insertmarks.php",
data: $("#markstbl").serialize(),
async: false,
type: "POST"
});
return true;
} else {
return false;
}
}
JsFiddle here.
The validation() function returns true no matter what it finds.
You need to declare a variable at the top of this function called errors or similar, with a value of false. For everywhere in the function that an error is found, set the value of errors to true.
At the close of the function with...
return !errors; // return the value of errors NOT'ed
Then you call call validation() in a test, like so...
if (validation()) {
// everything is groovy
} else {
// make them do the form over, or something
}

Categories