Чтобы отменить выбор одного и того же элемента дважды, примените следующую стратегию:
Получите все элементы, перемешайте их, а затем возьмите 16 первых из этой перемешанной коллекции. Затем примените стили / изображения, как вы sh для этих 16.
Чтобы реализовать саму перетасовку массива, вы можете «одолжить» эффективную реализацию из здесь
Вот простой способ сделать это:
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>
Если теперь у вас разные классы CSS, то вы можете просто расширить его следующим образом:
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>