requiring input before conditional statements in javascript - javascript

In this exercise I have a prompt where I want to require input. So if the user doesn't enter anything, it will ask again until a response is given. When a response is finally given it will go through the list of conditional statements. If a response is given on the first prompt it will simply go through that list of conditional statements. I can't seem to get this to work. What am I doing wrong here?
var question = prompt("What programming language are you currently learning?");
var questionUpper = question.toUpperCase();
var firstCap = question.charAt(0).toUpperCase() + question.slice(1).toLowerCase();
while (true) {
if (question === '') {
var test = prompt("Please enter a programming language.");
} else {
break;
}
if (questionUpper === 'HTML') {
alert(questionUpper + ' is a good language to start with.');
} else if (questionUpper === 'CSS') {
alert(questionUpper + ' helps HTML look good.');
} else if (firstCap === 'Javascript') {
alert(firstCap + ' is a fun language to learn after HTML and CSS.');
} else if (firstCap === 'Python') {
alert(firstCap + ' is a good language, too.');
} else {
alert("At least you're learning something.");
}
}

I believe the error is in the while cycle. You are assigning the answer to the variable "test", but the condition is checking the value of "question".
var question = prompt("What programming language are you currently learning?");
while (true) {
if (question === '') {
question = prompt("Please enter a programming language.");
} else {
break;
}
}
var questionUpper = question.toUpperCase();
var firstCap = question.charAt(0).toUpperCase() + question.slice(1).toLowerCase();
if (questionUpper === 'HTML') {
alert(questionUpper + ' is a good language to start with.');
} else if (questionUpper === 'CSS') {
alert(questionUpper + ' helps HTML look good.');
} else if (firstCap === 'Javascript') {
alert(firstCap + ' is a fun language to learn after HTML and CSS.');
} else if (firstCap === 'Python') {
alert(firstCap + ' is a good language, too.');
} else {
alert("At least you're learning something.");
}
I also moved the upper-case after the loop in order to make it effective.

This looks like it makes much more sense to solve using a language object representation (also making it much easier to understand and edit). For example:
var langs = {
html: 'HTML is a good language to start with.',
css: 'CSS helps HTML look good.',
javascript: 'Javascript is a fun language to learn after HTML and CSS',
python: 'Python is a good language, too.'
}
// ask initial question
var answer = prompt('What programming language are you currently learning?')
// ask follow up until answer is given
while(answer.length <= 0){
answer = prompt('Please enter a programming language.')
}
// deal with answer
var lower = answer.toLowerCase()
if(langs[lower]){
alert(langs[lower])
}else{
alert('At least you\'re learning something.')
}
This way you can modify your langs object to contain any properties you like for each language. Maybe they have text related to other questions, or other variables you would like to associate with each language. This makes it easier to add or remove languages, or separate the data from the view, allowing you to get language data easily from a database without changing any logic.

To achieve expected result, you can use switch case option
var question = prompt("What programming language are you currently learning?");
var questionUpper = question.toUpperCase();
var firstCap = question.charAt(0).toUpperCase() + question.slice(1).toLowerCase();
switch(questionUpper){
case 'HTML':
alert(questionUpper + ' is a good language to start with.');
break;
case 'CSS':
alert(questionUpper + ' is a good language to start with.');
break;
case 'JAVASCRIPT':
alert(questionUpper + ' is a good language to start with.');
break;
case 'PYTHON':
alert(questionUpper + ' is a good language to start with.');
break;
default:
alert("At least you're learning something.");
}
The sample in CodePen

Related

Javascript - How to know how much string matched in another string?

I have been implementing a simple quiz for English. In that, we need to validate answers, which are entered by users in input field. In the current implementation, I am comparing the correct answer with user's answer exactly. Like,
HTML
<input type="text" id="answer" />
<button onclick="validate()">Validate</button>
Javascript
var question = "Do you like movies?",
answer = "No, I don't like movies.";
function validate() {
var userInput = document.getElementById('answer').value;
if(answer == userInput) {
console.log("correct");
} else {
console.log("wrong");
}
}
But I don't want validate exactly. Like, ignore case sensitive, commas, apostrophe, etc. For example if user enters,
i dont like movies
The answer can be correct. I don't know how start and where to start. Anyone please help.
One option would be to strip out all non-word characters and spaces, and compare the lower-case version of each replaced string:
var question = "Do you like movies?",
answer = "No, I don't like movies.";
const normalize = str => str
.replace(/[^\w ]/g, '')
.toLowerCase();
function validate(userInput) {
const noramlizedInput = normalize(userInput)
const noramlizedAnswer = normalize(answer);
if (noramlizedInput == noramlizedAnswer) {
console.log("correct");
} else {
console.log("wrong");
}
}
validate('No i dont like movies');
validate("NO!!!!! I DON''t like movies.");
Another option would be to loop through all possible substrings of the userInput and figure out which has the most overlap with the desired answer, but that's a whole lot more complicated.
An easier option would be to check to see how many overlapping words there are:
var question = "Do you like movies?",
answer = "No, I don't like movies.";
const normalize = str => str
.replace(/[^\w ]/g, '')
.toLowerCase()
.split(/\s+/)
function validate(userInput) {
const noramlizedInputArr = normalize(userInput);
const noramlizedAnswerArr = normalize(answer);
const overlapCount = noramlizedInputArr.reduce((a, word) => (
a + Number(noramlizedAnswerArr.includes(word))
), 0);
console.log(overlapCount);
if (overlapCount >= 4) {
console.log("correct");
} else {
console.log("wrong");
}
}
validate('No i dont like movies');
validate("NO!!!!! I DON''t like movies.");
validate("i dont like movies.");
validate("Yes I like movies.");
If you are interested in simply catching spelling errors and small variations, a standard metric is called edit distance or Levenshtein distance. This is a count of the minimum number of deletions, insertions, or substitutions you need to change one text into another. Strings like "No I don't like the movies" and "No I don't like the moveys" will have small edit distances.
Here's a quick and dirty recursive edit distance function that will give you an idea:
function validate(text, pattern) {
// some simple preprocessing
let p = pattern.toLowerCase().replace(/[^a-z]+/ig, '')
let t= text.toLowerCase().replace(/[^a-z]+/ig, '')
// memoize recursive algorithm
let matrix = Array.from({length: t.length + 1}, () => [])
function editDistance(text, pattern, i = 0, j = 0){
if(i == text.length && j == pattern.length) return 0
if(i == text.length) return pattern.length - j
if(j == pattern.length) return text.length - i
let choices = [
(matrix[i+1][j+1] || (matrix[i+1][j+1] = editDistance(text, pattern, i+1, j+1))) + (text[i].toLowerCase() === pattern[j].toLowerCase() ? 0 : 1),
(matrix[i+1][j] || (matrix[i+1][j] = editDistance(text, pattern, i+1, j))) + 1,
(matrix[i][j+1] || (matrix[i][j+1] = editDistance(text, pattern, i, j+1))) + 1
]
return Math.min(...choices)
}
return editDistance(t, p)
}
// similar strings have smaller edit distances
console.log(validate("No I dont lik moves","No i dont like movies"))
// a little less similar
console.log(validate("Yes I like movies","No i dont like movies"))
// totally different
console.log(validate("Where is the bathroom","No i dont like movies"))
// careful -- small edit distance !== close meaning
console.log(validate("I do like tacos","I don't like tacos"))
Picking a minimum acceptable distance works pretty well for matching strings with small typos. Of course, if you are trying to gauge user intent, none of these simple hues tics will work. Strings like "I love tacos" and "I loath tacos" have a small edit distance and you can't tell that they mean the opposite without knowledge of the language. If you need to do this level of checking you can try using a service like Watson Conversation that will return user intents to input.

regexp looping and logic in javascript

Not certain if this can be done in regexp under javascript, but thought it would be interesting to see if it is possible.
So thought I would clean up a piece of html to remove most tags, literally just dropping them, so <H1><img><a href ....>. And that would be relatively simple (well, stole the basis from another post, thanks karim79 Remove HTML Tags in Javascript with Regex).
function(inString, maxlength, callback){
console.log("Sting is " + inString)
console.log("Its " + inString.length)
var regex = /(<([^>]+)>)/ig
var outString = inString.replace(regex, "");
console.log("No HTML sting " + outString);
if ( outString.length < maxlength){
callback(outString)
} else {
console.log("Lets cut first bit")
}
}
But then I started thinking, is there a way where I can control regex execution. So lets say that I want to keep certain tabs, like b,br,i and maybe change H1-6 to b. So in pseudo code, something like:
for ( var i in inString.regex.hits ) {
if ( hits[i] == H1 ) {
hits[i] = b;
}
}
The issue is that I want the text thats not HTML tags to stay as it is, and I want it to just cut out by default. One option would of course be to change the ones I want to keep. Say change <b> to [[b]], once that is done to all the ones of interest. Then put them back to <b> once all unknown have been removed. So like this (only for b, and not certain the code below would work):
function(inString, maxlength, callback){
console.log("Sting is " + inString)
console.log("Its " + inString.length)
var regex-remHTML = /(<([^>]+)>)/ig
var regex-hideB = /(<b>)/ig
var regex-showB = /([b])/ig
var outString = inString.replace(regex-hideB, "[b]");
outString = outString.replace(regex-remHTML, "");
outString = outString.replace(regex-showB, "<b>");
console.log("No HTML sting " + outString);
if ( outString.length < maxlength){
callback(outString)
} else {
console.log("Lets cut first bit")
}
}
But would it be possible to be smarter, writing cod ethat says here is a peice of HTML tag, run this code against the match.
As Tim Biegeleisen sai in its comment, maybe a better solution could be using a parser instead of a Regex...
By the way, if you want to control what is going to be changed by the regex you can pass a callback to the String.prototype.replace:
var input = "<div><h1>CIAO Bello</h1></div>";
var output = input.replace(/(<([^>]+)>)/gi, (val) => {
if(val.indexOf("div") > -1) {
return "";
}
return val;
})
;
console.log("output", output);

"Try...Catch" Block not Working with parseInt()

What I'm trying to do:
I have a javascript program that, when a button is clicked, takes in 4 strings from 4 text boxes in a form, and outputs those strings into a formatted textarea.
function testResults(form){
var errorhandle1 = parseInt(document.myForm.Item_Code.value);
var errorhandle2 = parseInt(document.myForm.Item_Cost.value);
var errorhandle3 = parseInt(document.myForm.Quantity.value);
//above variables are for error handling.
var d = " ";
var subtotal = parseInt(form.Item_Cost.value) * parseInt(form.Quantity.value);
var subtotalValue = parseInt(document.myForm.Subtotal.value);
var testVar = "Item Code: " + form.Item_Code.value + d +
"Item Name: " + form.Item_Name.value + d +
"Item Cost: " + form.Item_Cost.value + d +
"Quantity: " + form.Quantity.value + '\n';
document.myForm.myTextarea.value += testVar;
document.myForm.Subtotal.value = parseInt(subtotal) + subtotalValue;
document.myForm.Sales_Tax.value = document.myForm.Subtotal.value * salestax;
document.myForm.Total.value = parseInt(document.myForm.Subtotal.value) + parseFloat(document.myForm.Sales_Tax.value);
}
The above code works just fine, and does exactly what I want it to do for the scope of my program.
try {
if ((isNaN(errorhandle3) == true) || (isNaN(errorhandle2) == true)) {
throw "Error1";
}
} catch (e) {
if (e == "Error1") {
alert("Error! You must enter a number into the qty and cost fields!");
}
}
What I'm trying to accomplish with the try...catch block is simply to make sure that
document.myForm.Item_Code.value
document.myForm.Item_Cost.value
document.myForm.Quantity.value
are actually numbers.
The try...catch statements trigger every time I run the program and doesn't care what I put in the corresponding text boxes. I would greatly appreciate any and all insight on this!
Also: I looked at both of these links and was unable to understand my problem.
javascript parseInt return NaN for empty string
http://www.w3schools.com/jsref/jsref_isnan.asp
Your root problem here is that isNaN() tests to see if the value is NaN. It does not test to see if a string is a proper number. It has some coercion rules to try to deal with strings, but that really isn't what it is designed for.
You can see ways to test if something can be parsed into a valid number here: Validate decimal numbers in JavaScript - IsNumeric()
It's worth reading the detail in the good answers there, but it boils down to something like this which is a bit more than you need, but is general purpose:
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
And, then there's no reason to use exceptions in your code, so you can just do this:
if (!isNumber(errorhandle3) || !(isNumber(errorhandle2)) {
alert("Error! You must enter a number into the qty and cost fields!");
}
Also, in your code, some .Value properties look like maybe they should be .value (lowercase).
In your first code block
var errorhandle2 = parseInt(document.myForm.Item_Cost.Value);
var errorhandle3 = parseInt(document.myForm.Quantity.Value);
You are using Value, which should be value, that's case-sensitive.
By the way, isNaN returns boolean, you don't have to compare with true

How to find on 'input' the value has the '//' ( forward slash ) more than one time consequently?

I have a path, where the user can use the '/' forward slash only one time. In case if he use more than one forward slash ('//'), I suppose to throw an error.. at present I am testing on key press like this:
this.validatePageName = function($input) {
var val = $input.val().trim(),
isValid = true;
var forwardSlashes = !val.match('//');
if (!forwardSlashes) {
$input.denaliError( "\"" + val + "\" is not valid for a page name.");
isValid = false;
}
return isValid;
};
But apart from using 'match' - is there any good approach? any one suggest me some other bullet proof process if any?
if(val.indexOf("//") > -1){
This is what I was taught to use, however using match is perfectly fine too.

Better way to create text based game [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Right, i was uncertain if I should post this as it is a little vague but I really would like some help with this so I will try explain as best as possible.
The Idea:
To create a text based game using Javascript/jQuery, the game will be that of one where a story is being told and you get to pick the options.
My idea was to use a textarea to allow input from the user (select a option) and output text (from the story).
How far have I got?
Well this is what I have created so far.
JavaScript/jQuery:
var current, text, location, option1, option2;
location = ''; // house, car, moon
current = 0;
gameOver = false;
pick = false;
jQuery("textarea").keypress(function (e) {
if (e.which == 13) {
var content = this.value;
var lastLine = content.substr(content.lastIndexOf("\n") + 1);
// Story
if (current == 0 && pick == false) {
option1 = 'Look around';
option2 = 'Check you have arms (Check arms)';
text = 'You open your eyes \n\nOptions: \n' + option1 + '\n' + option2;
pick = true;
} else if (current == 0 && lastLine == 'Check arms' && pick == true) {
text = 'You check your arms, they seem fine';
pick = false;
} else if (current == 0 && lastLine == 'Look around' && pick == true || current == 2 && lastLine == 'Get Out') {
option1 = 'Walk to a nearby house';
option2 = 'Get in a rocket that is next to you (Get in rocket)';
text = 'You do a 360 spin, you see you have limited options \n\nOptions: \n' + option1 + '\n' + option2;
pick = false;
if (current == 2 && lastLine == 'Get Out') {
current = 1;
} else {
current++;
}
}
//House Story
else if (current == 1 && lastLine == 'Walk to house' && pick == false) {
option1 = 'Knock on the front door';
option2 = 'Jump through the front window';
text = 'You walk to the house and see there are no lights on, the building is old and appears to be burnt out\n\nOptions: \n ' + option1 + '\n ' + option2;
pick = false;
current++;
}
// Rocket story
else if (current == 1 && lastLine == 'Get in rocket' && pick == false) {
option1 = 'Get out of the rocket(Get out)';
option2 = 'Hit the biggest button you can find(Hit Button)';
text = 'You hop into the rocket, there are a lot of buttons infront of you\n\nOptions: \n ' + option1 + '\n ' + option2;
pick = false;
current++;
}
$('textarea ').val($('textarea ').val() + '\n\n ' + text + '\n ');
}
});
It works (kinda) but it is getting complicated to code like this. To me its very messy and I have tried to re-write it but I cannot find a way to make this neat/ easier to code.
Have a look at the demo:
Please do take a look at the demo if you wish to try and help me as you will get a good idea what I am trying to achieve.
Demo walk-through:
DEMO HERE
In the textarea click enter to start
Type one of the options to progress in the game (Options: Check arms or Look around)
Type one of the options to progress in the game (Options: Walk to a nearby house or Get in rocket)
End of demo
Note: After typing a option click enter to continue. At the moment all options must be typed exactly as seen (If option has brackets you type that instead)
This is a short demo but you should get the point. I have searched around and cant find/think of a suitable method to code this game.
Get to the point, what's the question?
My questions is: What is a suitable method to code this game?
Suitable: Easy to maintain/read + add new story "parts" etc.
I would go with some kind of strategy pattern. Create i.e. a Game constructor
var Game = new function(strategy) {
this.strategy = strategy;
}
Game.prototyp.playScene = function() {
return this.strategy();
}
Then you can create scenes where you would place your logic
var sceneOne = function() {
console.log('First scene logic here');
}
var sceneTwo = function() {
console.log('Second scene logic here');
}
and finally you can call these logics as follows:
var game;
if(e.which == 13) {
if(condition1) {
game = new Game(sceneOne);
} else {
game = new Game(sceneTwo);
}
game.playScene();
}
fiddle
The biggest issue I see here is that your code is going to grow and grow as your game/story expands. You're actually writing the logic of your game in the code itself.
As an alternative I would suggest splitting out your logic into steps and logic. For example:
var allTiles =
[
{location: 'Forest', description: 'Deep, dark and scary'},
{location: 'Castle', description: 'High, made from stone and very dramatic'},
];
var currentState =
{
equipment: ['Sword', 'Bow', '3 gold coins'];
currentLocationIndex: 0
};
These may of course be in different files so you can add locations to your world.
Next you need your core logic class, this will look a lot like the one you've already got:
jQuery("textarea").keypress(function (e) {
var currentLocation = allTiles[currentState.currentLocationIndex];
printDescription(currentLocation.Description);
// process commands... into pseudo code territory
if(userDoesAction1){
currentLocation.doAction1();
}
}
I've not gone into massive detail here - it will depend very much on the structure of your game. Personally I like the idea of creating an array functions in your location which are things you can do at your location... actually, JS is a very nice language to do this sort of game!
You can use my jQuery terminal. Then you can write core of the game that act on data in JSON object. If you write something like this you will be able to change the data (update or replace) without need to change the code, it's called data driven programming (Eric Raymond write nice chapter in his book about it)
When making games i think that an Object Oriented approach is the best to keep things separated and easy to code and find:
For example you could separate the different rooms in your game in different function structures.
var parentFunction = function(){
var protectedValue = ‘variable’;
var childFunction = function(){
alert(protectedValue);
}
childFunction();
}
var object = new parentFunction();
You initialize the function every time you move to the related ambient, and put the possible actions that the player can take in child-functions.
But i guess the answer would be too big here: you should spend some time before starting to make a scheme of the logic that your game will follow and how you want to separate things (and how they relate to each other).

Categories

Resources