Hi I'm struggling to get the hang of JavaScript and am practicing by trying to write a coin toss game using conditional statements and functions can someone point out where I'm going wrong?
var coinToss = prompt("heads or tails?");
console.log(coinToss);
var headTails = function() {
var outCome = Math.floor(Math.random() * 2) + 1;
if (outCome === 1) {
outCome = "heads";
} else {
outCome = "tails";
}
};
console.log(outCome);
var compare = function(outCome, coinToss) {
if (outCome === coinToss.toLowerCase) {
document.write("<p>You Win!</p>");
} else {
document.write("<p>You Loss!</p>")
};
};
toLowerCase is a method hence toLowerCase()
Call the function as compare(headTails(), coinToss);
Return the value from function headTails
Ternary could be used instead of if-else
var coinToss = prompt("heads or tails?");
var headTails = function() {
var outCome = Math.floor(Math.random() * 2) + 1;
console.log(outCome === 1 ? "heads" : "tails");
return outCome === 1 ? "heads" : "tails";
};
var compare = function(outCome, coinToss) {
if (outCome === coinToss.toLowerCase()) {
document.write("<p>You Win!</p>");
} else {
document.write("<p>You Loss!</p>")
};
};
compare(headTails(), coinToss);
You need to call the compare function, like so:
compare(headsTails(),coinToss);
Related
I am writing code for recursion. And here is my code.
Here, what I am trying to do is, if string has ' then replace it with HTML quotes and calling function recursively until all ' have been replaced.
But this is always returning me false. When I alert var a. If I not use return false then it returns undefined. Any clue what is the wrong here?
var a = replaceqt(" hello's there 'how are you?' ");
console.log(a);
function replaceqt(object) {
var indexc = object.indexOf("'");
var next = object.charAt(indexc + 1);
var prev = object.charAt(indexc - 1);
if (indexc == 0) {
object = object.replace("'", "‘");
} else if (parseInt(prev) >= parseInt(0) && parseInt(prev) <= parseInt(9)) {
object = object.replace("'", "'");
} else if (next == " ") {
object = object.replace("'", "’");
} else if (prev == " ") {
object = object.replace("'", "‘");
} else {
object = object.replace("'", "’");
}
indexc = object.indexOf("'");
if (indexc > -1) {
replaceqt(object);
return false;
} else {
return object;
}
}
Because you are returning false whenever there is a second call. Should return the result of recursive invocation instead.
var a = replaceqt(" hello's there 'how are you?' ");
console.log(a);
function replaceqt(object) {
var indexc = object.indexOf("'");
var next = object.charAt(indexc + 1);
var prev = object.charAt(indexc - 1);
if (indexc == 0) {
object = object.replace("'", "‘");
} else if (parseInt(prev) >= parseInt(0) && parseInt(prev) <= parseInt(9)) {
object = object.replace("'", "'");
} else if (next == " ") {
object = object.replace("'", "’");
} else if (prev == " ") {
object = object.replace("'", "‘");
} else {
object = object.replace("'", "’");
}
indexc = object.indexOf("'");
if (indexc <= -1) {
return object;
}
return replaceqt(object);
}
BTW you don't need parseInt(num) if num is a number say 0 or 9.
You need to replace
if (indexc <= -1){
return object;
}else{
replaceqt(object); return false;
}
with
if (indexc <= -1){
return object;
}else{
return replaceqt(object);
}
In your original code, the return value of replaceqt(object) is discarded when indexc >= 0.
You should try using .split and .join functions to simplify your code.
For a simple find-replace all, you can do this:
var sentence = "I hate spaces."
var charToFind = " ";
var replacement = "-";
var afterSplit = sentence.split(charToFind) // ["I", "hate", "spaces"]
var result = afterSplit.join(replacement) // "I-hate-spaces"
Your example is more complex than a find replace, because you need to keep track of left and right quotes.
To get around that, we can figure out if it's even or odd using the index in the array.
var someString = "My 'name' is 'Ryan'... I 'think'."
function replaceQuotesFor (str) {
return str
.split("'")
.map(function (str, index) {
var quote = index % 2 === 1
? '‘'
: '’'
return (index === 0)
? str
: quote + str
})
.join('')
}
console.log('Before:', someString)
console.log('After:', replaceQuotesFor(someString))
I stopped using for loops and modifying indices, because it made debugging frustrating.
I hope these functions help simplify your code and help you in the future!
I have JavaScript calculator wherein I have defined two arrays as follows:
var degInc, degArr = [];
var radInc, radArr = [];
var PI = Math.PI;
var radStart = (-91*PI/2), radEnd = (91*PI/2);
for (degInc = -8190; degInc <= 8190; degInc+=180) {
degArr.push(degInc);
}
for (radInc = radStart; radInc <= radEnd; radInc+=PI) {
var radIncFixed = radInc.toFixed(8);
radArr.push(radIncFixed);
}
to be used in conjunction with the tangent function (below) so as to display a value of Undefined in an input (HTML below) should the user attempt to take the tangent of these values (I have included other relavent function as well):
Input -
<INPUT NAME="display" ID="disp" VALUE="0" SIZE="28" MAXLENGTH="25"/>
Functions -
function tan(form) {
form.display.value = trigPrecision(Math.tan(form.display.value));
}
function tanDeg(form) {
form.display.value = trigPrecision(Math.tan(radians(form)));
}
function radians(form) {
return form.display.value * Math.PI / 180;
}
with jQuery -
$("#button-tan").click(function(){
if (checkNum(this.form.display.value)) {
if($("#button-mode").val() === 'DEG'){
tan(this.form); // INSERT OTHER 'if' STATEMENT HERE FOR RAD ARRAY
}
else{
tanDeg(this.form); // INSERT OTHER 'if' STATEMENT HERE FOR DEG ARRAY
}
}
});
I would like to incorporate an array check within the .click function such that if the user input is contained in the array (degArr or radArr depending on the mode), the calculator returns Undefined. Now, I know how to display Undefined in the input display ($('#disp').val('Undefined')), but I cannot figure out how to configure an if statement that checks the relevant array. Is there a way to do so within the #button-tan function where I have commented?
Loop through the arrays on click and set a variable if you find a matched value.
You can do something like this:
$("#button-tan").click(function(e) {
e.preventDefault();
var userInput = $('#disp').val();
var buttonMode = $('#button-mode').val();
var displayVal = '';
if (buttonMode === 'DEG') {
var radFound = false;
radArr.forEach(function(item) { // changed from degArr
if (item === userInput) {
radFound = true;
}
if (radFound) {
displayVal = 'undefined';
} else {
tan(this.form);
}
});
} else {
var degFound = false;
degArr.forEach(function(item) {
if (item === userInput) {
degFound = true;
}
if (degFound) {
displayVal = 'undefined';
} else {
tanDeg(this.form);
}
});
}
});
You could create a simple object of a Calculator class, which keeps a reference to these arrays, and use like this. I changed some methods to receive the input as parameter rather than form.
$(function () {
function Calculator()
{
var degInc;
this.degArr = [];
var radInc;
this.radArr = [];
var PI = Math.PI;
var radStart = (-91*PI/2);
var radEnd = (91*PI/2);
for (degInc = -8190; degInc <= 8190; degInc+=180) {
this.degArr.push(degInc);
}
for (radInc = radStart; radInc <= radEnd; radInc+=PI) {
var radIncFixed = radInc.toFixed(8);
this.radArr.push(radIncFixed);
}
}
var calc = new Calculator();
function tan(input) {
alert("tan called");
var value = Math.tan(input.value);
alert("tan called. value: " + value);
input.value = value;
}
function tanDeg(input) {
alert("tanDeg called");
var value = Math.tan(radians(input));
alert("tanDeg called. value: " + value);
input.value = value;
}
function radians(input) {
alert("radians called");
var value = input.value * Math.PI / 180;
alert("radians called. value: " + value);
return value;
}
$("#button-tan").click(function(){
alert (calc.degArr);
alert (calc.radArr);
var displayInput = $("#disp");
alert("user input: " + displayInput.val());
if (!isNaN(displayInput.val()))
{
if($("#button-mode").val() === 'DEG')
{
if (calc.radArr.indexOf(displayInput.val()) > -1)
{
alert("user input is in radArr");
}
else
{
alert("user input IS NOT in radArr");
tan(displayInput);
}
}
else
{
if (calc.degArr.indexOf(displayInput.val()) > -1)
{
alert("user input is in degArr");
}
else {
alert("user input IS NOT in degArr");
tan(displayInput);
}
}
}
else
alert("Not a number in input");
});
});
If you wanna do some tests, I created a JSFiddle demo here. Type -8190 in the first input, then click the button. It's gonna be inside the array. Then try typing "DEG" in the second input and clicking again, you'll notice code will check against another array (due to IFs). I couldn't make your auxiliar functions to calculate a value, but I think this helps you with your initial problem.
indexOf should work...
$("#button-tan").click(function(){
if (checkNum(this.form.display.value)) {
if($("#button-mode").val() === 'DEG'){
if (radArr.indexOf(Number(this.form)) > -1) {
$('#disp').val('Undefined');
} else {
tan(this.form);
}
}
else{
if (degArr.indexOf(Number(this.form)) > -1) {
$('#disp').val('Undefined');
} else {
tanDeg(this.form);
}
}
}
});
var fNum = parseFloat("32.23.45"); results in 32.23 but I need the string from last decimal point: 23.45
For example, the following strings should return the following values:
"12.234.43.234" -> 43.234,
"345.234.32.34" -> 32.34 and
"234.34.34.234w" -> 34.34
A fairly direct solution:
function toFloat(s) {
return parseFloat(s.match(/\d+(\.|$)/g).slice(-2).join('.'));
}
For example:
toFloat("32.23.45") // 23.45
toFloat("12.234.43.234") // 43.234
toFloat("345.234.32.34") // 32.34
toFloat("234.34.34.234w") // 34.34
Update: Here's an alternative version which will more effectively handle strings with non-digits mixed in.
function toFloat(s) {
return parseFloat(s.match(/.*(\.|^)(\d+\.\d+)(\.|$)/)[2]);
}
The following will do exactly what you would like (I'm presuming that the last one should return 34.234, not 34.24).
alert (convText("12.234.43.234"));
alert (convText("345.234.32.34"));
alert (convText("234.34.34.234w"));
function convText(text) {
var offset = text.length - 1;
var finished = false;
var result = '';
var nbrDecimals = 0;
while(!finished && offset > -1) {
if(!isNaN(text[offset]) || text[offset] === '.') {
if(text[offset] === '.') {
nbrDecimals++;
}
if(nbrDecimals > 1) {
finished = true;
} else {
result = text[offset] + result;
}
}
offset--;
}
return result;
}
Given the following obj:
var inputMapping = {
nonNestedItem: "someItem here",
sections: {
general: "Some general section information"
}
};
I'm writing a function to get that data by passing in a string "nonNestedItem" or in the nested case "sections.general". I'm having to use an eval and I was wondering if there was maybe a better way to do this.
Here is what I have so far and it works okay. But improve!
function getNode(name) {
var n = name.split(".");
if (n.length === 1) {
n = name[0];
} else {
var isValid = true,
evalStr = 'inputMapping';
for (var i=0;i<n.length;i++) {
evalStr += '["'+ n[i] +'"]';
if (eval(evalStr) === undefined) {
isValid = false;
break;
}
}
if (isValid) {
// Do something like return the value
}
}
}
Linky to Jsbin
You can use Array.prototype.reduce function like this
var accessString = "sections.general";
console.log(accessString.split(".").reduce(function(previous, current) {
return previous[current];
}, inputMapping));
Output
Some general section information
If your environment doesn't support reduce, you can use this recursive version
function getNestedItem(currentObject, listOfKeys) {
if (listOfKeys.length === 0 || !currentObject) {
return currentObject;
}
return getNestedItem(currentObject[listOfKeys[0]], listOfKeys.slice(1));
}
console.log(getNestedItem(inputMapping, "sections.general".split(".")));
You don't need to use eval() here. You can just use [] to get values from an object. Use a temp object to hold the current value, then update it each time you need the next key.
function getNode(mapping, name) {
var n = name.split(".");
if (n.length === 1) {
return mapping[name];
} else {
var tmp = mapping;
for (var i = 0; i < n.length; i++) {
tmp = tmp[n[i]];
}
return tmp;
}
}
This is my code:
var Evalcard = function(number) {
if (number == 1) {
this.name = "Ace";
this.value = 11;
}
else if (number == 11) {
this.name = "Jack";
this.value = 10;
}
else if (number == 12) {
this.name = "Queen";
this.value = 10;
}
else if (number == 13) {
this.name = "King";
this.value = 10;
}
return {this.name,this.value};
I'm pretty sure this return statement is not correct. How do you make a function return more than one value? Any help at all would be great.
In this case, you probably want to return either an array or an object literal:
return { name: this.name, value: this.value };
// later: EvalCard(...).name; EvalCard(...).number;
return [ this.name, this.value ];
// later: EvalCard(...)[0]; EvalCard(...)[1];
How about this:
return [this.name, this.value];
You could pass an object literal as you came so close to doing:
return { name:this.name, value:this.value };
or you could pass an array:
return [this.name, this.value];
Of course if your code is executed in the global context, you'll be setting name and value on the window object. If you're using Evalcard as a constructor, you wont need a return statement, the object being created will automatically be set:
var e = new Evalcard(1);
console.log(e.name); //outputs "Ace" if you remove the return statement.
Try:
return [this.name, this.value];
Try this...
function xyz() {
...
var x = 1;
var y = 'A';
return [x, y];
}
var a = xyz();
document.write('x=' + a[0] + ' and y = ' + a[1]);
Working example: http://jsfiddle.net/CxTWt/
var Evalcard = function(number) {
var evalName, evalValue;
if (number == 1) {
evalName= "Ace";
evalValue = 11;
}else if (number == 11) {
evalName = "Jack";
evalValue = 10;
}else if (number == 12) {
evalName= "Queen";
evalValue= 10;
}else if (number == 13) {
evalName= "King";
evalValue = 10;
}
return {name: evalName, value: evalValue};
}
alert(Evalcard(1).name+" "+Evalcard(1).value);
You need to change it to return an array or give keys to the object you are returning
So
return [this.name,this.value];
Or
return {name:this.name,value:this.value};
I would return an object:
return {key1:value1, key2:value2}
Then you can reference it like so:
myReturn.key1;
You can return it in a number of different ways:
Array
return [this.name,this.value];
Object
return {first:this.name, second:this.value};
String
return this.name+":"+this.value;