so I am doing a Jump game, you can see task here: Jump game
So I found a lot of solutions and they have no errors, but the thing that whenever i call a function, in webpage i see only blank page. I want to see just simple text "you won" or "you lost". What I did wrong here? Function is good, no errors. Maybe problem that i don't know how to call this function or numbers should be in array somehow? Here is my code:
<head>
<meta charset="utf-8" />
<title>Jump Game</title>
<style>
* {
padding: 0;
margin: 0;
}
canvas {
background: "#eee";
display: block;
margin: 0 auto;
border: 2px solid black;
}
</style>
</head>
<body>
<script>
var canJump = function(nums) {
if (nums.length < 2) {
return true;
}
for (let i = 0; i < nums.length - 1; i++) {
if (i + nums[i] >= nums.length - 1) {
return true;
};
if (nums[i] === 0) {
return false;
}
if (i + nums[i] > i + 1 + nums[i + 1]) {
nums[i + 1] = nums[i] - 1;
};
};
};
if(canJump(1,2,3,4) === true) {
document.write("you won");
}
else if(canJump(1,2,3,4) === false) {
document.write("you lost");
}
</script>
</body>
Please help me.
if(canJump(1,2,3,4) === true) ... should be if(canJump([1,2,3,4]) === true).
Related
When a player makes the correct guess, the error alert displays first then the success alert displays. I only want an error alert to display on an error and a success to display upon success.
I tried including the success alert in the if else statements.
The failure alert always runs. There's no if statement to prevent it.
Try this:
if(guessBoxes[guess-1] == "X"){
alert("GAME OVER - YOU FOUND IT! A WINNER");
} else {
alert("SORRY WRONG GUESS!; ");
}
Also, instead of that first if - else statement, just return false if they enter an invalid number. It eliminates the need for the large else statement and increases code readability:
function playGuessingGame() {
var guess = document.getElementById("numberToGuess").value;
var date = "";
if (isNaN(guess) || guess < 1 || guess > 9) {
alert("YOU CAN ONLY PLAY WITH NUMBERS 1-9 ");
return false;
}
var gemPosition = Math.floor(Math.random() * (9 - 1 + 1)) + 1;
var guessBoxes = ["O", "O", "O", "O", "O", "O", "O", "O", "O"];
guessBoxes[gemPosition - 1] = "X";
if (guess == 1) {
document.getElementById("guessBox1").innerHTML = guessBoxes[guess - 1];
} else if (guess == 2) {
document.getElementById("guessBox2").innerHTML = guessBoxes[guess - 1];
} else if (guess == 3) {
document.getElementById("guessBox3").innerHTML = guessBoxes[guess - 1];
} else if (guess == 4) {
document.getElementById("guessBox4").innerHTML = guessBoxes[guess - 1];
} else if (guess == 5) {
document.getElementById("guessBox5").innerHTML = guessBoxes[guess - 1];
} else if (guess == 6) {
document.getElementById("guessBox6").innerHTML = guessBoxes[guess - 1];
} else if (guess == 7) {
document.getElementById("guessBox7").innerHTML = guessBoxes[guess - 1];
} else if (guess == 8) {
document.getElementById("guessBox8").innerHTML = guessBoxes[guess - 1];
} else if (guess == 9) {
document.getElementById("guessBox9").innerHTML = guessBoxes[guess - 1];
}
if (guessBoxes[guess - 1] == "X") {
alert("GAME OVER - YOU FOUND IT! A WINNER");
} else {
alert("SORRY WRONG GUESS!; ");
}
document.getElementById("response").innerHTML;
}
Here is a working codepen with the changes:
https://codepen.io/ZorlacMeister/pen/wVJzKv
I've moved the gemPosition and guessBoxes variables outside of the function, since that function is called every time you click on the button. I also added the gameReset function.
Your code looks ridiculous, so I wrote something simple to help you understand:
var doc, bod, I, guessingGame; // for use on other loads
addEventListener('load', function(){
doc = document; bod = doc.body;
I = function(id){
return doc.getElementById(id);
}
guessingGame = function(guessInput, outputDiv, resetButton){
var g = Math.floor(Math.random()*10)+1;
guessInput.onchange = function(){
var s = this.value, n = +s, r;
if(!s.match(/^([1-9]|10)$/)){
r = 'Invalid Number';
}
else if(g === n){
r = 'You Win!';
}
else{
r = 'Guess Again';
}
outputDiv.innerHTML = r;
}
resetButton.onclick = function(){
g = Math.floor(Math.random()*10)+1; guessInput.value = outputDiv.innerHTML = '';
}
}
guessingGame(I('guess'), I('out'), I('reguess'));
}); // end load
/* css/external.css */
*{
box-sizing:border-box; padding:0; margin:0; border:none; outline:none;
}
html,body{
width:100%; height:100%;
}
body{
background:#ccc;
}
#content{
padding:7px;
}
lable{
display:inline-block;
}
#guess{
width:40px; font-size:14px; padding-left:3px; margin-left:4px;
}
input[type=button]{
padding:2px 5px;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1' />
<title>Test Template</title>
<link type='text/css' rel='stylesheet' href='css/external.css' />
<script type='text/javascript' src='js/external.js'></script>
</head>
<body>
<div id='content'>
<label for='guess'>Pick a number between 1 and 10</label><input id='guess' type='number' value='' min='0' max='10' maxlength='2' />
<input id='reguess' type='button' value='reset' />
<div id='out'></div>
</div>
</body>
</html>
I’m having trouble getting my snake to turn and not leave a trail. Every time my snake turns to go in a different direction it leaves behind pieces of itself. Each piece is a class of “hover” applied to a div block.
I created a function that I hoped would remove the excess pieces whenever a turn was made. My function removeExtra does remove the excess pieces on every turn (removeExtra is called from the moveSnake function each time an arrow is hit), but it also removes every piece of the snake when it turns. So every time I make a turn the snake starts over in that direction and then expands to its current size. A user could play and never run into any of the snake’s body pieces. If I don’t use this function though it leaves little snake turds all over the board!
Can someone help me fix my removeExtra function so that it only removes the class of hover that is not part of the snake body’s array? (var snake) In the removeExtra function I create an array of every hover class (every snake piece). I then use the length of this in the for loop. I have also tried using the difference between this array and the current snake array (var combo) as the second parameter of the for loop, but this doesn’t consistently clear the snake bits when I make turns.
I realize my code sucks. I’ve made this way more complicated than it should be. I should have used a canvas. But I’ve come this far, and I’m hoping there’s some way to salvage the game and never think about snakes again. If there really is no way to fix the mess I’ve made, just let me know, so that I can move on with my life. Thanks!
Here is the Codepen with the game.
Here is the function that's giving me trouble:
removeExtra = function(){
var array = [];
$(".hover").each(function() {
array.push($(this).attr("data"));
});
var len = array.length
var len2 = snake.length
var combo = len-len2
for (var i=0;i<len;i++){
$('*[data="' + array[i] + '"]').removeClass("hover");
}}
Since this is a work-in-progress (surprise!), just refresh the page if you don’t see any blue “food” pieces. Arrows keys will move the snake. You might have to click the board first.
//In the moveSnake function I had to use code from the below link in order to ignore multiple keydown events.
//https://stackoverflow.com/questions/9098901/how-to-disable-repetitive-keydown-in-jquery
$(document).ready(function() {
makebox();
addSnake();
moveSnake();
addBorder();
addFood();
killSnake();
addToSnake();
});
function makebox() {
var size = 30; //24
var boxSize = 20; //12
for (i = 1; i <= size * size; i++) {
$("#container").append("<div class='box'></div>");
};
$("#container").width(size * boxSize + "px");
$(".box").width(boxSize + "");
$(".box").height(boxSize + "px");
$(".box").each(function(i) {
$(this).attr('data', (i + 1));
});
};
function addBorder() {
//find all of the border divs and add a border class to them
$(".box").each(function() {
if ($(this).attr('data') % 25 == 0) {
$(this).addClass("right-border")
} else if ($(this).attr('data') % 25 == 1) {
$(this).addClass("left-border")
} else if ($(this).attr('data') < 25) {
$(this).addClass("top-border")
} else if ($(this).attr('data') >= 877) {
$(this).addClass("bottom-border")
}
})
}
function addSnake() {
var rightTime, leftTime, downTime, upTime;
moveRight = function() {
down = {}
rightTime = setInterval(function() {
for (var i = 0; i < snake.length; i++) {
snake[i]++
$('*[data="' + snake[i] + '"]').addClass("hover moving")
$('*[data="' + (snake[snake.length - 1] - snake.length) + '"]').removeClass("hover");
}
}, 150)
};
moveLeft = function() {
down = {}
leftTime = setInterval(function() { //snake -= 1
for (var i = 0; i < snake.length; i++) {
snake[i] -= 1
$('*[data="' + snake[i] + '"]').addClass("hover");
$('*[data="' + (snake[snake.length - 1] + snake.length) + '"]').removeClass("hover");
}
}, 150)
};
moveDown = function() {
down = {}
downTime = setInterval(function() { //snake += 25
for (var i = 0; i < snake.length; i++) {
snake[i] += 25
$('*[data="' + snake[i] + '"]').addClass("hover");
$('*[data="' + (snake[snake.length - 1] - 25 * snake.length) + '"]').removeClass("hover");
}
}, 150)
};
moveUp = function() {
down = {}
upTime = setInterval(function() { //snake -= 25
for (var i = 0; i < snake.length; i++) {
snake[i] -= 25
$('*[data="' + snake[i] + '"]').addClass("hover");
$('*[data="' + (snake[snake.length - 1] + 25 * snake.length) + '"]').removeClass("hover");
}
}, 150)
};
addTail = function() {
snake.push(snake[snake.length - 1])
}
var snake = [42]
$('*[data="' + snake[0] + '"]').addClass("hover");
var down = {};
removeExtra = function() {
var array = [];
$(".hover").each(function() {
array.unshift($(this).attr("data"));
});
var len = array.length
var len2 = snake.length
var combo = len - len2
for (var i = 0; i < len; i++) {
$('*[data="' + array[i] + '"]').removeClass("hover");
}
}
moveSnake = function() {
$(document).keydown(function(event) {
var keycode = (event.keyCode ? event.keyCode : event.which);
if (keycode == '39') {
if (down['39'] == null) {
window.clearInterval(leftTime);
window.clearInterval(downTime);
window.clearInterval(upTime);
moveRight();
removeExtra();
down['39'] = true;
}
} else if (keycode == '37') {
if (down['37'] == null) {
window.clearInterval(rightTime);
window.clearInterval(downTime);
window.clearInterval(upTime);
moveLeft();
removeExtra();
down['37'] = true;
}
} else if (keycode == '40') {
if (down['40'] == null) {
window.clearInterval(leftTime);
window.clearInterval(rightTime);
window.clearInterval(upTime);
moveDown();
removeExtra();
down['40'] = true;
}
} else if (keycode == '38') {
if (down['38'] == null) {
window.clearInterval(leftTime);
window.clearInterval(rightTime);
window.clearInterval(downTime);
moveUp();
removeExtra();
down['38'] = true;
}
}
});
addToSnake = function() {
var count = 0;
var config = {
attributes: true,
childList: true,
characterData: true
};
$(".box, .food").each(function() {
var target = this;
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if ($(".food").hasClass("hover") == true) {
$(".box").removeClass("food")
addTail();
addFood();
}
});
});
observer.observe(target, config);
});
}
killSnake = function() {
var config = {
attributes: true,
childList: true,
characterData: true,
subtree: true
};
$(".right-border, .left-border, .top-border, .bottom-border").each(function() {
var target = this;
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log("Game over!")
});
});
observer.observe(target, config);
});
}
}
addFood = function() {
var random = Math.floor(Math.random() * (900 - 1 + 1)) + 1;
$('*[data="' + random + '"]').addClass("food")
};
};
.box {
display: inline-block;
border: 2px grey solid;
}
#container {
display: block;
border: 2px black solid;
border-radius: 5px;
font-size: 0;
margin: 10px auto;
}
.hover {
background-color: black;
}
.food {
background-color: blue;
}
.white {
background-color: white;
}
.right-border,
.left-border,
.top-border,
.bottom-border {
background: red;
border: 2px red solid;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Snake</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="script.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<div class="container">
<center>
<h1>Snake</h1>
<div id="container"></div>
</center>
</div>
</body>
</html>
I'm making a small exercise for some students of mine where I am automating a kind of 10 pin bowling game I have put it into a JsBin here https://jsbin.com/qilizo/edit?html,js,output. I don't know whether I am tired, stupid or it's just because I am working on a national holiday but something has me puzzled. When i start the game I prompt the user to set up a number of desired players. This automatically produces an object array of Players like so:
[{score: Array[10], spareCount: 0, strikeCount: 0, username: "Player 1"}, ...]
Now later I allow the user to play frames where each Player in our array has two throws... I collect the score and add it to the certain player's score array. However when I try to perform this action using a .forEach method the score I generate is applied to all items in my Players array (play the game and see). I have put my code in a jsBin and the problem is on line 109 : a.score[currentFrame - 1] = playFrame();
I have tried to amend my code but I can't work out why the current (or last) frame score is being applied to all Player objects! If you can understand my syntax error and explain why I would be most appreciative. Play the game (just click the button after setting the player numbers) and you will see what I mean...
Snippet:
var players,
currentFrame = 0,
currentThrow = 0;
// helper functions
// Accurate isNumber function... Thank you Crockford (see JavaScript: The Good Parts)
function isNumber(value) {
return typeof(value === 'number') && isFinite(value);
}
function frameStyle(k) {
var returnCssClass,
k = k + 1;
if (k < currentFrame) {
returnCssClass = 'played-frame';
} else if (k === currentFrame) {
returnCssClass = 'current-frame';
} else {
returnCssClass = null;
}
return returnCssClass;
}
function setUpPlayers(num) {
var tempArray = [],
tempName = 'Player ',
emptyScores = Array(10).fill([-1, -1]); // set default to -1 as a rubbish player may hit no pins!
for (var i = 0; i < num; i++) {
tempArray.push({
username: tempName + (i + 1),
score: emptyScores,
strikeCount: 0,
spareCount: 0
}); // the way I have named the tempName is technically an antipattern!
}
return tempArray;
}
function getTotals(scores) {
var totalScore = scores.reduce(function(a, b) {
return a + b.reduce(function(c, d) {
return (c + (c + ((d > 0) ? d : 0)));
}, 0);
}, 0);
return totalScore;
}
function displayScore(score) {
// toDo reformat!
var formatScore = score.map(function(a, b) {
if (a === -1) {
a = '-';
} else if (a === 10) {
a = 'X';
}
return a;
});
return formatScore;
}
function createGrid() {
// If only I was using ES6 I could have multi line support!
var playerLen = players.length,
scoresLen = players[0].score.length;
boards = '<div class="score-board">' +
'<!-- one row for each player -->';
// need to loop this through the players...
for (var i = 0; i < playerLen; i++) {
boards += '<div class="row">' +
'<!-- first cell is the name -->' +
'<div class="name">' + players[i].username + '</div>';
// need to loop this with the users scores
for (var k = 0; k < scoresLen; k++) {
boards += '<div class="game ' + frameStyle(k) + ' ">' + displayScore(players[i].score[k]) + '</div>';
}
// don't forget the total
boards += '<div class="player-total">' + getTotals(players[i].score) + '</div>';
boards += '</div>';
}
boards += '</div>';
boards += '<div>Current Frame: ' + currentFrame + '</div>';
boards += '<button type="button" onclick="startGame()">Start Game</button>';
// fill the holder....
document.getElementById('boardHolder').innerHTML = boards;
}
function startGame() {
if (currentFrame >= 10) {
announceWinner();
} else {
currentFrame++;
// do the throws for Each Player!
players.forEach(function(a, b) {
a.score[currentFrame - 1] = playFrame();
});
// update the grid
createGrid();
// recurrrrrrsion....
//startGame();
}
}
function throwBall(pinsStanding) {
// i know it isn't a ball
return Math.floor(Math.random() * (pinsStanding + 1));
}
function playFrame() {
// here we just create the array and determine if we have a strike or a spare!
var pinsStanding = 10,
frameScore = [],
frameThrows = 2,
pinsDown;
for(var i = 0; i < frameThrows; i++) {
pinsDown = throwBall(pinsStanding);
pinsStanding = pinsStanding - pinsDown;
// if it is the pinsStanding = 0 and it is the first throw - a strike!
if(pinsStanding === 0 && i === 1) {
pinsStanding = 10;
frameThrows = 3;
}
// what if it is a spare?
frameScore.push(pinsDown);
}
return frameScore;
}
function announceWinner() {
}
// kick it all off!!!
window.onload = function() {
// lets get some users....
players = prompt('Please enter the NUMBER of players?', 2);
// check we have a number...
if (isNumber(players)) {
players = setUpPlayers(players);
createGrid();
}
};
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
/* classes */
.score-board {
border: 1px solid #000;
}
.row {
display: block;
border-bottom: 1px solid #000;
}
.row:last-child {
border-bottom: none;
}
.row > div {
display: inline-block;
padding: 5px;
}
.game {
border-right: 1px solid #000;
}
.name {
background-color: #f5f5f5;
border-right: 1px solid #000;
}
.player-total {
text-align: right;
background-color: #d5eabb;
}
.played-frame {
background-color: #aee1e8;
}
.current-frame {
background-color: #ffc0cb;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<h1>Let's go bowling!</h1>
<div id="boardHolder">
</div>
</body>
</html>
Here is the bin!
https://jsbin.com/qilizo/edit?html,js,output
You need to call Array(10).fill([-1, -1]) inside for loop, because otherwise all objects will share the same score array:
function setUpPlayers(num) {
var tempArray = [],
tempName = 'Player ';
for (var i = 0; i < num; i++) {
tempArray.push({
username: tempName + (i + 1),
score: Array(10).fill([-1, -1]),// set default to -1 as a rubbish player may hit no pins!
strikeCount: 0,
spareCount: 0
}); // the way I have named the tempName is technically an antipattern!
}
return tempArray;
}
https://jsbin.com/yeyupiteyu/1/edit?html,js,output
In JavaScript objects are passed by reference, and since array is an object, if you declare emptyScores outside the loop and then assign it to every element of the array, all elements will share the same score array.
You have make new emptyScores array for each element, so you have to declare it inside the loop:
var tempArray = [],
tempName = 'Player ';
for (var i = 0; i < num; i++) {
var emptyScores = Array(10).fill([-1, -1]);
tempArray.push({
username: tempName + (i + 1),
score: emptyScores,
strikeCount: 0,
spareCount: 0
});
}
I cannot figure out why if/else statements are not executing properly. The code only runs through the if(i===1) loop but thats it. I'm doing a simple exercise wherein I check the number submitted and see if the users gets hotter or colder to a preset number.
<html>
<head>
<title>Test</title>
<script src="jquery-1.11.0.min.js"></script>
<script>
$(document).ready(function () {
var checkNum = Math.floor(Math.random() * 10);
alert("Random number is" + checkNum);
var i = 0;
var scopedVal;
var submitVal;
var hotCheck = function (submitVal) {
if(i === 1) {
alert("try again");
scopedVal = submitVal;
alert("scopedVal is" + scopedVal);
} else {
if(abs(scopedVal - checkNum) > abs(submitVal - checkNum)) {
alert("Hotter");
scopedVal = submitVal;
} else {
alert("colder");
scopedVal = submitVal;
}
}
};
$('.subm').on('click', function () {
i++;
alert(" i is" + i);
alert("button pressed");
submitVal = $(this).closest('#outsideContainer').find('.num').val();
if(submitVal === checkNum) {
alert("You got it");
} else {
hotCheck(submitVal);
}
});
});
</script>
<style>
body {
width: 900px;
color: white;
margin: auto;
}
#outsideContainer {
width: 400px;
color: grey;
margin: auto;
position: relative;
}
</style>
</head>
<body>
<div id="outsideContainer">
<form>
<input type="text" name="text" class="num">
<br/>
</form>
<div id="buttonSubm">
<button class="subm">Submit</button>
<div></div>
</body>
</html>
I'm assuming this is a simple fix and it is driving me nuts.
If you want to run the "else" code as well as the "if" code remove the else statement:
var hotCheck = function(submitVal){
if(i===1){
console.log("try again");
scopedVal = submitVal;
console.log("scopedVal is " + scopedVal);
};
if(Math.abs(scopedVal-checkNum)> Math.abs(submitVal - checkNum)){
console.log("Hotter");
scopedVal = submitVal;
} else {
console.log("colder");
scopedVal = submitVal;
};
};
Demo:
http://jsfiddle.net/hHC88/
You also needed to change abs. to Math.abs
The abs() method does not exist. You're dealing with all integers so you can probably just remove it or fully reference it Math.abs()
You have to replace the
if( abs(scopedVal-checkNum)> abs(submitVal - checkNum)){
to
if( Math.abs(scopedVal-checkNum) > Math.abs(submitVal - checkNum)){
abs() is a method to Math.
Try this
i have tried it within the loop function but it says the function isn't being used so i put it outside still doesnt work and i dont know how to fix it as i thought that would work, rmember first day on javascript, thanks for the help in advance and please no jquery.
<html>
<head>
<style type="text/css">
#PictureContainer {
height: 300px;
width: 500px;
margin: 0 auto;
overflow: hidden;
display: inline-block;
}
#SliderWrapper {
width: 628px;
height: 300px;
margin: 0 auto;
overflow: hidden;
}
#image {
height: 300px;
width: 500px;
}
#Next {
float: right;
}
#Before {
float: left;
}
</style>
</head>
<body>
<div id="SliderWrapper">
<img id="Next" src="Forward.png" alt="Forward">
<img id="Before" src="Back.png" alt="Back">
<div id="PictureContainer">
<img id="image" src="html.png" alt="HTML">
</div>
</div>
<script language="javascript" type="text/javascript">
var i = 1;
function loop() {
i = i+1;
if(i == 5){
i = 1;
}
if (i == 1) {
document.getElementById('image').src = "html.png";
} else if(i == 2) {
document.getElementById('image').src = "css3.png";
} else if (i == 3) {
document.getElementById('image').src = "WebdevLogo's.jpg";
} else {
document.getElementById('image').src = "WebdevLogo's.jpg";
}
}
var pictureloop = setInterval(loop, 3000);
function Forward() {
if(i == 5) {
i = 1;
} else {
i = i+1;
}
}
function Back() {
if(i == 1) {
i = 4;
} else {
i = -1;
}
}
</script>
</body>
</html>
You have a function called loop, but you never call it, so it's never changing the source attribute of the image. In the forward and back functions, add a call to the loop function at the end. There are also a few problems internally with Back() that I've fixed.
function Forward() {
if(i == 5) {
i = 1;
} else {
i++;
}
loop();
}
function Back() {
if(i == 1) {
i = 5;
} else {
i--;
}
loop();
}
Within the loop() function, consider using a switch block instead of all those else ifs. Also in the loop function, use the increment operator - i++; - which increases the value by 1, rather than the manual statement i = i+1; Also, the if i==5 statement is redundant. You already have it in your Forward function.
this is more of a question for https://codereview.stackexchange.com/ but here are a few things that would make this code cleaner.
instead of duplicating image setting code, declare an array of images.
var images = ['img1.png','img2.png'];
var currentImage = 0;
function forward() {
currentImage++;
if (currentImage > images.length-1) currentImage == 0;
setImage()
}
function setImage() {
document.getElementById('image').src = images[currentImage];
}
setInterval(forward, 5000);