0

I have grid of 10 X 10 squares and I am using a random function to assign classes to the squares to give some of them different classes/images upon load.

$.fn.random = function() {
  var n = this.eq(Math.floor(Math.random() * this.length));
  // window.alert(this.eq(Math.floor(Math.random() * this.length)));
  return n;
}
$('a').random().addClass("snowman");

I have 16 of these random assignments.

More often than not, some of the random images are placed on top of each each other and therefore become hidden. I thought about removing all classes of the random piece and then adding the class of ('X') for example,

$('a').random().removeClass().addClass("snowman");

but it didn't work.

Is there any easy way to do this?

Karan
  • 12,059
  • 3
  • 24
  • 40
Johnroiste
  • 71
  • 1
  • 7
  • 2
    You'll need to "know" if it can be used - either by storing (in an array for example) which ones have already been used, or extending your `.random` to exclude those with a specific class - or just `$('a:not(.snowman)')...` (with checks for "none") – freedomn-m Jul 13 '20 at 11:05

2 Answers2

1

To void that you select the same element twice, apply the following strategy:

Get all the elements, shuffle them, and then take the 16 first of that shuffled collection. Then apply the styling/images as you wish for those 16.

To implement the array shuffling itself, you can "lend" an efficient implementation from here

Here is a simple way to do it:

function shuffle(a) {
    for (let i = a.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1));
        let temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    return a;
}

$.fn.filterRandom = function (count) {
    return $(shuffle(this.get()).slice(0, count));
}

// Clear styling, and choose 16 TD elements from the table
//    and reapply styling:
$("td").removeClass().filterRandom(16).addClass("yellow");
table { border-collapse: collapse }
td { border: 1px solid; width: 15px; height: 15px }
.yellow { background: yellow }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>

If now you have different CSS classes, then you can just extend like this:

function shuffle(a) {
    for (let i = a.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1));
        let temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    return a;
}

function pickRandom(arr) {
    return arr[Math.floor(Math.random() * arr.length)];
}

$.fn.filterRandom = function (count) {
    return $(shuffle(this.get()).slice(0, count));
}

// Clear styling, and choose 16 TD elements from the table
//    and reapply styling, choosing a class randomly for each:
$("td").removeClass().filterRandom(16).each(function () {
    $(this).addClass(pickRandom(["red","yellow","blue"]));
});
table { border-collapse: collapse }
td { border: 1px solid; width: 15px; height: 15px }
.yellow { background: yellow }
.blue { background: blue }
.red { background: red }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</table>
trincot
  • 317,000
  • 35
  • 244
  • 286
1

I would suggest to loop over each a and assign class randomly.

You can have one array like classArray which holds all your 16 classes as you've mentioned in question.

Then loop over each a with $('a').each((i, item) and use randomClass. Here I have pick class from random index.

If you want some of the a left unassigned then use * 2 here Math.floor(Math.random() * classArray.length * 2);. If you want every a should assign class then remove * 2 from it.

Try it below.

let classArray = ['red', 'green', 'blue'];

$.fn.randomClass = function() {
  let n = Math.floor(Math.random() * classArray.length * 2);
  if (n < classArray.length) {
    this.addClass(classArray[n]);
  }  
}

$('a').each((i, item) => $(item).randomClass());
div.cell {
  display: inline-flex;
  width: 30px;
  height: 30px;
  border: 1px solid;
}

.red {
  background-color: red;
  width: 100%;
}
.green {
  background-color: green;
  width: 100%;
}
.blue {
  background-color: blue;
  width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>

<div>
  <div class='cell'><a href='#'>  </a></div>
  <div class='cell'><a href='#'>  </a></div>
  <div class='cell'><a href='#'>  </a></div>
</div>
<div>
  <div class='cell'><a href='#'></a></div>
  <div class='cell'><a href='#'></a></div>
  <div class='cell'><a href='#'></a></div>
</div>
<div>
  <div class='cell'><a href='#'></a></div>
  <div class='cell'><a href='#'></a></div>
  <div class='cell'><a href='#'></a></div>
</div>
Karan
  • 12,059
  • 3
  • 24
  • 40