setAttribute() in a multi dimensional array - javascript

What I'm trying to figure out is how to give another class to certain div's in a two-dimensional array that has a value of "3" . This is what I tried at first.
numRows are the amount rows in the array.
numSeatsPerRow are the number of array items in every "numRows".
r and t are the positions in the two-dimensional array.
for(var r = 0; r<numRows; r++){
for(var t = 0; t<numSeatsPerRow; t++){
if(myArray[r][t] === 3){
document.getElementsByTagName("div")[r][t].setAttribute("class", "busySpot");
}
}
}
I soon understood that this wouldn't work. I tried to make a formula which could calculate every position as an ordinary array but couldn't make it work. Is there any other way to solve my problem?
In the code below I create a two-dimensional array based on two different inputs
var myArray = new Array(numRows);
for(var i = 0; i <numRows; i++){
myArray[i] = new Array(numSeatsPerRow);
}
In the next piece of code I give all array items the value 1 and then draw a green box for every item.
for(var h = 0; h<numRows; h++){
document.body.appendChild(//efter varje rad sker ett <br> i utskriften
document.createElement("br"));
document.body.appendChild(
document.createElement("br"));
for(var g = 0; g<numSeatsPerRow; g++){
myArray[h][g] = 1
var vSpot = document.createElement("div");
vSpot.className = "vacantSpot";
document.body.appendChild(vSpot);
}
}
What I'm trying to do in the top code is give the random boxes that I talked about another class.
this is how i came up with the random coordinates:
for(var v = 0; v < 15; v++){
var test = true;
while(test){
var x = Math.floor((Math.random() * numSeatsPerRow) + 0 );
var y = Math.floor((Math.random() * numRows) + 0);
if(myArray[x][y] === 1) {
myArray[x][y] = 3;
test = false;
}
}
}
Thanks!

Related

How to find all possible combinations of triplets equaling a given sum in JavaScript? ('Stars and Bars' or 'Balls and Bins' problem)

I found a similar post on StackOverflow that answers the question but in Python, and I'm looking for a solution for javascript (google script editor for a google sheet).
Balls and Bins problem
How can I solve this using JavaScript?
Figured it out using nested for loops. How to output arrays of all triples which equal to sum (numSum) by interval.
The reason I used an internal is because I am using much bigger numbers to calculate these for monetary loans, so the interval lets me calculate by $100 chunk instead of each dollar of a huge sum.
function calcSum(SUM, INTERVAL) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getSheetByName('Data');
var sumNum = SUM/INTERVAL
var a = 0
var b = 0
var c = sumNum
var aTicker = 0
var bTicker = sumNum
var cTicker = sumNum
//Loop through all triple combinations of sumNum
for (i = 0; i < sumNum + 1; i++) {
for (j = aTicker; j < sumNum + 1; j++) {
var array = [];
array.push(a * INTERVAL, b * INTERVAL, c * INTERVAL);
dataSheet.getRange("A" + rowCounter + ":D" + rowCounter).setValues([array]);
rowCounter++;
}
if (b < bTicker) {
b++;
} else {
b = 0;
bTicker--;
}
if (c > 0){
c--;
} else {
cTicker--;
c = cTicker;
}
}
a++;
aTicker++;
}
}

Why is my code executing far more times than it's supposed to?

I'm currently working on a poker odds generator and it's pretty much done, except for one thing. The program runs far more often than it should. I know that this is coming from the compare() function, because when I add a variable Q to keep track of the number of times the main function playPoker() has run, it produces a huge number until I comment it out - at which point it returns the exact number I'd expect.
Can any of you point out where I'm going wrong with this. I can't see why one function should lead to Q being incremented so much more than it should be. Literally, the last time I ran it the number was (32,487 instead of 100). I present the code below (without the poker hand-checking functions because they're not really important). Why is playPoker() running so many times?!
var Q = 0;
function playPoker(tableSize) {
//Create the players, the deck and the card table which stores the 5 cards the players have in common
var players = createPlayers(tableSize);
var deck = createDeck();
var cardTable = new CardTable();
//Deal each player two cards
for (i = 0; i < 2; i++) {
for (j = 0; j < players.length; j++) {
deal(deck, players[j]);
}
}
//Put five cards down on the table
for (k = 0; k < 5; k++) {
deal(deck, cardTable);
}
//Check for various winning hands here for each player
for (m = 0; m < players.length; m++) {
//Merge the player's two cards with the five cards on the table
var subjectCards = (players[m].cards).concat(cardTable.cards);
//Make an array of the values of each of the seven cards, which will be used to determine 4 of a kind, 3 of a kind and pairs
var valuesInOrder = getValuesInOrder(subjectCards);
//Create a dummy array, so that valuesInOrder remains unchanged
var straightValues = valuesInOrder.slice();
//Remove any duplicate card, meaning that the array contains only unique values (i.e. 2, 4, 5, 7, K ... NOT 2, 2, 2, 8, K, K, A)
var straightValues = straightenUp(straightValues);
//Calculate how many pairs are in the hand
var numPairs = howManyPairs(valuesInOrder, straightValues, players[m]);
//Find out whether the 5 table cards contain three cards of the same suit. If not, then a flush is impossible.
var flushPotential = threeSameSuit(cardTable.cards);
//Find out which hand each player has (i.e. straight, 3OAK, pair)
checkPokerHand(subjectCards, straightValues, valuesInOrder, flushPotential, numPairs, players[m])
}
var rankedPlayers = compare(players);
//return players;
Q++;
return Q;
}
And here's the for-loop that sets it off.
for (z = 0; z < 100; z++;) {
playPoker(4);
}
And here's the compare() function:
function compare(players) {
var remPlayers = players.slice();
var rankings = [];
var potentialWinners = [];
//Collect all the players' rankings in an array
for (i = 0; i < remPlayers.length; i++) {
rankings.push(remPlayers[i].rank);
}
//Find the highest ranking
var highestRank = getHighestValue(rankings);
//Move any players with the highest ranking to an array for potential winners
for (j = 0; j < remPlayers.length; j++) {
if (remPlayers[j].rank == highestRank) {
potentialWinners.push(remPlayers[j]);
remPlayers.splice(j, 1);
j--;
}
}
//With all potential winners gone, mark all other players with an L for losing.
for (k = 0; k < remPlayers.length; k++) {
remPlayers[k].result = 'L'
}
var foundWinner = false;
if (potentialWinners.length < 2) {
potentialWinners[0].result = 'W';
foundWinner = true;
}
//Check there is more than one potential winner. If not, the only guy in the array has won.
if (!foundWinner) {
//Loop through all players first cards and find the highest value, then delete any who don't have that, marking them with 'L'.
//If there is no single remnant, do the same for second cards, then third, then fourth, etc.
for (p = 0; p < 5; p++) {
var subRankings = [];
for (q = 0; q < potentialWinners.length; q++) {
subRankings.push(potentialWinners[q].bestHand[p]);
}
var highestSubRanking = getHighestValue(subRankings);
//Mark 'L' and remove any player who does not meet the highest subranking
for (m = 0; m < potentialWinners.length; m++) {
if (potentialWinners[m].bestHand[p] < highestSubRanking) {
potentialWinners[m].result = 'L';
potentialWinners.splice(m, 1);
}
if (potentialWinners.length < 2) {
potentialWinners[0].result = 'W';
//Set this flag to true to break the loop because a winner has been found
foundWinner = true;
break;
}
}
//Break the loop if we have found a winner
if (foundWinner) {
break;
}
//If we still haven't found a winner by the end of the 5th loop, all remaining players draw
if (p == 4) {
for (z = 0; z < potentialWinners.length; z++) {
potentialWinners[z].result = 'D';
}
}
if (foundWinner) {
break;
}
}
}
return players;
}
Try using var declarations on your variables to manage their scope within their relevant functions?

Filling up a 2D array with random numbers in javascript

I'm really sorry if anything like this has been posted here before but I couldn't find anything, I'm kinda new to the site still!
So for a while now I've been learning a bit about game development through html5 and javascript and I stumbled upon making tileset maps, I now have a tileset and an 2D array that I want to put certain tiles in (the number varies between 6 and 10 in this case).
I figured it could be a cool function to make the map choose between a small set of similar tiles so I don't have to specifically number every tile in the array(just define the type)
The method I have currently is probably the best for being able to define types but I want something that looks a bit cleaner and/or information to why my "cleaner" version dosen't work.
var ground = [
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()],
[tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile(),tile()]];
function tile() {
var y = (Math.random() * 5 | 0) + 6;
return y;
}
This is the code I've been using so far, I have to edit every element of the code with the tile() function to get a random number in each one, what I wanted to have was something like this:
for (var i = 0 ; i < 15; i++) {
for (var j = 0; j < 9; j++) {
ground[[i],[j]] = (Math.random() * 5 | 0) + 6;
}
}
to fill the array without having to add the function to each spot.
I have a feeling that I'm missing a return function or something along those lines but honestly I have no idea.
You were thinking in the right direction but there are some errors in your code ;)
You have to initialize the array first before you can push elements into it.
And you were counting i++ twice
Javascript
var ground = []; // Initialize array
for (var i = 0 ; i < 15; i++) {
ground[i] = []; // Initialize inner array
for (var j = 0; j < 9; j++) { // i++ needs to be j++
ground[i][j] = (Math.random() * 5 | 0) + 6;
}
}
Maybe even better (reusable)
function createGround(width, height){
var result = [];
for (var i = 0 ; i < width; i++) {
result[i] = [];
for (var j = 0; j < height; j++) {
result[i][j] = (Math.random() * 5 | 0) + 6;
}
}
return result;
}
// Create a new ground with width = 15 & height = 9
var ground = createGround(15, 9);
Here's a quick example. I've created a function that will take in a width and height parameter and generate the size requested. Also I placed your tile function inside generate ground to keep it private, preventing other script from invoking it.
var ground = generateGround(10, 10); //Simple usage
function generateGround(height, width)
{
var ground = [];
for (var y = 0 ; y < height; y++)
{
ground[y] = [];
for (var x = 0; x < width; x++)
{
ground[y][x] = tile();
}
}
return ground;
function tile()
{
return (Math.random() * 5 | 0) + 6;
}
}
http://jsbin.com/sukoyute/1/edit
Try removing the comma from...
ground[[i],[j]] = (Math.random() * 5 | 0) + 6;
...in your 'clean' version. Also, your incrementing 'i' in both for loops:
for (var i = 0 ; i < 15; i++) {
for (var j = 0; j < 9; i++) {
Hopefully these changes make it work for you :)

Javascript. Create multi dimensional array from calculation

I am trying to create a multi dimensional array based off of the calculations of another 3D array.
Input array is in format [shift, start Num, end num]
I should be clear the "," is just for visual purposes.
I need each value in its own array location i.e. [value1]=location 0,0 [value2]=location 0,1 [value3]=location 0,2 etc.
Example:
aInput looks like this
[0,1,5]
[1,1,3]
[2,1,2]
aOutput should look like this
[1,1,1]
[1,1,2]
[1,2,1]
[1,2,2]
[1,3,1]
[1,3,2]
[2,1,1]
[2,1,2]
[2,2,1]
[2,2,2]
[2,3,1]
[2,3,2]
[1,3,2]
[3,1,1]
[3,1,2]
[3,2,1]
[3,2,2]
[3,3,1]
[3,3,2]
[etc]
It needs to increase the number of items in the array based on the shift. i.e 0 = shift would be 1 column, shift = 1 would be 2 columns, shift = 3 would be 3 columns, and so on. This is what I have so far, but I can not figure out how to make it calculate for anything with a shift.
var aInput = new Array();
aInput[0] = new Array("0", "1","5");
aInput[1] = new Array("1", "1","3");
aInput[2] = new Array("2", "1","2");
for (var x=0; x < aInput[x].length; x++){
//Calculate out number
if (aInput[x][0] == 0){ // Im sure this should be a loop of some sort, just not sure how to do it
var i=Number(aInput[x][1]);
while (i <= Number(aInput[x][2])){
//Write to output array
aOutput.push(i);
i++;
}
}
}
Thanks in advance for any help, I'm really stumped on this one.
var aInput = new Array();
aInput[0] = new Array("0", "1", "5");
aInput[1] = new Array("1", "1", "3");
aInput[2] = new Array("2", "1", "2");
var input_indexed = [],
elem = []; // elem holds the row to be added to the output
// Get aInput[] into a more useful arrangement
for (var i = 0; i < aInput.length; i++) {
// Save the range of each column
input_indexed[parseInt(aInput[i][0])] = {
start: parseInt(aInput[i][1]),
end: parseInt(aInput[i][2])
};
// Initialize elem with the start value of each column
elem[aInput[i][0]] = parseInt(aInput[i][1]);
}
// Produce the output
aOutput = [];
done = false;
while (!done) {
aOutput.push(elem.slice(0)); // push a copy of elem into result
for (i = elem.length - 1;; i--) { // Increment elements from right to left
if (i == -1) { // We've run out of columns
done = true;
break;
}
elem[i]++; // Increment the current column
if (elem[i] <= input_indexed[i].end) {
// If it doesn't overflow, we're done
break;
}
// When it overflows, return to start value and loop around to next column
elem[i] = input_indexed[i].start;
}
}
FIDDLE
var aOutput = [];
for (var i in aInput) {
var y = parseInt(aInput[i][1])
for (var x = y; x <= parseInt(aInput[i][2]); x++) {
aOutput.push([i, y, x]);
}
}

Javascript generate random unique number every time

Ok so i need to create four randomly generated numbers between 1-10 and they cannot be the same. so my thought is to add each number to an array but how can I check to see if the number is in the array, and if it is, re-generate the number and if it isnt add the new number to the array?
so basically it will go,
1.create new number and add to array
2.create second new number, check to see if it exist already, if it doesn't exist, add to array. If it does exist, re-create new number, check again etc...
3.same as above and so on.
You want what is called a 'random grab bag'. Consider you have a 'bag' of numbers, each number is only represented once in this bag. You take the numbers out, at random, for as many as you need.
The problem with some of the other solutions presented here is that they randomly generate the number, and check to see if it was already used. This will take longer and longer to complete (theoretically up to an infinite amount of time) because you are waiting for the random() function to return a value you don't already have (and it doesn't have to do that, it could give you 1-9 forever, but never return 10).
There are a lot of ways to implement a grab-bag type solution, each with varying degrees of cost (though, if done correctly, won't ever be infinite).
The most basic solution to your problem would be the following:
var grabBag = [1,2,3,4,5,6,7,8,9,10];
// randomize order of elements with a sort function that randomly returns -1/0/1
grabBag.sort(function(xx,yy){ return Math.floor(Math.random() * 3) - 1; })
function getNextRandom(){
return grabBag.shift();
};
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
This is of course destructive to the original grabBag array. And I'm not sure how 'truly random' that sort is, but for many applications it could be 'good enough'.
An slightly different approach would be to store all the unused elements in an array, randomly select an index, and then remove the element at that index. The cost here is how frequently you are creating/destroying arrays each time you remove an element.
Here are a couple versions using Matt's grabBag technique:
function getRandoms(numPicks) {
var nums = [1,2,3,4,5,6,7,8,9,10];
var selections = [];
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
You can see it work here: http://jsfiddle.net/jfriend00/b3MF3/.
And, here's a version that lets you pass in the range you want to cover:
function getRandoms(numPicks, low, high) {
var len = high - low + 1;
var nums = new Array(len);
var selections = [], i;
// initialize the array
for (i = 0; i < len; i++) {
nums[i] = i + low;
}
// randomly pick one from the array
for (var i = 0; i < numPicks; i++) {
var index = Math.floor(Math.random() * nums.length);
selections.push(nums[index]);
nums.splice(index, 1);
}
return(selections);
}
And a fiddle for that one: http://jsfiddle.net/jfriend00/UXnGB/
Use an array to see if the number has already been generated.
var randomArr = [], trackingArr = [],
targetCount = 4, currentCount = 0,
min = 1, max = 10,
rnd;
while (currentCount < targetCount) {
rnd = Math.floor(Math.random() * (max - min + 1)) + min;
if (!trackingArr[rnd]) {
trackingArr[rnd] = rnd;
randomArr[currentCount] = rnd;
currentCount += 1;
}
}
alert(randomArr); // Will contain four unique, random numbers between 1 and 10.
Working example: http://jsfiddle.net/FishBasketGordo/J4Ly7/
var a = [];
for (var i = 0; i < 5; i++) {
var r = Math.floor(Math.random()*10) + 1;
if(!(r in a))
a.push(r);
else
i--;
}
That'll do it for you. But be careful. If you make the number of random numbers generated greater than the may number (10) you'll hit an infinite loop.
I'm using a recursive function. The test function pick 6 unique value between 1 and 9.
//test(1, 9, 6);
function test(min, max, nbValue){
var result = recursValue(min, max, nbValue, []);
alert(result);
}
function recursValue(min, max, nbValue, result){
var randomNum = Math.random() * (max-min);
randomNum = Math.round(randomNum) + min;
if(!in_array(randomNum, result)){
result.push(randomNum);
nbValue--;
}
if(nbValue>0){
recursValue(min, max, nbValue, result);
}
return result;
}
function in_array(value, my_array){
for(var i=0;i< my_array.length; i++){
if(my_array[i] == value){
console.log(my_array+" val "+value);
return true;
}
}
return false;
}
Here is a recursive function what are you looking for.
"howMany" parameter is count of how many unique numbers you want to generate.
"randomize" parameter is biggest number that function can generate.
for example : rand(4,8) function returns an array that has 4 number in it, and the numbers are between 0 and 7 ( because as you know, Math.random() function generates numbers starting from zero to [given number - 1])
var array = [];
var isMatch= false;
function rand(howMany, randomize){
if( array.length < howMany){
var r = Math.floor( Math.random() * randomize );
for( var i = 0; i < howMany; i++ ){
if( array[i] !== r ){
isMatch= false;
continue;
} else {
isMatch= true;
break;
}
}
if( isMatch == false ){
array.push(r);
ran(howMany, randomize);
}
ran(howMany, randomize);
return array;
}
}
In your answer earlier, you do have a small bug. Instead of
var originalLength = grabBag.length;
for(var i = 0; i < originalLength .length; i++){
console.log(getNextRandom());
}
I believe you meant:
var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
console.log(getNextRandom());
}
Thanks.

Categories

Resources