I coded quite rough code but it works, but I though I should learn better way to do it next time, so I need help to get this code more proper.
The purpose of this code is image slider.
Image of the slider
I would like to have animation from right to left when the button is pressed, but I'm kinda out of ideas how to do it. There's total 4 images on the slider. It will only show 3 at a time, and it will rotate them on proper order, but I haven't figured how to add animation that would hide the first image as the rest images "appear" from the right side.
Javascript
function rullaaVasen(j) {
var divit = $("#portfolio").find("div").toArray();
//a , b, c - using them to switch classes which have different background images
if(j == 1) {
a = 2;
b = 3;
c = 4;
i = 2;
v = 4;
} else if(j == 2) {
a = 3;
b = 4;
c = 1;
i = 3;
v = 3;
} else if(j == 3) {
a = 4;
b = 1;
c = 2;
i = 4;
v = 2;
} else if(j == 4) {
a = 1;
b = 2;
c = 3;
i = 1;
v = 1;
}
$(divit[0]).attr("class","sivu1 kuva" + a);
$(divit[1]).attr("class","sivu2 kuva" + b);
$(divit[2]).attr("class","sivu3 kuva" + c);
$("#vasenNappi").attr('onClick', 'rullaaVasen('+i+');');
$("#oikeaNappi").attr('onClick', 'rullaaOikea('+v+');');
}
Html
<div id="slideri">
<div id="vasenNappi" onClick="rullaaVasen(1);"></div>
<div id="portfolio">
<div class="sivu1 kuva1"></div>
<div class="sivu2 kuva2"></div>
<div class="sivu3 kuva3"></div>
</div>
<div id="oikeaNappi" onClick="rullaaOikea(1);"></div>
Thanks in advance for any answers!
Try this code.
//increment a based on j. Since 5 is the limit if a is 5 it is reset to 1.
a = (j+1)==5?1:(j+1);
//increment b based on a. Since 5 is the limit if b is 5 it is reset to 1.
b = (a+1)==5?1:(a+1);
//increment c based on b. Since 5 is the limit if c is 5 it is reset to 1.
c = (b+1)==5?1:(b+1);
//i is same as a.
i = a;
//v is based on j
v = 5-j;
From what I understand from your code is that you were doing a change of variables a, b, c, i and v within 1-5 based on value of j.
here is a js fiddle http://jsfiddle.net/7HX2C/1/ of a "slider".
also pasted the jsfiddle below.
//usage
var slider = new slider();
slider.slide(0); //slides to index 0 and shows 1,2,3 of 1,2,3,4
slider.next(); //goes to index 1 and shows 2,3,4 of 1,2,3,4 one more would show 3,4,1
slider.prev(); //goes back to index 0 and shows 1,2,3 of 1,2,3,4 one more would show 4,1,2
//slider
function slider() {
var self = this;
self.div = $("div");
self.items = [1, 2, 3, 4]; //an array of the items to slide
self.currentIndex = 0; //which one you are currently looking at
self.displayAmount = 3; //how many items to display
self.currentItems = []; //an array of the items to show out of items array
self.slide = function (j) {
self.currentItems = [];
self.currentIndex = j;
//start looping from current index, loop as long as i is less than the items we have and current items to show is less than the display amount
for (var i = self.currentIndex; i < self.items.length && self.currentItems.length < self.displayAmount; i++) {
self.currentItems.push(self.items[i]);
}
//if current items isn't hitting our display amount
if (self.currentItems.length < self.displayAmount) {
//calculate how many we need to add
var amountToAdd = self.displayAmount - self.currentItems.length;
//loop through starting from 0 and add the amount missing as long as current items never gets longer than the items we have
for (var i = 0; i < amountToAdd && self.currentItems.length < self.items.length; i++) {
self.currentItems.push(self.items[i]);
}
}
};
self.next = function () {
var slideTo = self.currentIndex + 1;
if (slideTo > self.items.length) {
slideTo = 0;
}
self.slide(slideTo);
};
self.prev = function () {
var slideTo = self.currentIndex - 1;
if (slideTo < 0) {
slideTo = self.items.length - 1;
}
self.slide(slideTo);
};
self.showInfo = function() {
self.div.html(self.currentItems.toString() + " of " + self.items.toString() + " is displayed");
}
}
Related
I use Quick Union algorithm to find if one of the first 5 sites are connected with one of the last 5 sites.
The first five sites have the same root, it's a penultimate array element. The last five sites have the same root as well. It's the last array element.
for (let i = 0; i < 5; i++) {
this.union(i,this.array.length-2);
}
for (let j = this.array.length-this.number-2; j < this.array.length-2; j++) {
this.union(j,this.array.length-1);
}
I need to paint a path like this
My code for highlighting the sites is:
let id = this.array[this.array.length-2]
for (let i = 0; i < this.array.length-2; i++) {
if(this.connected(i,id) && $("#result td").eq(i).hasClass('opened')){
$("#result td").eq(i).css({'background':'blue'});
}
}
It results:
But It's not right that 2 left sites are highlighted.
What Algorithm should i use to highlight only right path?
Connected method:
connected(p, q){
return this.root(p) === this.root(q);
}
Root method
root(index){
while(this.array[index] !== index) index = this.array[index];
return index;
}
Looks like you just want a basic Fill algorithm, but with 2 caveats. 1) You only want it to fill downwards as if water was flowing 2) you want the Fill() to be called on every empty space in the first (top) row, as if water was being poured accross the top.
var EMPTY = 0; // empty unfilled spot
var SOLID = 1; // solid spot
var FILLED = 2; // filled spot
var ROWS = 5; // # of rows of data indexed 0 to 4
var COLS = 5; // # of columns of data indexed 0 to 4
var data = [
[1,0,0,1,1],
[1,1,0,1,1],
[0,1,0,0,1],
[0,1,1,0,1],
[0,1,1,0,1]
]; // data that matches the example
// check if a location is EMPTY
function isEmpty(grid, rowIndex, colIndex) {
// valid row and col?
if(rowIndex < 0 || rowIndex >= ROWS || colIndex < 0 || colIndex >= COLS) {
return false;
}
// SOLID or FILLED already?
if(grid[rowIndex][colIndex] !== EMPTY) {
return false;
}
return true;
}
// replace EMPTY locations with FILLED locations
function fillDown(grid, startRow, startCol) {
if(false === isEmpty(grid, startRow, startCol)) {
return;
}
var nextLocation = [[startRow, startCol]]; // list of locations to process
while(nextLocation.length > 0) { // loop
var loc = nextLocation.pop();
var r = loc[0]; // row index
var c = loc[1]; // column index
// fill the empty location
grid[r][c] = FILLED;
// try to fill the locations to the LEFT, RIGHT and DOWN from the current location
if(isEmpty(grid, r, c - 1)) { // left
nextLocation.push([r, c - 1]);
}
if(isEmpty(grid, r, c + 1)) { // right
nextLocation.push([r, c + 1]);
}
if(isEmpty(grid, r + 1, c)) { // down
nextLocation.push([r + 1, c]);
}
}
}
// call fillDown() for the first row of the data (water pouring accross the top)
for(var c = 0; c < COLS; c++) {
fillDown(data, 0, c);
}
// show the result
alert(data.join('\n'));
Extra note, row and column indexes for a 2d array can be converted to a 1d array index by the formula: index = (r * COLS) + c, so the last location in the data row = 4, col = 4 would be 4 * 5 + 4 == 24, the index for the last location in a 1d array.
This is the first time I've written anything beyond a few simple lines in javascript. I know similar questions have been asked before because I've looked at a lot of them. I still can't seem to figure out what I'm doing wrong though. I am attempting to make a blackjack game simulation. I've almost got it except I keep running into problems when I need to change the value of an ace from 11 to 1. When I need to change the value of an ace from 11 to 1, it seems to only display the last player's results. Here's the script in it's entirety:
function cardShuffle(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function add(a, b) {
return a + b;
}
function contains(arr, obj) {
var i = 0;
for (;i < arr.length;i++) {
if (arr[i] === obj) {
return true;
}
}
return false;
}
function blackjack() {
var spades = "\u2660";
var clubs = "\u2663";
var hearts = "\u2665";
var diamonds = "\u2666";
var dealer = "Dealer";
var player = "Player";
var table = [player, dealer];
var suits = [hearts, clubs, diamonds, spades];
var deck = [];
// create a deck of cards
x = 0;
for (;x < suits.length; x++) {
var cards = ["A", 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K"];
i = 0;
for (;i < cards.length; i++) {
deck.push(cards[i] + suits[x]);
}
}
i = 0;
for (;i < table.length; i++) {
var players = table[i];
var cardsToDeal = 1;
var cardsHeld = [];
var sum = [];
aces = [];
var result;
for (;0 < cardsToDeal;) {
// get a random card from the deck
var index = cardShuffle(0, deck.length - 1);
var card = deck[index];
// give the card to the player
cardsHeld.push(card);
// remove the card from the deck
deck.splice(index, 1);
// strip the suit from the card and get the value
var value = card.substring(0, card.length - 1);
if (value == "J" || (value == "Q" || value == "K")) {
value = 10;
} else {
if (value == "A") {
value = 11;
// put aces into a separate array
aces.push(value);
} else {
value = Number(value);
}
}
// put the value of the card into the sum array
sum.push(value);
// store the sum of the value in the total variable
var total = sum.reduce(add, 0);
/*
This is where I think the problem is.
It works if the last player's hand is greater than 21 and contains an ace.
But if the first players hand has an ace and is greater than 21
only those result are shown in console.log. I don't know why.
*/
if (total > 21 && contains(sum, 11)) {
var i = sum.indexOf(11);
if (i !== -1) {
sum[i] = 1;
}
total = sum.reduce(add, 0);
}
if (total >= 17 && total <= 21) {
result = Number(total);
}
if (total >= 17) {
cardsToDeal--;
}
}
console.log(players, cardsHeld, sum, total);
}
}
blackjack();
On this line:
for (;i < table.length; i++) {
... you use a variable i for a loop. But inside this loop, you redefine that variable, and change its value:
var i = sum.indexOf(11);
which results in this kind of behavior:
If you just change that variable's name to something else, it seems to work fine:
if (total > 21 && contains(sum, 11)) {
var index = sum.indexOf(11);
if (index !== -1) {
sum[index] = 1;
}
total = sum.reduce(add, 0);
}
Be careful about variable scopes when using the var keyword, they are not limited to blocks -unlike let- but to functions (and be sure to add a var in front of the first definition, to avoid making it global). Also, just a piece of advice. for loops are generally used when you know how many iterations you're going to do. This:
for (;0 < cardsToDeal;) { /*...*/ }
would be better with a while loop.
When you check for Aces, you declare i again. This changes the value of i in your table loop. Change the the second var i to var ii and you should be good. To better understand this, you can look up more about Javascript scope.
if (total > 21 && contains(sum, 11)) {
var ii = sum.indexOf(11); // This is what changed
if (ii !== -1) {
sum[ii] = 1;
}
total = sum.reduce(add, 0);
}
I need to split a number to number of sections
I want number of sections, between each consecutive numbers in each section the number of the sections
For example
If the given number is 20 and the number of sections is 3
then need to split numbers 1 to 20 into three sections.
So the result will be
section 1 = [1,4,7,10,13,16,19] // between any
section 2 = [2,5,8,11,14,17,20]
section 3 = [3,6,9,12,15,18]
I'm using javascript to do this.... any idea
Sorry for my bad English
You could use two nested for loops and count the sections and the value to max.
function getSection(sections, max) {
var value, result = [], i;
for (i = 1; i <= sections; i++) {
result.push([]);
for (value = i; value <= max; value += sections) {
result[i - 1].push(value);
}
}
return result;
}
console.log(getSection(3, 20));
Something like that:
function get_s(s_cnt, w_num) {
var a = new Array(s_cnt), b = Math.ceil(w_num/s_cnt), c = w_num;
for (var i=0; i<s_cnt; i++) {
var b_ = (b < c) ? b : c; c -= b;
a[i] = new Array(b_);
for (var j=0; j<b_; j++) {
a[i][j] = j*s_cnt + i + 1;
}
}
return a;
}
var s = get_s(3,20);
for (var i=0; i<3; i++) console.log("section "+(i+1)+": "+s[i].join(", "));
I'm trying to create a simple memory matching game and I'm having trouble assigning one number to each table cell from my cardValues array. My giveCellValue function is supposed to generate a random number then pick that number from the array and give it to one of the table cells but I'm a little over my head on this one and having trouble accomplishing this task.
var countCells;
var cardValues = [];
var checker = true;
var createTable = function (col, row) {
$('table').empty();
for (i = 1; i <= col; i++) {
$('table').append($('<tr>'));
}
for (j = 1; j <= row; j++) {
$('tr').append($('<td>'));
}
countCells = row * col;
};
createTable(3, 6);
for (i = 1; i <= countCells / 2; i++) {
cardValues.push(i);
if (i === countCells / 2 && checker) {
checker = false;
i = 0;
}
}
var giveCellValue = function () {
var random = Math.ceil(Math.random() * cardValues.length) - 1;
for (i = 0; i <= cardValues.length; i++) {
$('td').append(cardValues[random]);
cardValues.splice(random, 1);
}
};
giveCellValue();
console.log(cardValues);
Use
var countCells;
var cardValues = [];
var checker = true;
var createTable = function (col, row) {
$('table').empty();
for (var i = 0; i < col; i++) {
$('table').append($('<tr>'));
}
for (var j = 0; j < row; j++) {
$('tr').append($('<td>'));
}
countCells = row * col;
};
createTable(3, 6);
for (i = 0; i < countCells; i++) {
cardValues.push(i % 9 + 1);
}
var giveCellValue = function () {
var len = cardValues.length, tds = $('td');
for (var i = 0; i < len; i++) {
var random = Math.floor(Math.random() * cardValues.length);
tds.eq(i).append(cardValues.splice(random, 1));
}
};
giveCellValue();
console.log(cardValues);
Demo: Fiddle
Leaving aside the problems that have already been mentioned in the comments above...
If I understand it right, you want to assign each of the numbers in cardValues to a random table cell?
Seems like the problem is with this line:
var random = Math.ceil(Math.random() * cardValues.length) - 1;
What this does is generates a random number once. If you access the variable random at a later time, you're not calling the full line of code again, you're just getting the same value that was calculated the first time. E.g. if the above code runs, spits out '7' as its random number and stores that in random, then every time you go through the for loop, the value of random will always be '7' rather than being re-generated every time - make sense?
Try putting the randomiser inside the for loop - that way it will be run multiple times, generating a new random number every time:
var giveCellValue = function () {
var random;
for (i = 0; i <= cardValues.length; i++) {
random = Math.ceil(Math.random() * cardValues.length) - 1;
$('td').append(cardValues[random]);
cardValues.splice(random, 1);
}
};
Actually, I'd change line 4 above to random = Math.floor(Math.random() * cardValues.length); too which should have the same effect.
How do I generate objects on a map, without them occupying the same space or overlapping on a HTML5 Canvas?
X coordinate is randomly generated, to an extent. I thought checking inside the array to see if it's there already, and the next 20 values after that (to account for the width), with no luck.
var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
var positiony = 0, type;
for (var i = 0; i < nrOfPlatforms; i++) {
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
var positionx = (Math.random() * 4000) + 500 - (points/100);
var duplicatetest = 21;
for (var d = 0; d < duplicatetest; d++) {
var duplicate = $(jQuery.inArray((positionx + d), platforms));
if (duplicate > 0) {
var duplicateconfirmed = true;
}
}
if (duplicateconfirmed) {
var positionx = positionx + 20;
}
var duplicateconfirmed = false;
platforms[i] = new Platform(positionx,positiony,type);
}
}();
I originally made a cheat fix by having them generate in an area roughly 4000 big, decreasing the odds, but I want to increase the difficulty as the game progresses, by making them appear more together, to make it harder. But then they overlap.
In crude picture form, I want this
....[]....[].....[]..[]..[][]...
not this
......[]...[[]]...[[]]....[]....
I hope that makes sense.
For reference, here is the code before the array check and difficulty, just the cheap distance hack.
var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
var position = 0, type;
for (var i = 0; i < nrOfPlatforms; i++) {
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
platforms[i] = new Platform((Math.random() * 4000) + 500,position,type);
}
}();
EDIT 1
after some debugging, duplicate is returning as [object Object] instead of the index number, not sure why though
EDIT 2
the problem is the objects are in the array platforms, and x is in the array object, so how can I search inside again ? , that's why it was failing before.
Thanks to firebug and console.log(platforms);
platforms = [Object { image=img, x=1128, y=260, more...}, Object { image=img, x=1640, y=260, more...} etc
You could implement a while loop that tries to insert an object and silently fails if it collides. Then add a counter and exit the while loop after a desired number of successful objects have been placed. If the objects are close together this loop might run longer so you might also want to give it a maximum life span. Or you could implement a 'is it even possible to place z objects on a map of x and y' to prevent it from running forever.
Here is an example of this (demo):
//Fill an array with 20x20 points at random locations without overlap
var platforms = [],
platformSize = 20,
platformWidth = 200,
platformHeight = 200;
function generatePlatforms(k) {
var placed = 0,
maxAttempts = k*10;
while(placed < k && maxAttempts > 0) {
var x = Math.floor(Math.random()*platformWidth),
y = Math.floor(Math.random()*platformHeight),
available = true;
for(var point in platforms) {
if(Math.abs(point.x-x) < platformSize && Math.abs(point.y-y) < platformSize) {
available = false;
break;
}
}
if(available) {
platforms.push({
x: x,
y: y
});
placed += 1;
}
maxAttempts -= 1;
}
}
generatePlatforms(14);
console.log(platforms);
Here's how you would implement a grid-snapped hash: http://jsfiddle.net/tqFuy/1/
var can = document.getElementById("can"),
ctx = can.getContext('2d'),
wid = can.width,
hei = can.height,
numPlatforms = 14,
platWid = 20,
platHei = 20,
platforms = [],
hash = {};
for(var i = 0; i < numPlatforms; i++){
// get x/y values snapped to platform width/height increments
var posX = Math.floor(Math.random()*(wid-platWid)/platWid)*platWid,
posY = Math.floor(Math.random()*(hei-platHei)/platHei)*platHei;
while (hash[posX + 'x' + posY]){
posX = Math.floor(Math.random()*wid/platWid)*platWid;
posY = Math.floor(Math.random()*hei/platHei)*platHei;
}
hash[posX + 'x' + posY] = 1;
platforms.push(new Platform(/* your arguments */));
}
Note that I'm concatenating the x and y values and using that as the hash key. This is to simplify the check, and is only a feasible solution because we are snapping the x/y coordinates to specific increments. The collision check would be more complicated if we weren't snapping.
For large sets (seems unlikely from your criteria), it'd probably be better to use an exclusion method: Generate an array of all possible positions, then for each "platform", pick an item from the array at random, then remove it from the array. This is similar to how you might go about shuffling a deck of cards.
Edit — One thing to note is that numPlatforms <= (wid*hei)/(platWid*platHei) must evaluate to true, otherwise the while loop will never end.
I found the answer on another question ( Searching for objects in JavaScript arrays ) using this bit of code to search the objects in the array
function search(array, value){
var j, k;
for (j = 0; j < array.length; j++) {
for (k in array[j]) {
if (array[j][k] === value) return j;
}
}
}
I also ended up rewriting a bunch of the code to speed it up elsewhere and recycle platforms better.
it works, but downside is I have fewer platforms, as it really starts to slow down. In the end this is what I wanted, but its no longer feasible to do it this way.
var platforms = new Array();
var nrOfPlatforms = 7;
platformWidth = 20,
platformHeight = 20;
var positionx = 0;
var positiony = 0;
var arrayneedle = 0;
var duplicatetest = 21;
function search(array, value){
var j, k;
for (j = 0; j < array.length; j++) {
for (k in array[j]) {
if (array[j][k] === value) return j;
}
}
}
function generatePlatforms(ind){
roughx = Math.round((Math.random() * 2000) + 500);
type = ~~(Math.random()*5);
if (type == 0) type = 1;
else type = 0;
var duplicate = false;
for (var d = 0; d < duplicatetest; d++) {
arrayneedle = roughx + d;
var result = search(platforms, arrayneedle);
if (result >= 0) {
duplicate = true;
}
}
if (duplicate = true) {
positionx = roughx + 20;
}
if (duplicate = false) {
positionx = roughx;
}
platforms[ind] = new Platform(positionx,positiony,type);
}
var generatedplatforms = function(){
for (var i = 0; i < nrOfPlatforms; i++) {
generatePlatforms(i);
};
}();
you go big data, generate all possibilities, store each in an array, shuffle the array,
trim the first X items, this is your non heuristic algorithm.