1

I am making a random colour generator. I would like to add percentages or chances to get a certain colour by setting their percentage in a field. (eg. User sets the blue colour to have a 50% chance to be generated) Can I do this? If there is an easier/more efficient way to write this code, please let me know. I am very new to coding but wanted to challenge myself.

I want to know how to set, eg. 50%, to a colour but wouldn't know how to do it within an array, as I only have 0-9 index in my array. Please help :)

var colors = ["Red", "Yellow", "Blue", "Green", "Orange", "Purple", "Pink", "Black", "White", "Violet"];

$(document).ready(function(){
 $('#spin-btn').click(function(){
    var output = colors.length;
    var randomNumber = Math.floor(Math.random()*output);

    for(i=0;i<=output;i+=1){
        var newColor = colors[randomNumber];
        console.log(newColor);

        if(newColor === "Red"){
            $('#red').show();
        } else {
            $('#red').hide();
        }
        if(newColor === "Yellow"){
            $('#yellow').show();
        } else {
            $('#yellow').hide();
        }
        if(newColor === "Blue"){
            $('#blue').show();
        } else {
            $('#blue').hide();
        }
        if(newColor === "Green"){
            $('#green').show();
        } else {
            $('#green').hide();
        }
        if(newColor === "Orange"){
            $('#orange').show();
        } else {
            $('#orange').hide();
        }
        if(newColor === "Purple"){
            $('#purple').show();
        } else {
            $('#purple').hide();
        }
        if(newColor === "Pink"){
            $('#pink').show();
        } else {
            $('#pink').hide();
        }
        if(newColor === "Black"){
            $('#black').show();
        } else {
            $('#black').hide();
        }
        if(newColor === "White"){
            $('#white').show();
        } else {
            $('#white').hide();
        }
        if(newColor === "Violet"){
            $('#violet').show();
        } else {
            $('#violet').hide();
        }


        break;
    }

2 Answers2

3
 var colors = [
  "Blue","Blue", "Blue", "Blue", "Blue", "Blue", "Blue", "Blue" , "Blue" 
  "Red","Yellow", "Green", "Orange", "Purple", "Pink", "Black", "White", "Violet"  
 ];

 function generateColor() {
   var colorsAmount = colors.length;
   var randIndex = Math.floor(Math.random() * colorsAmount);
   return colors[randIndex];
 }

in the colors array you repeat the element to increase his probability to be chosen .

now theres 9 elements with the value "blue" and all the rest repeat once.

so there is 9 of 18 probability to choose blue (50%), and all the other colors 1 of 18 (5.55..%)

inspired by this answer

Ofir G
  • 736
  • 6
  • 18
  • Should I use your function or is my function okay? If I wanted the user to be able to choose the probability, is there a way for them to add colors to an array? by appending? For example, in the 'Blue:' field input box, the user puts '50' for 50%. After pressing the 'submit probability' button, then it calculates how many 'blue''s it needs to add to the array? – Ben Stallwood Jan 15 '18 at 11:10
  • you need to calculate from the percentage in the user input, the amount of that element to be repeated so it will be matched the probability. – Ofir G Jan 15 '18 at 11:32
  • How do I go about calculating the percentage in user input? – Ben Stallwood Jan 15 '18 at 11:50
0

EDIT: I misconstrued the question. Thought they meant 'percentages' in terms of color opacity. I left that code-snippet in the end of this answer, in case it's of use to anyone. Apologies for the confusion.

Code Improvement

In terms of code, here's a quick way to reduce all those lines. When you have such code as this (with so many if-elsethe first thing you must question yourself is... What happens if tomorrow you add a new color to the array? What if you add 100 colors? Then you'd need 100 more if-else cases. Absolute nightmare, right? So let's think of a way to fix that.

Keep in mind that coding is all you want, you set the rules and magic. It's beautiful. So, how can you use the information you have in colors so as not to repeat yourself?

STEP ONE

Add CSS rules to the box where you want to show the color. The CSS rules would match the names of the colors you have inside your variable colors so you can quickly add/remove CSS classes.

For the code snippet I removed various colors so as not to write so many CSS rules. When you improve some, look up wonderful SASS, it'd be perfect for this kind of example.

STEP 2

Remove all those if/elsestatements and for loopand make use of your jQuerylibrary for all its got, like the functions addClass() and removeClass(). So what you actually might want to do is have a single HTML element as target for your random color, and chance it's class according to the random color generated. The CSS class will be the one in charge of outputting the appropriate color generated.

In the JScode, all you have to do is get your random color, then clean the HTML element target of your random color, and then add the generated color. (Sorry for such long wording).

Super simple, super cute.

Code snippet for this improvement:

 
var colors = ["red", "yellow", "blue", "green"];

$(document).ready(function() {
  $('#spin-btn').click(function() {
    var output = colors.length,
      randomNumber = Math.floor(Math.random() * output),
      color_container = $('#color-output');

    var color = colors[randomNumber];
    color_container.removeClass(); //Cleanup previous color classes
    color_container.addClass(color);
  });
});
#spin-btn {
  padding: 20px;
  margin-bottom: 10px;
  background-color: #eee;
  cursor: pointer;
}
#color-output {
  width: 100px;
  height: 100px;
}
.default { background: gray; }
.blue {  background: blue;}
.yellow {   background: yellow;}
.red {   background: red; }
.green {   background: green;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="spin-btn">Generate random color</div>
<div id="color-output" class="default"></div>

So if tomorrow you added 100 new colors, you'd just update the colors variable, and add the pertaining CSS classes. Your actual JS code would not change. Yay DRY! (Don't-repeat-yourself).

Adding probability to Code Improvement

In terms of probability and letting the users choose what color most likely should appear, I am basing my answer on this link provided by user Rory in comments to original question.

You'd have to dynamically manipulate your colors variable to include more/less of the colors that the user wants to come out.

You can start off with your default array of colors, then pass it to a function that adds the pertaining colors the users have chosen, then choose a random color based on the manipulated colors array.

For that I've added the following functions (which can be greatly improved to be more dynamic, this is just a stepping stone to get started, I leave the improvement off to you).

    function getColors() {
      var blue_prob = $('#blue-prob').val(), //These are your inputs
        red_prob = $('#red-prob').val();

      var colors = ["red", "yellow", "blue"]; // default colors
      addProbability(colors, blue_prob - 1, "blue"); //blue_prob - 1 because "blue" already appears once
      addProbability(colors, red_prob - 1, "red"); //red_prob - 1 because "red" already appears once
      return colors;
    }

    function addProbability(colors, probability, color) {
      for (let i = 0; i < probability; ++i)
        colors.push(color);
    }

Code snippet for this part:

It's best to run at at full screen, cause the console output will fill it up real quick. So try out the inputs, the default ones, 2for blue and 1 for red, will make blue appear twice and red appear once.

$(document).ready(function() {
  $('#spin-btn').click(function() {
    var colors = getColors();
    var output = colors.length,
      randomNumber = Math.floor(Math.random() * output),
      color_container = $('#color-output');

    console.log(colors);

    var color = colors[randomNumber];
    color_container.removeClass(); //Cleanup previous color classes
    color_container.addClass(color);
  });
});

function getColors() {
  var blue_prob = $('#blue-prob').val(),
    red_prob = $('#red-prob').val();

  var colors = ["red", "yellow", "blue"]; // default colors
  addProbability(colors, blue_prob - 1, "blue"); //blue_prob - 1 because "blue" already appears once
  addProbability(colors, red_prob - 1, "red"); //red_prob - 1 because "blue" already appears once
  return colors;
}

function addProbability(colors, probability, color) {
  for (let i = 0; i < probability; ++i)
    colors.push(color);
}
#spin-btn {
  padding: 20px;
  margin-bottom: 10px;
  background-color: #eee;
  cursor: pointer;
}

#color-output {
  width: 100px;
  height: 100px;
}

.default {
  background: gray;
}

.blue {
  background: blue;
}

.yellow {
  background: yellow;
}

.red {
  background: red;
}

.green {
  background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="spin-btn">Generate random color</div>
<div id="color-output" class="default"></div>
<span>Blue probability</span><input id="blue-prob" value="2" /> <br>
<span>Red probability</span><input id="red-prob" value="1" /> <br>

Things to build upon this existing code

  • Make input more dynamic not just hard-coded blue/red
  • Let users input percentages (10%, 20%, 30%...) then in your code convert that to numbers between 1-10. Take it down a decimal.
  • Error checking (user inputs text, or something like 10.5% ... etc)

Adding color saturation percentages

Here's where SASS would be real magic. Alright, you want percentages too right? Well just expand on the principle of class name. You could have a whole bunch of CSS classes such as

.color-10 { opacity: 0.1; }
.color-20 { opacity: 0.2; }
.color-30 { opacity: 0.3; }

Since you are not using SASSthat's cumbersome to write out in CSS. So I'd suggest to go with inline-styles instead. So instead of having the CSS class give it the opacity, use jQuery to manipulate it. The trick on this is to have the body background on white. Or you'll color will be affected.

EDIT: (explaining why I chose opacity as a simple way to achieve color variation)

The opacity is to make use of the percentages for the color. Opacity changes how opaque an element is. In other words, transparency of the element. It's not the most proper way to do it, but it is simple. So if you set the rectangle red, then make it 50% transparent, the color red will seem "pinkish" , as if you desaturated it. In order for this way to work, the background of the element must be white, or your color will change its hue when you set the opacity of the element.

Simple code snippet:

var colors = ["red", "yellow", "blue", "green"];

$(document).ready(function() {
  $('#spin-btn').click(function() {
    var output = colors.length,
      randomNumber = Math.floor(Math.random() * output),
      color_container = $('#color-output');

    var color = colors[randomNumber],
      percentage = getPercentage();
    console.log(color, percentage);
    color_container.removeClass(); //Cleanup previous color classes
    color_container.addClass(color);
    color_container.css({
      'opacity': percentage
    });
  });


  function getPercentage() {
    return Math.random(); //Work on this, I just spat it out in 5 seconds. Will NOT include 1, full  opacity
  }

});
#spin-btn {
  padding: 20px;
  margin-bottom: 10px;
  background-color: #eee;
  cursor: pointer;
}

#color-output {
  width: 100px;
  height: 100px;
}

.default {
  background: gray;
}

.blue {
  background: blue;
}

.yellow {
  background: yellow;
}

.red {
  background: red;
}

.green {
  background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="spin-btn">Generate random color</div>
<div id="color-output" class="default"></div>

The way I would go about it is by using rgba() which allows a fourth parameter to include the opacity of the color itself.

.blue-40 {
    background-color: rgba(0, 0, 255, 0.40);
}

But I'd use SASS for generating all those CSS rules. If you are not using SASSI'm sure you can use JS to figure out how to get an rgba() color.

Hope this helped :)

Chayemor
  • 3,577
  • 4
  • 31
  • 54
  • @Cheyemor Helps a lot, could you explain why you are using opacity? – Ben Stallwood Jan 15 '18 at 11:38
  • The opacity is to make use of the percentages for the color. Opacity changes how opaque an element is. In other words, transparency of the element. It's not the most proper way to do it, but it is simple. So if you set the rectangle red, then make it 50% transparent, the color red will seem "pinkish" , as if you desaturated it. In order for this way to work, the background of the element must be white, or your color will change it's hue when you set the opacity of the element. – Chayemor Jan 15 '18 at 11:38
  • Okay I see. So with the color-10 color-20 opacity thing. I am not too sure on this part? Does this mean color-10% color-20%? – Ben Stallwood Jan 15 '18 at 11:43
  • very nice coding, but how is this solve the probability issue ? – Ofir G Jan 15 '18 at 11:44
  • Exactly. But writing that out manually is ... well, horrible. That's why I refer to SASS. SASS even has functions to change the color saturation itself instead of adding transparency. – Chayemor Jan 15 '18 at 11:45
  • I have also placed some input fields in my html, where users can choose the percentage of a certain color to be generated. for example, I want blue to be 50%, and red to be 20%, green to be 30%. So this will add up to 100%. So when the user submits the percentages on a button, then presses the generate button, its either going to be 50% chance to show blue, 20% to show red or 30% chance to show green. – Ben Stallwood Jan 15 '18 at 11:46
  • @Chayemor I have set a min and max in the getPercentage function between 1 and 100. What I want is if red is 50%, then randomly generated numbers between 1 and 50 will show the colour red on the output. etc. – Ben Stallwood Jan 15 '18 at 11:58
  • Thank you for pointing that out @OfirG . I had a brain lapse and read the question not for probability problems, but rather percentage for opacity of the colors. I am reconstructing my answer to properly do it. Sorry for the confusion. – Chayemor Jan 15 '18 at 12:18
  • @Chayemor This is perfect! Just what I wanted. I was going towards the same sort of thing with a for loop and colors.push() however mine was a little less efficient, haha :) – Ben Stallwood Jan 15 '18 at 12:38