Reputation: 731
I have a site with different message-boxes. The heads of these boxes should always have a different random color. In order to prevent messages next to each other having the same color, I use splice
to remove the used colors from the array colors
. At some point the array colors
will be empty, which is why the remaining boxes will have no color. How can I "refill" the array, so every element gets a random color?
Here is my page: http://www.tdvk.de/. Yellow is the default head color.
function selectColor() {
var random = Math.floor(Math.random() * colors.length);
return colors.splice( random, 1 )[0];
}
var colors = [ "rgb(199, 179, 78)", "rgb(127, 195, 133)", "rgb(102, 169, 162)", "rgb(132, 122, 224)" ];
var i = 0;
while ( i != colors.length ) {
$( "tr" ).each(function(i) {
var head = $( ".msgHead", this );
head.css( "background-color", selectColor() );
i++;
});
}
if { i = colors.length ) {
/* reset array and continue */
}
Upvotes: 4
Views: 429
Reputation: 534
Instead of hardcoding color combinations, you can generate them on the fly
var usedColors = []
function randomDigit( max ){
return Math.floor( Math.random() * max )
}
function getNewColor(){
var max = 255
var r = randomDigit( max )
var g = randomDigit( max )
var b = randomDigit( max )
if ( !colorUsed( r, g, b ) ) return storeColor( r, g, b )
else return getNewColor()
}
function storeColor( r, g, b ){
usedColors[ r + "," + g + "," + b ] = true
return [ r, g, b ]
}
function colorUsed(r,g,b){
return usedColors[ r + "," + g + "," + b ]
}
var newColor = getNewColor()
Or if you prefer to have them predefined
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
var colors = [ "rgb(199, 179, 78)", "rgb(127, 195, 133)", "rgb(102, 169, 162)", "rgb(132, 122, 224)" ]
function getColors(boxCount){
var colorArr = []
var fullIterations = Math.floor( boxCount / colors.length )
var lastIteration = boxCount - fullIterations * colors.length
for(var x = 0; x < fullIterations; x++){
for(var i = 0; i < colors.length; i++){ var color = colors[ i ]; colorArr.push(color); }
colors = shuffle( colors )
}
for(var x = 0; x < lastIteration; x++){ var color = colors[ x ]; colorArr.push(color); }
colors = shuffle( colors )
return colorArr
}
var newColors = getColors(20)
Upvotes: 0
Reputation: 45155
Your question is leaving out some important details, but I think what you want to do is keep selecting random colors from the array, repeating no values until you've used every color and only then start repeating.
Probably you best solution might be to start with a Fisher-Yates shuffle of your original array and then just select each color in turn until you reach the last color. Then simply reshuffle and start back from the beginning.
So in pseudo-code, you'd have something like this:
shuffleArray
colorIndex = 0;
while still selecting colors
select color at array[colorIndex]
colorIndex++
if (colorIndex > array.length)
colorIndex = 0;
shuffleArray
For example:
// from http://bost.ocks.org/mike/shuffle/
function shuffle(array) {
var m = array.length,
t, i;
// While there remain elements to shuffle…
while (m) {
// Pick a remaining element…
i = Math.floor(Math.random() * m--);
// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
var colorIndex = 0;
var colors = ["rgb(199, 179, 78)", "rgb(127, 195, 133)", "rgb(102, 169, 162)", "rgb(132, 122, 224)"];
var i = 0;
shuffle(colors);
while (i < 8) {
alert(colors[colorIndex++]);
i++;
if (colorIndex >= colors.length) {
shuffle(colors);
colorIndex = 0;
}
}
Note there is one more thing to consider. Regardless of how you do this, there is a possibility that the first element selected from your "refilled" array will be the same as the last element from the previous cycle. You might want to think about how to handle that case.
Upvotes: 1
Reputation: 1009
Given that you're boxes are ordered from top to bottom. Why not select the random color by making sure the color of the previous box (above) is different than the current box. For example:
// remove splice from selectColor, the only thing selectColor needs to do now is select a random color from your list.
var previousColor = null;
$("tr").each(function (element) {
// select random color
var color = selectColor();
// make sure it is different than previous color
while (color === previousColor) selectColor();
// ...
// set element color
// ...
// make sure next element is different
previousColor = color;
});
Upvotes: 0
Reputation: 5984
Instead of using splice
, why not just iterate through them?
var selectedColorIndex = Math.round(Math.random() * colors.length);
function selectColor() {
var random = Math.floor(Math.random() * colors.length);
return colors[selectedColorIndex];
}
Edit: this will now select a random element.
Upvotes: 2
Reputation: 3764
How to refill with the same colors:
if ( i = colors.length ) {
colors = [ "rgb(199, 179, 78)", "rgb(127, 195, 133)", "rgb(102, 169, 162)", "rgb(132, 122, 224)" ];
}
But like others have suggested, there are other ways to do this like wrapping around to the first element again and not splicing, or randomizing which values there are.
Upvotes: 3