Insert randomly but never next to each other

2019-07-19 22:17发布

Based on Insert a div in a random location in a list of divs -- I'm trying to randomly insert some cat photos into a div of non-cat photos:

http://jsfiddle.net/frank_o/QXdL3/21/

But is there a way to prevent the cats from appearing next to each other sequentially? They should be spread out.

JS:

var insertionTemplate = $('.template').find('.image').html(),
    insertionTargetChildren = $('.main').find('.image'),
    insertionFrequency = 3;

var random;
for (var i = 0; i < insertionFrequency; i++) {
    random = Math.floor(Math.random() * insertionTargetChildren.length) + 0;
    insertionTargetChildren.eq(random).append(insertionTemplate);
}

HTML:

<div class="template" style="display: none;">
    <div class="image">
        <img src="http://placekitten.com/75/150" />
    </div>
</div>
<div class="main">
    <div class="image">
        <img src="http://lorempixel.com/75/150" />
    </div>

    <!-- ... -->

</div>

3条回答
家丑人穷心不美
2楼-- · 2019-07-19 22:34

You can shotgun the list, like the above answers, but this is a bit more efficient since you only need to inspect the precise objects you are inserting against, rather than inspecting every image.

Add 2 steps. The first should shuffle the array of images so that they're in a different order every time. The second should create an array of insertion points into the other list. If you don't want cat images to be next to each other, then make sure your list of insertion points, is at least spaced by 2.

You should also use <script type="text/template"> tags for your templates.

http://jsfiddle.net/kf2zU/1/

HTML

<script id="cat-template" type="text/template">
    <div class="image">
        <img src="http://placekitten.com/75/150" />
    </div>
</script>
<script id="img-template" type="text/template">
    <div class="image">
        <img src="http://lorempixel.com/75/150" />
    </div>
</script>
<div class="main">
</div>

JS

var catTemplate = $("#cat-template").html();
var imgTemplate = $("#img-template").html();

//place images into .main
var $main = $(".main");
var numImages = 50;
for (var i = 0; i<numImages; i++){
    $main.append($(imgTemplate));
}

//make a list of cat images for example
var numCatImages = 50;
var cats = [];
for (i = 0; i < numCatImages; i++){
    cats.push($(catTemplate));
}

//shuffle the cat list so they appear in random order
cats = _.shuffle(cats);

//create a list of insertion points
var insertionPoints = [];
var insertionIndex = 0;
var minSpacing = 2;
var maxSpacing = 8;
var spacingRange = maxSpacing - minSpacing;
while(insertionIndex < numImages){
    insertionIndex += Math.floor(Math.random() * spacingRange) + minSpacing;
    insertionPoints.push(insertionIndex);
}

//place cat images at the insertion points
//it's important to start from the end and work your way forward so the previous insertions don't mess with subsequent insertion points
//so we reverse the array of insertion points

insertionPoints = insertionPoints.reverse();
var catIndex = 0;
_.each(insertionPoints, function(insertionIndex, i){
    $main.children().eq(insertionIndex).after(cats[catIndex++]);
});
查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-07-19 22:37

Within your loop you could check to see whether the number generated is equal to the last number that was generated +-1

DEMO http://jsfiddle.net/QXdL3/22/

for (var i = 0; i < insertionFrequency; i++) {
    random = Math.floor(Math.random() * insertionTargetChildren.length) + 0;

    if (random != excludeNumA && random != excludeNumB) {
       insertionTargetChildren.eq(random).append(insertionTemplate);
    }
    excludeNumA = random + 1;
    excludeNumB = random - 1;
}
查看更多
放荡不羁爱自由
4楼-- · 2019-07-19 22:58

I've fixed the issues and made a check to see if the next or previous element is a cat.

var target    = $('.main').find('.image'),
    frequency = 3,
    element   = $();

for (var i = 0; i < frequency; i++) {
    (function getElems() {
        element   = target.eq( Math.floor(Math.random() * target.length) );
        var next  = element.next(),
            prev  = element.prev(),
            all   = element.add(next, prev);

        if (element.hasClass('cat') || next.hasClass('cat') || prev.hasClass('cat')) getElems();
    }());

    var template  = $('.template div').clone(true);
    element.before(template);
}

FIDDLE

查看更多
登录 后发表回答