My code below is supposed to draw a picture of a rock on the canvas at random times. But the code I currently have doesn't draw anything even after many refreshes. I also could do with loop round the mathRock function so that I get constant new random rocks without having to refresh the page, but I don't know which loop to use.
My code for the rock spawn is below:
var num;
var rock = new Image();
rock.src = "rock.png";
mathRock();
spawnRock();
function mathRock() {
var x = parseInt(Math.random()* 10);
document.getElementById("num");
}
function spawnRock() {
if (num == 2|| num == 4 || num == 6 || num == 8){
context.drawImage(rock, 500, 450);
} else {
}
}
Your mathRock function is a no-op: It assigns to a local variable and does a DOM query, but it doesn't do anything with that local variable or the result of the DOM query.
spawnRock will only ever see undefined for num, as you've declared it but never assigned a value to it.
It might be that mathRock was meant to assign to num rather than x, but it's unclear what (if anything) it was meant to do with the DOM query, or where context in spawnRock is meant to come from.
The document.getElementById("num") will look for an element with id="num", it doesn't do anything with the global variable num.
To make that work, you would assign the value to the variable. For calculating the random number, use the Math.floor method rather than parsing the number to a number:
function mathRock() {
var x = Math.floor(Math.random() * 10);
num = x;
}
However, you should rather return the value than using a global varible, and pass the value into the next function.
You can't use a regular loop to repeatedly change the image, you need a timer. Use the setInterval method for that.
var rock = new Image();
rock.src = "rock.png";
window.setInterval(function(){
var num = mathRock();
spawnRock(num);
}, 5000);
function mathRock() {
return Math.floor(Math.random() * 10);
}
function spawnRock(num) {
if (num == 2|| num == 4 || num == 6 || num == 8){
context.drawImage(rock, 500, 450);
} else {
}
}
Related
I am trying to use Math.random to draw an image.
Though I know I haven't got it right.
I know I need a loop to go through the Math.random function, but don't know how to implement it. I also know I my spawnRock function isn't correct but do not know how to fix it. Any help?
This code also breaks my current drawImages.
var num;
function mathRock() {
var x = Math.floor((Math.random() * 10) + 1);
document.getElementById("num").innerHTML = x;
}
function spawnRock() {
if (num = 2, 4, 8){
context.drawImage(rock, 1500, 450);
} else {
}
var rock = new Image();
rock.src = "rock.png";
Here's a quick primer on Math.random
Math.random() * X will generate a random floating point number between zero up to (but not including) X. So Math.random*10 will generate, for example, 0.22, 1.56, 7.92 up to 9.9999999999.
If you need random integers, you can strip off the non-integer portion of the random number with parseInt( Math.random()*10 ) which will generate 0,1,2,3,4,5,6,7,8,9.
If you just want a random "coin-flip" (true or false) you can do that like this:
var randomTrueFalse=(Math.floor(Math.random()*2)==0);
If you need to do something randomly 3 out of 10 times then you can do that like this:
var thirtyPercentSuccess=( (Math.random()*10-7)>=0 );
Then use your desired version of the random number to choose whether to draw or do something else:
if (thirtyPercentSuccess){
context.drawImage(rock, 1500, 450);
}else{
// something else
}
mathRock is working fine, but I guess you should assing x to num variable: num = x then in spawnRock change the if condition to num == 2 || num == 4 || num==8 since == or === are used to compare and = to assign.
New Code:
var totalEval = function (attendanceAverage, assignmentAverage, quizAverage) {
return (quizAverage * .25 + assignmentAverage * .65 + attendanceAverage * .1 );
},
courseGrade = function (percent) {
if (percent >= .90 ){return "A";}
else if(percent >= .80){return "B";}
else if(percent >= .70){return "C";}
else if(percent >= .60){return "D";}
else {return "F";}
};
Call:
var projectedGrade = courseGrade(totalEval(attendanceAverage, assignmentAverage, quizAverage));
window.document.getElementById('currentGrade').innerHTML = projectedGrade;
Now it's not calling it correctly; I get no result at all.
Edit: After much talking about it and demonstrating the following code, here's my question in a nutshell: How do I take the numerical value in totalEval and use it to create the letter grade in courseGrade?
Edit: New code, still doing the same thing, but now drawing on the function that holds the numberical score I'm trying to work with. Still giving everyone F's:
var courseGrade = function(totalEval){
if (totalEval >= .90 ){return "A";}
else if(totalEval >= .80){return "B";}
else if(totalEval >= .70){return "C";}
else if(totalEval >= .60){return "D";}
else {return "F";}
};
Easy question, I'm very sure, but I can't seem to get it. For a simple program to take a numerical score and translate it into a letter grade, I have the following:
var courseGrade = function(percent){
if (percent >= .90 ){return "A";}
else if(percent >= .80){return "B";}
else if(percent >= .70){return "C";}
else if(percent >= .60){return "D";}
else {return "F";}
};
The issue is, how do I draw the previously determined result into this function? To clarify, if the function I've used to collect all assignment/test/etc grades into one total average is called "totalAverage", how does one take totalAverage and input whatever the result is inside this given function?
The code creating the totalSum from which I'm drawing the numerical score to become the letter grade, noting the weighted aspect of each element of the total:
var totalEval=function(attendanceAverage, assignmentAverage, quizAverage){
var totalSum = (quizAverage*.25 + assignmentAverage*.65 + attendanceAverage*.1 );
return totalSum;
};
Assuming you've a script like this:
var totalEval = function (attendanceAverage, assignmentAverage, quizAverage) {
return (quizAverage * .25 + assignmentAverage * .65 + attendanceAverage * .1 );
},
courseGrade = function (percent) {
if (percent >= .90 ){return "A";}
...
},
...;
Then, when you need to get a "courseGrade", you'll call the function calculating it like this:
var cG = courseGrade(totalEval(attendanceAverage, assignmentAverage, quizAverage));
In this function call, totalEval() is executed first, then the value it returns is passed to courseGrade(), and in that function percentage gets the value returned from totalEval().
Notice, that in the arguments of the function call of totalEval you need to use actual values, or alternatively names of some variables holding the values corresponding "attendanceAverage" etc.
In your question you have changed the name of the argument within the initiatation of the courseGrade(). The name of the argument in the initiatation is not important, arguments are getting their values when the function is invoked.
Okay, so I'm fairly new to programming. I've been learning to code for quite sometime now, but I hadn't really MADE anything. That considered, I'm attempting to make my first project using JavaScript and make a snake game. Unfortunately, I've ran into multiple problems, which obviously is something that comes hand in hand with programming, but I am new and I'm stuck. Can someone help me figure out if I'm coding this in an efficient way. Also, I have a more specific issue. I've added basic movement functionality to the head of my snake, but I can't figure out how to get the rest of it's parts to follow. If someone could explain to me how to do this, that would be incredible. I've worked about two weeks now to try and figure it out and I'm just stumped. I'm using Raphael's JavaScript Library to generate the graphics on an SVG canvas.
/*
Libraries in use:
1. Rapheal
2. jQuery
*/
// This variable is set to an array so that we can add multiple snakeParts to our PrimarySnake.
var snakeParts = [],
// This variable uses Raphael to generate a canvas.
snakeCanvas = Raphael(10, 10, 400, 400),
// This generates a rectangle that fills the canvas.
snakeCanvasBg = snakeCanvas.rect(0,0,400,400),
// This variable is set to an array so that we can use each and every direction that is pressed.
direction = [],
// This variable is set to an array so that we can use the turn coordinates of our first snake part.
turnCoords = [];
// Generates and returns a random number between 0 and 400. This function is used to help generate the goal of our snake at a random location on the canvas.
function getRandNum () {
var rand = Math.round(Math.random()*400);
// This while loop ensures that our snakeGoal never exceeds the coordinates x = 390 or y = 390. If it did, it's parts would be cut from the canvas.
while (rand > 395) {
rand = Math.round(Math.random()*400);
}
// This while loop ensures that our rand variabe will always be divisible by 10, which is used to make sure our snakeGoal and snakePart elements are always rendered in coordinates divisible by 10.
while (rand % 10 !== 0) {
var randString = rand.toString(),
// This variable stores the whole length of our randString variable.
randStringLength = randString.length,
// This variable stores the last number of our rand as a string character.
subtractionChar = randString.charAt(randStringLength - 1),
// This variable stores the last number of our rand as a integer.
subtractionInt = parseInt(subtractionChar),
// Finally, this line subtracts the last number of our rand from the entirety and then sets that value equal to rand, ensuring that rand is always divisible by 10.
rand = rand - subtractionInt;
}
return rand;
}
// This function is called any time a button is pressed. The jQuery which method allows our code to compare if the key pressed is equal to the keyCode of a designated key.
$(document).keydown(
function (pressedDirection) {
if (pressedDirection.which === 37) {
direction.push("left");
} else if (pressedDirection.which === 38) {
direction.push("up");
} else if (pressedDirection.which === 39) {
direction.push("right");
} else if (pressedDirection.which === 40) {
direction.push("down");
} else if (pressedDirection.which === 32) {
direction.push("stop");
}
if (pressedDirection.which === 37 || pressedDirection.which === 38 || pressedDirection.which === 39 || pressedDirection.which === 40 || pressedDirection.which === 32) {
console.log(direction[direction.length - 1]);
PrimarySnake.addTurnCoords();
PrimarySnake.movePeice();
}
// This prevents our screen from scrolling when an arrow key is
pressedDirection.preventDefault();
}
);
function Snake () {
// This method generates a new peice to the Snake.
this.addPart = function () {
console.log(snakeParts.length);
snakeParts[snakeParts.length] = snakeCanvas.rect(0,0,10,10);
snakeParts[snakeParts.length - 1].attr("fill", "blue");
snakeParts[snakeParts.length - 1].attr("stroke-width", ".25");
}
// This method provides the movement functionality of our Snake.
this.moveDirection = function () {
for (value in snakeParts) {
var currentCoord = [snakeParts[value].attr("x"), snakeParts[value].attr("y")];
// This if-else statement moves the snakePart at the -value- index up, down, left, or right according to the last direction pressed.
if (direction[direction.length - 1] === "up") {
snakeParts[value].attr("y", currentCoord[1] - 10);
} else if (direction[direction.length - 1] === "down") {
snakeParts[value].attr("y", currentCoord[1] + 10);
} else if (direction[direction.length - 1] === "left") {
snakeParts[value].attr("x", currentCoord[0] - 10);
} else if (direction[direction.length - 1] === "right") {
snakeParts[value].attr("x", currentCoord[0] + 10);
}
}
}
this.moveInterval;
// This function makes our moveDirection move our snakePeice every 50 milliseconds.
this.movePeice = function () {
var moveDirection = this.moveDirection;
// clearInterval is used to eliminate any interval previously running, ensuring that our peices only move one direction at a time.
clearInterval(this.moveInterval);
this.moveInterval = setInterval(function(){moveDirection()}, 50);
}
// This function adds an array of coordinates to the turnCoords array.
this.addTurnCoords = function () {
turnCoords.push([snakeParts[0].attr("x"), snakeParts[0].attr("y")]);
}
}
// This generates a new instance of our Snake class.
var PrimarySnake = new Snake();
// This generates a new part on the canvas.
PrimarySnake.addPart();
// This fills our snakeCanvasBg with a grey color, giving us a grey background.
snakeCanvasBg.attr("fill", "#CDCDCD");
Well, your code seems nice, or at least "efficient" as you are calling it.
To make the parts of your snake follow its head, you must iterate through its parts and assign each (n+1) piece the coordinates from (n). To do so, start with the last piece and iterate up to the first one, which movement is defined by the user, like in:
this.moveDirection = function () {
// Move every piece except the head.
for (var i = snakeParts.length - 1; i > 0; i--) {
snakeParts[i].attr("x", snakeParts[i-1].attr("x"));
snakeParts[i].attr("y", snakeParts[i-1].attr("y"));
}
// Now move the head.
if (direction[direction.length - 1] === "up") {
snakeParts[value].attr("y", currentCoord[1] - 10);
} else if (direction[direction.length - 1] === "down") {
snakeParts[value].attr("y", currentCoord[1] + 10);
} else if (direction[direction.length - 1] === "left") {
snakeParts[value].attr("x", currentCoord[0] - 10);
} else if (direction[direction.length - 1] === "right") {
snakeParts[value].attr("x", currentCoord[0] + 10);
}
}
That code may need a bit of work but that's the idea. Hope it helps!
I'm new to Javascript, and I'm trying to wrap my head around while loops. I understand their purpose, and I think I understand how they work, but I'm having trouble with them.
I want the while value to repeat itself until two random numbers match each other. Currently, the while loop only runs once, and I need to run it again if I want it to repeat itself.
How can I set this loop up so that it will automatically repeat the if statement until diceRollValue === compGuess? Thanks.
diceRollValue = Math.floor(Math.random()*7);
compGuess = Math.floor(Math.random()*7);
whileValue = true;
while (whileValue) {
if (diceRollValue === compGuess) {
console.log("Computer got it right!")
whileValue = false;
}
else {
console.log("Wrong. Value was "+diceRollValue);
whileValue = false;
}
}
That's because you're only executing the random number generator outside of the while. If you want two fresh numbers they need to be executed within the while statement. Something like the following:
var diceRollValue = Math.floor(Math.random() * 7),
compGuess = Math.floor(Math.random() * 7),
whileValue = true;
while (whileValue){
if (diceRollValue == compGuess){
console.log('Computer got it right!');
whileValue = false; // exit while
} else {
console.log('Wrong. Value was ' + diceRollValue);
diceRollValue = Math.floor(Math.random() * 7); // Grab new number
//whileValue = true; // no need for this; as long as it's true
// we're still within the while statement
}
}
If you wanted to refactor it, you can use break to quit the loop (instead of using a variable) as well:
var diceRollValue = Math.floor(Math.random() * 7),
compGuess = Math.floor(Math.random() * 7);
while (true){
if (diceRollValue == compGuess){
// breaking now prevents the code below from executing
// which is why the "success" message can reside outside of the loop.
break;
}
compGuess = Math.floor(Math.random() * 7);
console.log('Wrong. Value was ' + diceRollValue);
}
console.log('Computer got it right!');
You have two problems, the first is that you are setting whileValue in both the if and the else blocks so the loop will break after one iteration regardless of the values of the random numbers.
Secondly you're generating the guess before the loop so you'd be checking the same values over and over.
So remove whileValue assignment in the else block and move the compGuess assignment into the while loop.
Put the 2 random variables inside the loop.
whileValue = true;
while (whileValue) {
diceRollValue = Math.floor(Math.random()*7);
compGuess = Math.floor(Math.random()*7);
if (diceRollValue === compGuess) {
console.log("Computer got it right!")
whileValue = false;
}
else {
console.log("Wrong. Value was "+diceRollValue);
}
}
I'm creating a slider with 6 slides, and I want to randomly move between them, making sure that neither of the previous two slides are shown as the next slide. The functionality doesn't really matter, since what I'm really doing is generating random numbers and keeping track of the previous two. The first slide is always numbered 1, so for the first two iterations that'll be one of the previous numbers that can't be used.
Here's what I have so far, and it works fine for generating the random numbers in the range, but 'caching' the last two values doesn't work reliably:
var rand = Math.floor(Math.random() * 6) + 1;
var prev1 = 1;
var prev2;
function randomSlide() {
// 5 second interval between slides
// Don't show either of previous two slides next
random = setInterval(function() {
prev2 = prev1;
prev1 = rand;
do {
rand = Math.floor(Math.random() * 6) + 1;
} while (rand == prev1 || rand == prev2);
prev1 = rand;
$('#slider').anythingSlider(rand);
//console.log(prev1,prev2);
}, 5000);
}
function firstSlide() {
firstTime = setTimeout(function() {
randomSlide();
}, 5000);
}
firstSlide();
randomSlide();
It's quite simple I think but my brain's getting frazzled trying to parse the values of the two 'cache' variables at the first, and then each subsequent, iteration.
I'm executing a single iteration at the beginning because if randomSlide() executes on load then the first (welcome) slide doesn't get a chance to display.
When you do the prev1 = rand the second time after you've changed the value of rand, you're assigning the new slide's number to it. The next time you enter the loop you do prev2 = prev1, and since prev1 == rand it means that now all three variables prev1, prev2 and rand are the same. Just remove the second prev1 = rand.
Another issue is that you set the interval twice: first you call firstSlide() which executes randomSlide() after a 5 second delay (which sets one interval), then right after you call randomSlide() again which sets another interval.
Here's another (simpler?) approach to getting the result:
<script>
// Return a random number from 1 to 6, exclude
// the last two numbers.
var getRandom = (function() {
var a = [1,2,3,4,5,6];
return function() {
var i = (Math.random() * 4 ) | 0;
a[5] = a.splice(i,1);
return a[5];
}
}());
function writeRandom() {
document.getElementById('d0').innerHTML += getRandom() + '<br>';
}
setInterval(writeRandom, 100)
</script>
<div id="d0"></div>
Not exactly random for the first 2 iterations, but you can fix that by randomising the array when it's initialised. But likely it doesn't matter for a slide show.
It's less code, but the splice part makes it slower in the browsers I tested. My version of the OP is:
var getRandom2 = (function() {
var r0 = r1 = r2 = 1;
return function() {
r0 = r1;
r1 = r2;
do {
r2 = Math.floor(Math.random() * 6) + 1;
} while (r2 == r0 || r2 == r1);
return r1;
}
}());