I'm looking to create a code in which a card would be drawn randomly by pressing a button. However, I would like some cards to be rarer than others, but I don't know how to integrate this, the code is not at all my favorite domain ...
Thank you very much for your help and the tips you can give me!
var spongebob = "<img src = 'http://www.homastudio.com/img/spongebob.png'>";
var patrick = "<img src = 'http://www.homastudio.com/img/patrick.png'>";
var squidward = "<img src = 'http://www.homastudio.com/img/squidward.png'>";
var sandy = "<img src = 'http://www.homastudio.com/img/sandy.png'>";
var krabs = "<img src = 'http://www.homastudio.com/img/krabs.png'>";
var larry = "<img src = 'http://www.homastudio.com/img/larry.png'>";
var images = [spongebob, patrick, squidward, sandy, krabs, larry]
var names = ["Spongebob Squarepants", "Patrick Star", "Squidward Tentacles", "Sandy Cheeks", "Eugene Krabs", "Larry Lobster"]
function displayImage(){
var rn = Math.random();
rn = rn*6;
rn = Math.floor(rn);
document.getElementById("pic").innerHTML=images[rn];
document.getElementById("name").innerHTML=names[rn];
}
What you're after is called a Weighted Random selection, that is to say it is still a random selection, but some items are weighted higher. The algorithm is fairly simple.
You start with a list of items, and you assign each one a relative weight. The higher the weight, the more likely it is to be picked. Then, pick a random number between 0 and the total weight of all items and you step through the items subtracting each items weight from the random number you selected. when the number reaches zero, you have your item.
Heres an example.
function WeightedBroker(){
this.totalWeight = 0;
this.items = [];
this.addItem = function(value,weight){
this.items.push({value,weight});
this.totalWeight+= weight;
}
this.pickItem = function(){
var rnd = Math.floor(Math.random() * this.totalWeight);
for(var i=0;i<this.items.length;i++){
if(rnd<=this.items[i].weight)
return this.items[i].value;
rnd -= this.items[i].weight;
}
}
}
var broker = new WeightedBroker();
broker.addItem("a",100);
broker.addItem("b",10);
broker.addItem("c",1);
for(var i=0;i<10;i++)
console.log(broker.pickItem());
Applying this to your code is pretty easy, you will want to change those 2 arrays (one with img html, and one with names) to objects containing the properties name and src. You add each of these items to the broker I wrote above with appropriate weights for each according to your requirement. Something like this:
function WeightedBroker(){
this.totalWeight = 0;
this.items = [];
this.addItem = function(value,weight){
this.items.push({value,weight});
this.totalWeight+= weight;
}
this.pickItem = function(){
var rnd = Math.floor(Math.random() * this.totalWeight);
for(var i=0;i<this.items.length;i++){
if(rnd<=this.items[i].weight)
return this.items[i].value;
rnd -= this.items[i].weight;
}
}
}
var broker = new WeightedBroker();
broker.addItem({src:"<img src = 'http://www.homastudio.com/img/spongebob.png'>",name:"Spongebob Squarepants"},100);
broker.addItem({src:"<img src = 'http://www.homastudio.com/img/patrick.png'>",name:"Patrick Star"},100);
broker.addItem({src:"<img src = 'http://www.homastudio.com/img/squidward.png'>",name:"Squidward Tentacles"},100);
broker.addItem({src:"<img src = 'http://www.homastudio.com/img/sandy.png'>",name:"Sandy Cheeks"},100);
broker.addItem({src:"<img src = 'http://www.homastudio.com/img/krabs.png'>",name:"Eugene Krabs"},100);
broker.addItem({src:"<img src = 'http://www.homastudio.com/img/larry.png'>",name:"Larry Lobster"},100);
var item = broker.pickItem();
document.getElementById("pic").innerHTML=item.src;
document.getElementById("name").innerHTML=item.name;
<div id="name"></div>
<div id="pic"></div>
instead of having the array just have images do something like the following (where a low number in 'rarity' means more rare:
var spongebob = {
url:"<img src = 'http://www.homastudio.com/img/spongebob.png'>",
rarity: 1
};
var patrick = {
url:"<img src = 'http://www.homastudio.com/img/patrick.png'>",
rarity: 2
};
var squidward = {
url:"<img src = 'http://www.homastudio.com/img/squidward.png'>",
rarity: 4
};
var images = [spongebob, patrick, squidward];
var imageChoiceArr = [];
for(var i=0;i<images.length;i++) {
image = images[i];
for(var ii=0;ii<image.rarity;ii++) {
imageChoiceArr.push(image.url);
}
}
Then pick randomly from the 'imageChoiceArr'
Related
I'm developing a web page of the game Mastermind, using images instead of colors.
I generate the password using Math.floor(Math.random() * 6) + 1; to generate numbers from 1 to 6, and using that function to convert a number to an image:
var sam = document.createElement("img");
sam.src = "./samwell_tarly.jpeg";
var arya = document.createElement("img");
arya.src = "./arya_stark.jpeg";
var dany = document.createElement("img");
dany.src = "./dany.jpeg";
var jon = document.createElement("img");
jon.src = "./jon.jpeg";
var ned = document.createElement("img");
ned.src = "./ned_stark.jpeg";
var tyrion = document.createElement("img");
tyrion.src = "./tyrion.jpeg";
var ocu1 = document.getElementById("oc1");
var ocu2 = document.getElementById("oc2");
var ocu3 = document.getElementById("oc3");
var ocu4 = document.getElementById("oc4");
function intToGot(x) {
if(x==1){return arya;}
if(x==2){return sam;}
if(x==3){return ned;}
if(x==4){return dany;}
if(x==5){return jon;}
if(x==6){return tyrion;}
}
and then:
const oc1=Math.floor(Math.random() * 6) + 1;
ocu1.appendChild(intToGot(oc1));
const oc2=Math.floor(Math.random() * 6) + 1;
ocu2.appendChild(intToGot(oc2));
const oc3=Math.floor(Math.random() * 6) + 1;
ocu3.appendChild(intToGot(oc3));
const oc4=Math.floor(Math.random() * 6) + 1;
ocu4.appendChild(intToGot(oc4));
Those are my divs:
<div class="maiores" id="oc1"></div>
<div class="maiores" id="oc2"></div>
<div class="maiores" id="oc3"></div>
<div class="maiores" id="oc4"></div>
The problem i am facing is that:
When the numbers generated are all different, all of the 4 random images appear correctly, with no problems at all. But, when there is repetition, for example, if the password should be [sam,sam,dany,jon], only the last one of the repeated images appear, and the others just don't appear. In that case, the first 'sam' wouldn't appear. I can't understand how am I using wrong the appendChild function, and I need help to solve that problem.
You've only made one image node for each character. It can only go in one place.
Just generate your images on the fly, instead of ahead of time.
function makeGot(fileName) {
const n = document.createElement("img");
n.src = filename;
return n;
}
function intToGot(x) {
if(x==1){return makeGot("arya_stark.jpeg");}
if(x==2){return makeGot("samwell_tarly.jpeg");}
if(x==3){return makeGot("ned_stark.jpeg");}
if(x==4){return makeGot("dany.jpeg");}
if(x==5){return makeGot("jon.jpeg");}
if(x==6){return makeGot("tyrion.jpeg");}
}
solution
Explanation
This is because if a node is already a part of a document, then you cannot use that node reference again in another part of a document. If you do then the previous nodes get removed and inserted into new location.
const parent = document.querySelector("#parent");
const parent2 = document.querySelector("#parent2");
function createListChildElement(text) {
const element = document.createElement("li");
element.textContent = text;
return element;
}
const firstListChild = createListChildElement("First");
parent.appendChild(firstListChild);
const secondListChild = createListChildElement("Second");
parent.appendChild(secondListChild);
parent2.appendChild(firstListChild);
<h1>Second List</h1>
<ul id="parent"></ul>
<h1>Second List</h1>
<ul id="parent2"></ul>
Solution
You can create a new node/clone and append it to a new parent. You can do this using cloneNode method node
const parent = document.querySelector('#parent');
const parent2 = document.querySelector('#parent2');
function createListChildElement( text ) {
const element = document.createElement('li');
element.textContent = text;
return element;
}
const firstListChild = createListChildElement("First");
parent.appendChild( firstListChild );
const secondListChild = createListChildElement("Second");
parent.appendChild( secondListChild );
const clonedChild = firstListChild.cloneNode(true);
parent2.appendChild( clonedChild );
<h1>First list</h1>
<ul id="parent"></ul>
<h1>Second list</h1>
<ul id="parent2"></ul>
I've created to a simple illustrator script to loop through the artboards and export each as a PNG back into the folder that the original illustrator file is in. At least I thought I had. I don't need to do anything complicated with layers or different formats this is just a speed up production sort of a thing. I'm a bit rusty on .jsx and appreciate there are similar solutions out there, but I can't get this to run. It seems to fail on the doc.ExportFile line but I really can't see what I'm doing wrong. I'd appreciate anyone taking a look:
var doc = activeDocument;;//Gets the active document
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var basePath = new File($.fileName).parent.fsName;
$.writeln(doc)
var options;
options = new ExportOptionsPNG24();
options.artBoardClipping = true;
options.matte = false;
options.horizontalScale = 100;
options.verticalScale = 100;
options.transparency = true;
for (var i = 0; i < numArtboards; i++ ) {
doc.artboards.setActiveArtboardIndex( i );
var artboardName = doc.artboards[i].name;
var destFile = new File('/' + artboardName + ".png");
doc.exportFile(destFile, ExportFormat.PNG24 , options);
}
The main problem seemed to be that you hve to have a destination path with the file name. This now seems to work: (You may need to altter the fileNamr generation as code just gets the first nune letters of a filename)
var doc = app.activeDocument;;//Gets the active document
var fleName = doc.name.slice(0, 9)//Get the file code number not the full name;
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var filePath = (app.activeDocument.fullName.parent.fsName).toString().replace(/\\/g, '/');
$.writeln("fleName= ",fleName)
$.writeln("numArtboards= ",numArtboards)
$.writeln("filePath= ",filePath);
var options = new ExportOptionsPNG24();
for (var i = 0; i < numArtboards; i++ ) {
doc.artboards.setActiveArtboardIndex( i );
options.artBoardClipping = true;
options.matte = false;
options.horizontalScale = 100;
options.verticalScale = 100;
options.transparency = true;
var artboardName = doc.artboards[i].name;
$.writeln("artboardName= ", artboardName);
var destFile = new File(filePath + "/" + fleName + " " + artboardName + ".png");
$.writeln("destFile= ",destFile);
doc.exportFile(destFile,ExportType.PNG24,options);
}
I have searched the forum thoroughly for a solution to this with no luck. Hoping someone can help me here.
I have an empty div with no background image. When a user clicks on it, I have a function that sets the background image like this:
function myAnimation(element) {
var images = ["url(images/pig.png)", "url(images/cat.png)", "url(images/frog.png)", "url(images/dog.png)"];
var random = Math.floor(Math.random() * 4);
element.style.backgroundImage = images[random];
}
Although this works, the problem I'm having is finding the solution to when the user clicks on the image again. As there is only four possible numbers generated, I keep getting a repeating number from the var random method. I think I need a way to check the last number generated and if it's the same, it should try and generate a different number. This way there will be no repeating images. Hope this makes sense. Just so you know, I'm new to programming and only learning Javascript for the last 3 months. I think I may need a loop or another function inside this function, not sure.
I am checking prevNo with generated random number. If both are same, then call the function again. Else assign the random number to prevNo and load the image.
var prevNo = -1;
function myAnimation(element) {
var images = ["url(images/pig.png)", "url(images/cat.png)", "url(images/frog.png)", "url(images/dog.png)"];
var random = Math.floor(Math.random() * 4);
if( random == prevNo) {
myAnimation(element);
return;
} else {
prevNo = random;
}
element.style.backgroundImage = images[random];
}
You can filter your images, considering all items except the current background element, and take a random element of the result.
This is a example of how you can accomplish this:
function myAnimation(element) {
var currentBackgroundImage = element.style.backgroundImage;
var images = [
"url(https://place-hold.it/100x100&text=1)",
"url(https://place-hold.it/100x100&text=2)",
"url(https://place-hold.it/100x100&text=3)",
"url(https://place-hold.it/100x100&text=4)",
];
var restOfImages = images.filter(function (image) {
return image !== currentBackgroundImage;
})
var random = Math.floor(Math.random() * restOfImages.length);
element.style.backgroundImage = restOfImages[random];
}
Another way, without filter:
function myAnimation(element) {
var currentBackgroundImage = element.style.backgroundImage;
var images = [
"url(https://place-hold.it/100x100&text=1)",
"url(https://place-hold.it/100x100&text=2)",
"url(https://place-hold.it/100x100&text=3)",
"url(https://place-hold.it/100x100&text=4)",
];
var restOfImages = [];
for(var i = 0; i < images.length; i++) {
if (images[i] !== currentBackgroundImage) {
restOfImages.push(images[i]);
}
}
var random = Math.floor(Math.random() * restOfImages.length);
element.style.backgroundImage = restOfImages[random];
}
And here is a working snipplet:
function myAnimation(element) {
var currentBackgroundImage = element.style.backgroundImage;
var images = [
"url(https://place-hold.it/100x100&text=1)",
"url(https://place-hold.it/100x100&text=2)",
"url(https://place-hold.it/100x100&text=3)",
"url(https://place-hold.it/100x100&text=4)",
];
var restOfImages = images.filter(function (image) {
return image !== currentBackgroundImage;
})
var random = Math.floor(Math.random() * restOfImages.length);
element.style.backgroundImage = restOfImages[random];
}
var el = document.getElementById('container');
el.onclick= function() { myAnimation(el); };
#container{
width: 100px;
height: 100px;
background-color: red;
}
<div id="container"></div>
You can repeatedly use Array.splice to remove a random element.
var images = [...
var random = Math.floor(Math.random() * 4);
element.style.backgroundImage = images.splice(random, 1)[0];
I'm using the same function across the entire site so I'm using local storage with a window onload call to headerPic():
const originalArr = ["image1.jpg", "image2.jpg", etc...];
function headerPic() {
let headerImgArray = localStorage.getItem("headerList") ? JSON.parse(localStorage.getItem("headerList")) : originalArr;
if (headerImgArray.length < 1) {
headerImgArray = originalArr;
}
const randomName = headerImgArray[Math.floor(Math.random() * headerImgArray.length)];
document.getElementById("headerImg").src = `imagesHeader/${randomName}`;
headerImgArray.splice(headerImgArray.indexOf(randomName), 1);
if (headerImgArray.length < 1) {
headerImgArray = originalArr;
}
localStorage.setItem("headerList", JSON.stringify(headerImgArray));
}
I'm trying to make an image cycle through a set of images, when you click a button. Why won't it work? I want to make sure the images are preloaded, so that it will not make the website slower.
var ImageSet = new Array();
ImageSet[0] = ImageOne;
ImageOne = newImage();
ImageSet[0].src = 'Website/Images/CoverPhotos/LogoCover.jpg';
ImageSet[1] = ImageTwo;
ImageTwo = newImage();
ImageSet[1].src = 'http://p1.pichost.me/i/64/1886374.jpg';
ImageSet[2] = ImageThree;
ImageThree = newImage();
ImageSet[2].src = 'http://abduzeedo.com/files/originals/5/50cuteanimpic6.jpg';
ImageSet[3] = ImageFour;
ImageFour = newImage();
ImageSet[3].src = 'http://www.onsecrethunt.com/wallpaper/wp-content/uploads/2015/01/Cool-Wallpapers-Card-Pictures-1200x675.jpg';
var ImageSwitchNo = 0;
function Change() {
if (ImageSwitchNo < 3) {
ImageSwitchNo++;
}else {
ImageSwitchNo = 0;
}
var ImageSrc = document.getElementById('HeaderPhotoImage').innerHTML;
ImageSrc.src = ImageSet[3];
}
You are giving ImageOne a value on line three after trying to store it in the array on the line before it.
Instead of this:
var ImageSet = new Array();
ImageSet[0] = ImageOne;
ImageOne = newImage();
ImageSet[0].src = 'Website/Images/CoverPhotos/LogoCover.jpg';
try doing it like this for all of them:
var ImageSet = [];
ImageOne = newImage(); //gives ImageOne a value.
ImageSet[0] = ImageOne; //THEN sets the index of ImageSet to that value.
ImageSet[0].src = 'Website/Images/CoverPhotos/LogoCover.jpg';
Your code may work if you change the second line from bottom,
ImageSrc.src = ImageSet[3];
to
ImageSrc.src = ImageSet[ImageSwitchNo];
I'm studying javascript for the first time and I've some doubt: I have two arrays; the first one contain the image of a person, the second one his personal informations (the arrays' length is the same because they contain the same number of people). I'd like to write the content in my page so print the image and the infos of the first user, then the image and the infos of the second and so on...
How can I do it?
this is the code:
function jsonCard()
{
var richiestaCard = new XMLHttpRequest();
richiestaCard.onreadystatechange = function()
{
if(richiestaCard.readyState == 4)
{
var objectcardjson = {};
window.arrayCard= []; //creazione dell'array che conterrĂ le cards
objectcardjson = JSON.parse(richiestaCard.responseText);
arrayCard = objectcardjson.cards; //the first array
}
}
richiestaCard.open("GET", "longanocard.json", true);
richiestaCard.send(null);
}
function jsonEntity()
{
var richiestaEntity = new XMLHttpRequest();
richiestaEntity.onreadystatechange = function()
{
if(richiestaEntity.readyState == 4)
{
var objectentityjson = {};
window.arrayEntity= []; //creazione dell'array che conterrĂ le entity
objectentityjson = JSON.parse(richiestaEntity.responseText);
arrayEntity = objectentityjson.cards; //the second array
}
}
richiestaEntity.open("GET", "longano.json", true);
richiestaEntity.send(null);
}
function displayArrayCards()
{
jsonCard();
jsonEntity();
var inizioTag = "<img src=";
var fineTag = "\>";
for(i = 0; i < arrayCard.length; i++)
{
...
}
}
I'd like to have the image and then the infos (for the first user), the image and the infos for the second and so on all included in a div.
Try something along the lines of
function displayArrayCards()
{
jsonCard();
jsonEntity();
var wrapper = document.getElementById('div you want to put all of these users into');
for(i = 0; i < arrayCard.length; i++)
{
var userDiv = document.createElement('div');
var cardImg = document.createElement('img');
img.src = arrayCard[i];
/** Set other attributes for img **/
var entityDiv = document.createElement('div');
entityImg.innerHTML = arrayEntity[i];
/** Set other attributes for div **/
userDiv.appendChild(cardImg);
userDiv.appendChild(entityDiv);
wrapper.appendChild(userDiv);
}
}
Honestly there are a lot of ways to do this. Above is simply what I would do.