Beginners JavaScript - javascript

I'm new to JavaScript.
I've worked my work through Learning JavaScript (o'reilly) but am just trying to make my first JavaScript.
I thought it best to work on something I'm interested in and as it turned out is fairly complicated.
I'm basically trying to simulate (eventually) a situation in Space Hulk (Boardgame) where a Genestealer has 12 steps between him and the Space Marine.
On the first step its 6 on either dice to kill the Genestealer, and after that 5 or 6 to kill.
The gun jams if the number on the dice is the same.
I'm just trying to emulate the first step here. I think the problem is with jamCheck.
Basically this outputs as always true, even if I change it to != it always shows gun jammed.
I wondered if the variable needed to be passed into another local variable, but it works for killCheck without having to do this. (and I tried it, although I may be doing it wrong)
It is completely possible there is something really simple wrong here.
I hope you can help, or point me in the right direction.
Many thanks!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>SH</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
//<![CDATA[
function diceRoll1() {
iValue = Math.random(); // random number between 0 and 1
iValue *= 6; // multiply by 6 to move the decimal
iValue = Math.floor(iValue)+1; // round to nearest integer. +1 to 1-6.
var roll1 = iValue;
document.getElementById('result1').innerHTML = 'Dice roll 1 : ' + roll1;
killCheck (roll1);
jamCheck (roll1);
return;
}
function diceRoll2() {
iValue = Math.random(); // random number between 0 and 1
iValue *= 6; // multiply by 6 to move the decimal
iValue = Math.floor(iValue)+1; // round to nearest integer. +1 to 1-6.
var roll2 = iValue;
document.getElementById('result2').innerHTML = 'Dice roll 2 : ' + roll2;
killCheck (roll2);
jamCheck (roll2);
return;
}
function killCheck(roll1,roll2){
if (roll1==6 || roll2==6)
{
document.getElementById('kill').innerHTML = 'GS KILLED';
}
return;
}
function jamCheck(roll1,roll2){
if (roll1 == roll2)
{
document.getElementById('jam').innerHTML = 'GUN JAMMED';
}
return;
}
//]]>
</script>
</head>
<body onload="diceRoll1();diceRoll2();killCheck();jamCheck();">
<p id="result1">Dice roll 1</p>
<p id="result2">Dice roll 2</p>
<p id="kill">GS ALIVE</p>
<p id="jam">GUN FINE</p>
</body>
</html>
EDIT: I eventually got there with a lot of help from a friend; here is the current code:
...
function getDiceValue() {
var diceValue = Math.random();
diceValue *= 6;
diceValue = Math.floor(diceValue) + 1;
return diceValue;
}
function killCheck(roll1, roll2) {
if (roll1 === 6 || roll2 === 6) {
document.getElementById('kill').innerHTML = 'GS KILLED';
}
return;
}
function jamCheck(roll1, roll2){
if (roll1 === roll2) {
document.getElementById('jam').innerHTML = 'GUN JAMMED';
}
return;
}
function rollDice() {
var roll1 = getDiceValue(),
roll2 = getDiceValue();
document.getElementById('result1').innerHTML = 'Dice roll 1 : ' + roll1;
document.getElementById('result2').innerHTML = 'Dice roll 2 : ' + roll2;
killCheck (roll1, roll2);
jamCheck (roll1, roll2);
}
//]]>
...
<body onload="rollDice();">

Math.floor() rounds down (think about the name... ceil rounds up) if you REALLY want to round to the "nearest" integer you need to use Math.round().
In your case if you multiply by 6 and round down you'll never get a number higher than 5.
I suspect this is your problem, though I only glanced at your code, so, forgive me if that's just one mistake and not the cause of your issue.
[Edit] upon further reflection, disregard the above. The problem is that your methods expects 2 parameters but you're only passing in one.
I think you're misunderstanding the way parameter passing works.
jamCheck(p1, p2){} what you name these is not relevant. These labels only exist INSIDE your method. I suspect that what is confusing you is that you're using the same labels for the variables you're passing in, as well as the ones in your method. So, when you call the method jamCheck(roll1) it can't do what it needs to cause it's designed to work on 2 variables. Beyond that whatever result you're getting is just the browser trying to make up for code whose syntax is broken. In languages like C or Java you wouldn't even be able to compile such code; You'd be pointed at these lines as not making any sense, by the compiler.
So, the solution is (something like)...
var roll1,roll2;
roll1 = diceRoll1();
roll2 = diceRoll2();
jamCheck(roll1,roll2);
killCheck(roll1,roll2);
But in your diceRoll methods the last thing you'll need to do is return roll1; (or roll2 respectively)
And look to kirean's answer for how to wrap this all up in an init method, so that you're not calling 4 (or more) methods from the body's onload callback.

Youre doing a couple things wrong here, the first is confusing function scoped variables with global scoped variables.
this function
function jamCheck(roll1,roll2){
if (roll1 == roll2)
{
document.getElementById('jam').innerHTML = 'GUN JAMMED';
}
return;
}
expects two parameters, but you are passing in none here body onload="...jamcheck()"
as a result, undefined is equal to undefined, so of course its true.
You need a wrapper function similar to this
function executeGame(){
var dice1 = rollDice1();
var dice2 = rollDice2();
jamCheck(dice1, dice2)
}
And then call this function on body onload.

Related

I am stuck with html/javascript webpage

I'm trying to solve a problem and I quote:
"A game needs to be created in which the user attempts to guess a random whole number between 1 and 100. Upon Guessing, the game will tell the user if they need to go higher or lower. If the user guesses the number, the game will tell them they’re right, and how many attempts it took"
I'm trying to attempt this by having a webpage with a prompt asking for the guess, and then if loops deciding if the guess is the same, higher or lower than the random number. However! I've got the prompt to show up, but no matter what number it will always say the numbers correct! Please help!
Here's my html:
<!DOCTYPE html>
<html lang="en">
<script src="Assignment%20Task%202.js"></script>
<body>
PLAY THE GUESSING GAME:
Guess a number between 0 and 1000!
</body>
<br>
<button onclick= "Guessing_game()" >play</button>
<br>
<p>
You have guessed this many times:
</p>
<p id="num_guesses"></p>
</html>
here's my javascript:
var number = Math.floor(Math.random() * 1000) + 1;
var num_guesses = 1;
function Guessing_game() {
var guess;
guess = prompt("what is your guess?");
if (guess = number) {
alert("Good Job! You got the number correct!");
}
if (guess < number) {
num_guesses = +1;
alert("Bad luck! You need to guess lower");
}
if (guess > number) {
num_guesses = +1;
alert("Bad luck! You need to guess higher");
}
document.getElementById("num_guesses").innerHTML = num_guesses;
}
The problem is with your if (guess = number) line of code.
Using guess = number assigns the number to the guess variable here. If you want to check whether guess is equal to number use guess==number in the if condition like:
if (guess == number)
For more information, you can read it out here.
= is assignment operator.
For e.g var a = "foo";
== is used for value comparison.
For e.g
if(a == "foo") {
// Do something if above condition is true
}
=== is strict comparison, that means value and type should be same .
As others have pointed out, in javascript (and in many other languages):
= is the assignment operator
But the best operator to use (especially in javascript) is not ==.
== indicates that two values are equivalent
Instead, the best operator to use is ===:
=== indicates that two values are identical.
In this case, this is, ideally, what you ought to be using in your script:
if (guess === number) {
[... CODE HERE...]
}

Devide numbers on countup function

I'm starting to learn javascript and I basically needed a countup that adds an x value to a number(which is 0) every 1 second. I adapted a few codes I found on the web and came up with this:
var d=0;
var delay=1000;
var y=750;
function countup() {
document.getElementById('burgers').firstChild.nodeValue=y+d;
d+=y;
setTimeout(function(){countup()},delay);
}
if(window.addEventListener){
window.addEventListener('load',countup,false);
}
else {
if(window.attachEvent){
window.attachEvent('onload',countup);
}
}
There's probably residual code there but it works as intended.
Now my next step was to divide the resultant string every 3 digits using a "," - basically 1050503 would become 1,050,503.
This is what I found and adapted from my research:
"number".match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
I just can't find a way to incorporate this code into the other. What should I use to replace the "number" part of this code?
The answer might be obvious but I've tried everything I knew without sucess.
Thanks in advance!
To use your match statement, you need to convert your number to a String.
Let's say you have 1234567.
var a = 1234567;
a = a + ""; //converts to string
alert(a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(","));
If you wish, you can wrap this into a function:
function baz(a) {
a = a + "";
return a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
}
Usage is baz(1234); and will return a string for y our.
While I do commend you for using a pattern matching algorithm, this would probably be easier to, practically speaking, implement using a basic string parsing function, as it doesn't look anywhere as intimidating from just looking at the match statement.
function foo(bar) {
charbar = (""+bar).split(""); //convert to a String
output = "";
for(x = 0; x < charbar.length; x++) { //work backwards from end of string
i = charbar.length - 1 - x; //our index
output = charbar[i] + output; //pre-pend the character to the output
if(x%3 == 2 && i > 0) { //every 3rd, we stick in a comma, except if it is not the leftmost digit
output = ',' + output;
}
}
return output;
}
Usage is basically foo(1234); which yields 1,234.

Finding the smallest multiple

I'm trying to learn and practice javascript on my own and I've made a bit of progress but I can still get stuck with elementary problems. I think my code is really close to giving me the correct answer but I fail to see what issue I'm missing. If someone better at coding would please take a second and fill me in on what logic error I have, I would be greatly appreciative!
<script>
//2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
var input = 11;
function smallestMultiple(){
for(var i = 2; i <= 10; i++){
if(input % i === 0 && isDivisible(input))
alert(input);//this should only alert when input is divisible by all numbers between 2 and 10
}else{
input ++;
//if input isn't divisible by all numbers between 2 and 10, increment input by 1
}
}
};
// The following function should return true when "input" is divisible by 10, which is the trigger for alerting "input"
function isDivisible(input){
if(input % 10 === 0){
return true;
}else{
return false;
}
};
smallestMultiple();
</script>
Your script is going to find the smallest integer that's divisible both by 10 and a number in 2,3,...,9, which is not what you need.
The faster implementation would probably be setting a couple of temporary divisors that shrinks until the left edge surpass the right one ...
The simplest instead is just selecting a number in 1,2,3...,9, then try to divide it for every number in 1,2,3...,9
The following html sandbox (to remain on-topic) would probably help you to understand.
<html>
<head>
<meta charset="utf8">
</head>
<body>
<div>
<p class="output"></p>
</div>
<script>
window.onload = function() {
function smallest_shared_multiple(from, to) {
var tmp_divisor = from
var tmp_candidate = tmp_divisor
for(;tmp_divisor < to +1;) {
if (tmp_candidate % tmp_divisor) {
tmp_divisor = from
tmp_candidate++
} else {
tmp_divisor++
}
}
return tmp_candidate
}
document.querySelector('p.output').innerHTML =
'For the given range, the smallest shared multiple is ' +
smallest_shared_multiple(1, 10)
}
</script>
</body>
</html>
edit: Please, consider to indent your code before posting. Moreover, as a general rule of programming, it's better naming functions in way that's evocative to what they're supposed to do. ..and make variables' scope the smallest you can. :)

JavaScript factorial prevent infinity

I have been using this function for calculating factorial numbers in JavaScript:
var f = [];
function factorial (n) {
if (n == 0 || n == 1)
return 1;
if (f[n] > 0)
return f[n];
return f[n] = factorial(n-1) * n;
}
All seemed to be going well until I tried the number 500. It returned infinity.
Is there a way that I can prevent infinity as an answer?
Thank you.
You indeed need to use bignumbers. With math.js you can do:
// configure math.js to work with enough precision to do our calculation
math.config({precision: 2000});
// evaluate the factorial using a bignumber value
var value = math.bignumber(500);
var result = math.factorial(value);
// output the results
console.log(math.format(result, {notation: 'fixed'}));
This will output:
1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
500! is, for lack of a better term, "[bleep]ing huge".
It is far, far beyond what can be stored in a double-precision float, which is what JavaScript uses for numbers.
There's no way to prevent this, other than use numbers that are reasonable :p
EDIT: To show you just how huge it is, here's the answer:
500! = 1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
That right there is a 1,135-digit number. For comparison, double-precision floats can handle about 15 digits of precision.
You could consider using an arbitrary precision numeric library. This is a question of its own, though. Here's one related question: https://stackoverflow.com/questions/744099/is-there-a-good-javascript-bigdecimal-library.
I dont know if anyone has solved this elsewise...
I'm a novice beginner in coding and dont know all the aspects. But after I faced this factorial problem myself, i came here when searching for the answer. I solved the 'infinity' display problem in another way. I dont know if its very efficient or not. But it does show the results of even verry high intergers.
Sorry for any redundancy or untidiness in the code.
<!DOCTYPE html>
<html>
<head>
<title>Factorial</title>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'></script>
</head>
<body>
<input type='text' id='number' />
<input type='button' value='!Factorial!' id='btn' />
<script>
var reslt=1;
var counter=0;
var mantissa=0; //stores the seperated matissa
var exponent=0; //stores the seperated exponent
$(document).ready(function (){
$('#btn').click(function (){
var num=parseFloat($('#number').val()); //number input by user
for(i=1;i<=num;i++){
reslt=reslt*i;
//when the result becomes so high that the exponent reaches 306, the number is divided by 1e300
if((parseFloat(reslt.toExponential().toString().split("e")[1]))>=300){
reslt=reslt/1e300; //the result becomes small again to be able to be iterated without becoming infinity
counter+=1; //the number of times that the number is divided in such manner is recorded by counter
}
}
//the mantissa of the final result is seperated first
mantissa=parseFloat(reslt.toExponential().toString().split("e")[0]);
//the exponent of the final result is obtained by adding the remaining exponent with the previously dropped exponents (1e300)
exponent=parseFloat(reslt.toExponential().toString().split("e")[1])+300*counter;
alert(mantissa+"e+"+exponent); //displays the result as a string by concatenating
//resets the variables and fields for the next input if any
$('#number').val('');
reslt=1;
mantissa=0;
exponent=0;
counter=0;
});
});
</script>
</body>
</html>
Javascript numbers can only get so big before they just become "Infinity". If you want to support bigger numbers, you'll have to use BigInt.
Examples:
// Without BigInt
console.log(100 ** 1000) // Infinity
// With BigInt
// (stackOverflow doesn't seem to print the result,
// unless I turn it into a string first)
console.log(String(100n ** 1000n)) // A really big number
So, for your specific bit of code, all you need to do is turn your numeric literals into BigInt literals, like this:
var f = [];
function factorial (n) {
if (n == 0n || n == 1n)
return 1n;
if (f[n] > 0n)
return f[n];
return f[n] = factorial(n-1n) * n;
}
console.log(String(factorial(500n)));
You'll find that you computer can run that piece of code in a snap.
Hi this is due to the nature of java script as it can't represents number above 253-1 reference so to solve this either wrap the number with BigInt(n) or add to the number >> 3n
const factorial = (n) => {
n = BigInt(n)
if ( n < 1 ) return 1n
return factorial(n - 1n) * n
}

Math.random() returns value greater than one?

While playing around with random numbers in JavaScript I discovered a surprising bug, presumably in the V8 JavaScript engine in Google Chrome. Consider:
// Generate a random number [1,5].
var rand5 = function() {
return parseInt(Math.random() * 5) + 1;
};
// Return a sample distribution over MAX times.
var testRand5 = function(dist, max) {
if (!dist) { dist = {}; }
if (!max) { max = 5000000; }
for (var i=0; i<max; i++) {
var r = rand5();
dist[r] = (dist[r] || 0) + 1;
}
return dist;
};
Now when I run testRand5() I get the following results (of course, differing slightly with each run, you might need to set "max" to a higher value to reveal the bug):
var d = testRand5();
d = {
1: 1002797,
2: 998803,
3: 999541,
4: 1000851,
5: 998007,
10: 1 // XXX: Math.random() returned 4.5?!
}
Interestingly, I see comparable results in node.js, leading me to believe it's not specific to Chrome. Sometimes there are different or multiple mystery values (7, 9, etc).
Can anyone explain why I might be getting the results I see? I'm guessing it has something to do with using parseInt (instead of Math.floor()) but I'm still not sure why it could happen.
The edge case occurs when you happen to generate a very small number, expressed with an exponent, like this for example 9.546056389808655e-8.
Combined with parseInt, which interprets the argument as a string, hell breaks loose. And as suggested before me, it can be solved using Math.floor.
Try it yourself with this piece of code:
var test = 9.546056389808655e-8;
console.log(test); // prints 9.546056389808655e-8
console.log(parseInt(test)); // prints 9 - oh noes!
console.log(Math.floor(test)) // prints 0 - this is better
Of course, it's a parseInt() gotcha. It converts its argument to a string first, and that can force scientific notation which will cause parseInt to do something like this:
var x = 0.000000004;
(x).toString(); // => "4e-9"
parseInt(x); // => 4
Silly me...
I would suggest changing your random number function to this:
var rand5 = function() {
return(Math.floor(Math.random() * 5) + 1);
};
This will reliably generate an integer value between 1 and 5 inclusive.
You can see your test function in action here: http://jsfiddle.net/jfriend00/FCzjF/.
In this case, parseInt isn't the best choice because it's going to convert your float to a string which can be a number of different formats (including scientific notation) and then try to parse an integer out of it. Much better to just operate on the float directly with Math.floor().

Categories