Resulting "undifined" after using splice - javascript

Im trying to code a random houses generator in JS for a game of thrones game,
the code looks like that at the moment:
//Houses Array:
var HousesArray = [
'Stark',
'Lanister',
'Greyjoy',
'Barathion',
'Arryn',
'Tyrell',
'Martell',
'Targaryen'
];
//Houses Variables:
var house1 = {}
var house2 = {}
var house3 = {}
//Random House Generator
var RandomIndex = Math.floor(Math.random()*HousesArray.length)
var RandomElement = HousesArray[RandomIndex]
//3 Players Generator:
house1 = RandomElement
console.log(house1)
HousesArray.splice(house1,1)
RandomElement = HousesArray[RandomIndex]
house2 = RandomElement
console.log(house2)
HousesArray.splice(house2,1)
RandomElement = HousesArray[RandomIndex]
house3 = RandomElement
console.log(house3)
What I tryed to do here is to give the house1 variable a random house name from one of the HousesArray Eelements,
echo that to the console log,
then remove the selected element from HousesArray using the splice commend (to ensure that the next selection will not be the same one).
after all that - generate new house name from the elements left in the HousesArray and repeat.
But for some reasos, Every time house1 = "Targaryen" (or house2) the next 2/1 resolts automaticly return "undifined" (I beleive its becuse the "Targaryen" element is the last in the list)
How can i fix that?

Your code is not working because RandomIndex is always the same, if it's 7, it will return undefined because splice modifies the original array by removing the found House,
change RandomIndex to be a function to call everytime so it generates a new index using the new length of the array:
var RandomIndex = () => Math.floor(Math.random() * HousesArray.length)
//Houses Array:
var HousesArray = [
'Stark',
'Lanister',
'Greyjoy',
'Barathion',
'Arryn',
'Tyrell',
'Martell',
'Targaryen'
];
//Houses Variables:
var house1 = {}
var house2 = {}
var house3 = {}
//Random House Generator
var RandomIndex = () => Math.floor(Math.random() * HousesArray.length)
var RandomElement = HousesArray[RandomIndex()]
//3 Players Generator:
house1 = RandomElement
console.log(house1)
HousesArray.splice(HousesArray.indexOf(house1), 1)
RandomElement = HousesArray[RandomIndex()]
house2 = RandomElement
console.log(house2)
HousesArray.splice(HousesArray.indexOf(house2), 1)
RandomElement = HousesArray[RandomIndex()]
house3 = RandomElement
console.log(house3)

Doesn't appear you're using the splice method correctly here, it takes the first 2 arguments as numbers, and the third argument would be an element you want to replace it with if you'd like. Instead I would use a filter here:
let newHouseArray = HousesArray.filter(house => house !== house1)

This kept me stumped for quite a while, I would do something like this instead:
Now if you console.log(houses) you will get 3 random houses from random positions (as stated in the above comment) allowing players 2 and 3 to get houses earlier in position than players 1 and 2
Hope this helps :) seem's like a fun game:
//Houses Array:
var HousesArray = ['Stark', 'Lanister', 'Greyjoy', 'Barathion', 'Arryn', 'Tyrell', 'Martell', 'Targaryen'];
// stores the houses
var houses = [];
// Generates 3 random numbers and allows players 2 and 3 to get the houses early in position than player 1 and 2
var arr = [];
while (arr.length < 3) {
var r = Math.floor(Math.random() * 8);
if(arr.indexOf(r) === -1) arr.push(r);
}
// Pushed the houses to the house array
for (var x = 0; x < arr.length; x++) {
houses.push(HousesArray[arr[x]])
}
console.log(houses);

Related

Randomly swap 2 elements of array with another 2 elements

I have a list of team members and a list of 2 substitutes:
team = Samson, Max, Rowan, Flynn, Jack
subs = Struan, Harry
I need to randomly swap the 2 subs into the team. I'm getting stuck because I need to ensure that only these 2 elements are swapped and that both are swapped in. I tried just looping through the subs array and randomly swapping each element with an element from the team array, but too frequently it swapped Struan with Max and then Harry with Struan, so that in the end Struan was still in the subs array and not in the team.
So: I need to exclusively swap the 2 elements in the sub array with random elements from the team array. How can I do that?
You can do this with this function. Give the function current team and substitudes and get new team with random substitution done.
const team = ['Samson', 'Max', 'Rowan', 'Flynn', 'Jack']
const subs = ['Struan', 'Harry']
const substitudePlayers = (team, subs) => {
const newTeam = [...team]
// get 2 random numbers which are less than team members count
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max-1);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 2 random numbers
let num1 = getRandomInt(0, team.length)
let num2 = getRandomInt(0, team.length)
// make sure that numbers are different
while(num2 === num1) num2++
// substitude
newTeam[num1]=subs[0]
newTeam[num2]=subs[1]
return newTeam
}
const substitudedTeam = substitudePlayers(team, subs);
console.log(substitudedTeam)
This should work:
function getRandomItem () {
let randomItem = team[Math.floor(Math.random()*team.length)];
if(subs.indexOf(randomItem)<0){
return randomItem;
} else {
return getRandomItem();
}
}
subs.forEach((item,i)=>{
subs.splice(i,1,getRandomItem());
}

How to randomize without replacement with conditions?

I have a number of embedded images, which I randomize 4 times without replacement (once an image is seen, you cannot see it again). I'd like to add a condition, which suggests that a set of additional images cannot be seen (not only the image that was previously selected). These are images that have similar traits to the one selected.
To demonstrate:
Let's say I have the following array of vars:
BF1, BA1, BF2, BA2, BF3, BA3
I want to randomly draw 3 vars (images) out of the array without replacement, AND I want vars that have the number 2 (same set) to be removed from the next array as well. So, if the first drawn var is BF2, the next draw will be from the following array:
BF1, BA1, BF3, BA3 (only one of these options can randomly appear)
Now let's say I drew the var BF1, so the next set of possible vars will be:
BF3, BA3.
I hope this makes sense. This is the code I have so far for the drawing without replacement:
function shuffle(array){
var counter = array.length,
temp, index;
while (counter > 0){
index = Math.floor(Math.random() * counter);
counter = counter-1;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
var myArray = [BF1,BA1,BF2, BA2, BF3,BA3, BA4, BF4, BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BA17, BF17, BA18, BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, BF26, BA27, BF27, BA28, BF28, BA29, BF29, BA30, BF30, BA31, BF31, BA32, BF33, BA33, BA34, BF35, BA35, BA36, BF36];
shuffle(myArray)
You can definitely implement this in any number of ways, but no matter what you use, you'll need to perform the following 3 steps in some capacity (I split them out into separate methods, but you can combine them as you see fit):
Shuffle the list
Pick an item
Filter out the items matching the pick (in this case, those with the same number)
You have the shuffle routine covered, so that just leaves the pick and the filter.
For the pick, I just used Math.random to pull a random member of the list:
return array[Math.floor(Math.random() * array.length)];
For the filter, I used Array.prototype.filter to pull out the desired items. In this case, with the strings, I parse the number out of the string and then remove any items in the array that have the same number as the last pick:
return array.filter(el => +el.match(/\d+/).join() != +picked.match(/\d+/).join());
But with actual images, you'll just replace that with however you read the labels of your images.
Example
Here's the full working example, with the list of picks first, followed by a sorted array of the picks showing they were all used.
var imageList = ['BF1', 'BA1', 'BF2', 'BA2', 'BF3', 'BA3', 'BA4', 'BF4', 'BA5', 'BF5', 'BF6', 'BA6', 'BF7', 'BA7', 'BA8', 'BF8', 'BA9', 'BF9', 'BF10', 'BA10', 'BA11', 'BF11', 'BA12', 'BF12', 'BA13', 'BF13', 'BA14', 'BF14', 'BA15', 'BF15', 'BA16', 'BF16', 'BA17', 'BF17', 'BA18', 'BF18', 'BA19', 'BF19', 'BA20', 'BF20', 'BA21', 'BF21', 'BF22', 'BA23', 'BF23', 'BA24', 'BF24', 'BA25', 'BF25', 'BA26', 'BF26', 'BA27', 'BF27', 'BA28', 'BF28', 'BA29', 'BF29', 'BA30', 'BF30', 'BA31', 'BF31', 'BA32', 'BF33', 'BA33', 'BA34', 'BF35', 'BA35', 'BA36', 'BF36'];
var selection = imageList.slice();
var picked = [];
function shuffle(array) {
var counter = array.length, temp, index;
while (counter > 0) {
index = Math.floor(Math.random() * counter);
counter = counter - 1;
temp = array[counter];
array[counter] = array[index];
array[index] = temp;
}
return array;
}
function pick(array) {
return array[Math.floor(Math.random() * array.length)];
}
function filterPicked(picked, array) {
return array.filter(el => +el.match(/\d+/).join() != +picked.match(/\d+/).join());
}
while (selection.length) {
// 1. Shuffle
shuffle(selection);
// 2. Pick
picked.push(pick(selection));
// 3. Filter
selection = filterPicked(picked[picked.length-1], selection);
}
console.log(`Picks: [${picked.join(', ')}]`);
console.log(`Sorted picks: [${picked.sort((a, b) => +a.match(/\d+/).join() - +b.match(/\d+/).join()).join(', ')}]`);
Step-by-step
Shuffle the selection array (a copy of the full array or all selections)
Pick an item off the selection array, push it onto the array of picks
Filter the selection array to remove items matching the last pick
Repeat 1-3 with each newly filtered array, until no selections remain
You can shuffle array with loop and random numbers, then in another loop extract first image in resulting array, filter array with numbers at the end of string
var myArray="BF1, BA1, BF2, BA2, BF3, BA3, BA4, BF4, BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BA17, BF17, BA18, BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, BF26, BA27, BF27, BA28, BF28, BA29, BF29, BA30, BF30, BA31, BF31, BA32, BF33, BA33, BA34, BF35, BA35, BA36, BF36";
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
const arr = shuffle(myArray.split(','));
function draw(a, times) {
let res =[]
for (let i = 1; i <= times; i++) {
let str = a[0]
res.push(str)
a = a.filter(a => parseInt(a.match(/\d+$/)[0], 10) !== parseInt(str.match(/\d+$/)[0], 10))
}
return res
}
console.log(draw(arr, 4))

Creating an array that is consisted of unique numbers

I'm developing a simple game that allows user to generate from 1 to 5 Cat images from certain Cat Api. Then, after clicking start button the app generates shadow copies of those cats(with low opacity). Game will be later about dragging bottom images and fiting them to their shadow copies, that are randomly positioned(only then game makes sense). Then I'm planning make some futher features like time counter, points etc. etc. just for learning purposes.
But what am struggling with is creating a unique random number(that'll be index of particular cat) an will not be repeated during iteration...
Here is the code
const newArray = []; //
const catsArrayList = [...catBoardCopy.querySelectorAll('.cat')] //Array with cat images
function randomizeIndex() { // randomize an index number
let randomIndex = Math.floor((Math.random() * catsArrayList.length - 1) + 1);
console.log(randomIndex);
return randomIndex;
}
catsArrayList.forEach(catElement => { // here I am iterating over an array with cats which length is for example 5(this is max actually)
newArray.push(catsArrayList[randomizeIndex()]); // and pushing those elements with randomly generated index to the new array
})
newArray.forEach(newCat => {
shadowCatsContainer.appendChild(newCat); // here random cats are finally put to html container
})
And all of this work until the point when one of those random numbers is at least one time repeated... of course this happens actually 90% of time.
Im supposing it won't be simple solution to that. I tried so hard to make it work with different techniques, different loops, different array methods and nothing :( Also please take note that Im beginner so I need exhaustive guidance of what is going on :)
Have a nice day.
Your code is close; you can just remove the items that you're assigning to the new array from the source array so you don't use it twice.
const cats = [...catBoardCopy.querySelectorAll('.cat')]
function randomIndex() {
return Math.floor(Math.random() * cats.length);
}
cats.forEach(catElement => {
const index = randomIndex();
shadowCatsContainer.appendChild(cats[index]);
cats.splice(index, 1);
})
One option is to simply shuffle an array:
const cats = ['Tigger', 'Smokey', 'Kitty', 'Simba', 'Sassy'];
function shuffle(array, n = 500) {
const output = array.slice();
for (let i = 0; i < n; ++i) {
swap(output, getRandomInt(0, output.length), getRandomInt(0, output.length))
}
return output;
}
function swap(array, i, j) {
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}
const shadowedCats = shuffle(cats);
console.log(cats);
console.log(shadowedCats);
console.log(shuffle(cats));
An example using array. Here I created an array with the possible numbers, it goes from 0 to the number of elements contained in the 'catsArrayList' array. If for example 'catsArrayList' has 3 elements, then the array with the possible numbers will be equal to: [0, 1, 2]
The idea now is to draw a random number from that array and then remove it from the list, and then we can go on repeating the process without getting repeated values.
e.g.
let catsArrayList = ['value1', 'value2', 'value3', 'value4', 'value5', 'value6'] // example
let numbers = [...Array(catsArrayList.length).keys()]
let lengthnumbers = numbers.length
for(let i = 1; i <= lengthnumbers; i++) {
let randoms = Math.floor(Math.random() * numbers.length)
console.log(i + 'º number: ' + numbers.splice(randoms, 1))
}
Click on 'Run code snippet' a few times and you will see that you will get different, non-repetitive random numbers

Compare arrays in loop - javascript

I'm doing a lottery system and I need to make sure that each Array is ​​different. This is my code:
var intNumberOfBets = 10;
let aLotteryTicket=[];
let aData = [];
for(intI = 0; intI <intNumberOfBets; intI++){
let oCasilla ={};
oCasilla.block=[];
for(intI = 0; intI <intNumberOfBets; intI++){
let oCasilla ={};
oCasilla.block=[];
Each "lottery ticket" has an array with 5 numbers. They can have the same numbers as others but in different positions.
for (let intB=1;intB<=5;intB++)
{
for(let intA=1;intA<=50; intA++){ aLotteryTicket.push(intA); }
oCasilla.block.push(aLotteryTicket.splice(parseInt(Math.random()*aLotteryTicket.length),1)); // ADD 5 NUMBERS RANDOMLY TO ARRAY
};
oCasilla.block.sort(function (a,b){ return (parseInt(a)-parseInt(b));});
aData.push(oCasilla);
alert(aData[intI].block); // show generated arrays
}//END FOR
How can I prevent each array from being the same as another, before adding it to my final Array aData[]?
Example:If i add the array 5,6,7,8,9 to oCasilla.block=[]; , i need to check that there is not another 5,6,7,8,9 in oCasilla.block=[];
Thanks in advance
You can use a set of string representations (numbers separated by comma built using join(',')) of your tickets to keep track of what was added, and only add if a ticket was not previously created.
function generateTicket() {
// generate an array with 5 unique random numbers
let a = new Set();
while (a.size !== 5) {
a.add(1 + Math.floor(Math.random() * 50));
}
return Array.from(a);
}
let oCasilla = {
block: []
};
let addedTickets = new Set(); // add stingified ticket arrays here
// add 10 unique tickets to oCasilla.block
while (oCasilla.block.length !== 10) {
const ticket = generateTicket();
if (!addedTickets.has(ticket.join(','))) {
oCasilla.block.push(ticket);
addedTickets.add(ticket.join(','));
}
}
console.log(oCasilla);

why is this javascript array undefined?

I have the following code, which attempts to generate a 2 dimensional array of random numbers:
var block_size = 32;
var can_width = can.width;
var color_depth = 12;
var passes = can_width / block_size;
var map_store = new Array(passes);
for(i=0;i<passes;i++) {
for(j=0;j<passes;j++) {
map_store[i] = new Array(passes);
color = Math.random() * color_depth;
map_store[i][j] = Math.round(color);
}
}
which seems to work fine if i put console.log statements within the loop, however if I try to access the map_store array outside of the loops. all of it's elements are undefined. why is this?
map_store[i] = new Array(passes); should be above the 2nd for loop. You're clearing your previous j values.
for(i=0;i<passes;i++) {
map_store[i] = new Array(passes); // <--
for(j=0;j<passes;j++) {
color = Math.random() * color_depth;
map_store[i][j] = Math.round(color);
}
}

Categories

Resources