Javascript 在画布中随机生成不重复或重叠的对象

Javascript 在画布中随机生成不重复或重叠的对象,javascript,arrays,html,canvas,Javascript,Arrays,Html,Canvas,我如何在地图上生成对象,而不让它们在HTML5画布上占据相同的空间或重叠 X坐标在一定程度上是随机生成的。我想检查数组内部,看看它是否已经存在,以及之后的20个值(考虑宽度),但没有运气 var nrOfPlatforms = 14, platforms = [], platformWidth = 20, platformHeight = 20; var generatePlatforms = function(){ var positiony = 0, type; for (var i

我如何在地图上生成对象,而不让它们在HTML5画布上占据相同的空间或重叠

X坐标在一定程度上是随机生成的。我想检查数组内部,看看它是否已经存在,以及之后的20个值(考虑宽度),但没有运气

var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
  var positiony = 0, type;
  for (var i = 0; i < nrOfPlatforms; i++) {
    type = ~~(Math.random()*5);
    if (type == 0) type = 1;
    else type = 0;
    var positionx = (Math.random() * 4000) + 500 - (points/100);
    var duplicatetest = 21;
    for (var d = 0; d < duplicatetest; d++) {
      var duplicate = $(jQuery.inArray((positionx + d), platforms));
      if (duplicate > 0) {
        var duplicateconfirmed = true;
      }
    }
    if (duplicateconfirmed) {
      var positionx = positionx + 20;
    }
    var duplicateconfirmed = false;
    platforms[i] = new Platform(positionx,positiony,type);
  }
}();
不是这个

......[]...[[]]...[[]]....[]....
我希望这是有道理的

供参考,这里是数组检查前的代码和难度,只是便宜的距离黑客

var nrOfPlatforms = 14,
platforms = [],
platformWidth = 20,
platformHeight = 20;
var generatePlatforms = function(){
  var position = 0, type;
  for (var i = 0; i < nrOfPlatforms; i++) {
    type = ~~(Math.random()*5);
    if (type == 0) type = 1;
    else type = 0;
    platforms[i] = new Platform((Math.random() * 4000) + 500,position,type);
  }
}();

您可以实现一个while循环,该循环尝试插入一个对象,但如果对象发生碰撞,则会自动失败。然后添加一个计数器,并在放置所需数量的成功对象后退出while循环。如果对象靠得很近,此循环可能会运行更长时间,因此您可能还希望为其提供最大的使用寿命。或者您可以实现一个“甚至可以在x和y的地图上放置z对象”来防止它永远运行

下面是这个()的一个例子:

//在随机位置用20x20点填充数组,无重叠
var平台=[],
平台尺寸=20,
平台宽度=200,
平台高度=200;
函数生成平台(k){
var=0,
最大尝试次数=k*10;
while(放置0){
var x=Math.floor(Math.random()*平台宽度),
y=Math.floor(Math.random()*平台高度),
可用=真实;
for(平台中的var点){
if(数学abs(点x-x)
以下是实现网格快照哈希的方法:

var can=document.getElementById(“can”),
ctx=can.getContext('2d'),
wid=罐宽,
hei=罐的高度,
numPlatforms=14,
普拉特维德=20,
普拉特黑=20,
平台=[],
散列={};
对于(var i=0;i
注意,我将x和y值连接起来,并将其用作散列键。这是为了简化检查,并且是唯一可行的解决方案,因为我们将x/y坐标捕捉到特定的增量。如果我们不抓拍,碰撞检查会更复杂

对于大型集合(根据您的标准,似乎不太可能),最好使用排除方法:生成一个包含所有可能位置的数组,然后针对每个“平台”,从数组中随机选取一个项目,然后将其从数组中移除。这类似于你洗牌的方式


编辑-需要注意的一点是,
numPlatforms我使用这段代码搜索数组中的对象,找到了另一个问题()的答案

function search(array, value){
    var j, k;
    for (j = 0; j < array.length; j++) {
        for (k in array[j]) {  
            if (array[j][k] === value) return j;
        }
    }
}
函数搜索(数组、值){
var j,k;
对于(j=0;j
最后,我还重写了一堆代码,以便在其他地方加快速度,更好地回收平台

这是可行的,但缺点是我的平台少了,因为它真的开始变慢了。最后,这是我想要的,但这样做不再可行

var platforms = new Array();
    var nrOfPlatforms = 7;
    platformWidth = 20,  
    platformHeight = 20;
    var positionx = 0;
    var positiony = 0;
    var arrayneedle = 0;
    var duplicatetest = 21;

    function search(array, value){
        var j, k;
        for (j = 0; j < array.length; j++) {
            for (k in array[j]) {  
                if (array[j][k] === value) return j;
            }
        }
    }

    function generatePlatforms(ind){  
        roughx = Math.round((Math.random() * 2000) + 500);
        type = ~~(Math.random()*5);  
        if (type == 0) type = 1;  
        else type = 0;  

        var duplicate = false;

        for (var d = 0; d < duplicatetest; d++) {
            arrayneedle = roughx + d;
            var result = search(platforms, arrayneedle);
            if (result >= 0) {
                duplicate = true;
            }
        }

        if (duplicate = true) {
            positionx = roughx + 20;
        }
        if (duplicate = false) {
            positionx = roughx;
        }
        platforms[ind] = new Platform(positionx,positiony,type);  
    }  

    var generatedplatforms = function(){
        for (var i = 0; i < nrOfPlatforms; i++) {
            generatePlatforms(i);
        };
    }();
var platforms=new Array();
var nRof平台=7;
平台宽度=20,
平台高度=20;
变量x=0;
变量y=0;
var arrayneedle=0;
var检验=21;
函数搜索(数组、值){
var j,k;
对于(j=0;j=0){
重复=正确;
}
}
如果(重复=真){
位置X=粗糙度X+20;
}
如果(重复=错误){
位置x=粗糙度x;
}
平台[ind]=新平台(位置X、位置Y、类型);
}  
var generatedplatforms=函数(){
对于(var i=0;i
您可以使用大数据,生成所有可能性,将每种可能性存储在一个数组中,对数组进行洗牌,
修剪前X项,这是您的非启发式算法

对象是否具有可变宽度?@JasonPerske否固定宽度为20px您可以将它们映射到网格(以20像素的增量捕捉对象),然后跟踪2d散列对象中填充的内容。@shmiddy我该怎么做?仍然存在检查它们是否碰撞或重叠的函数失败的问题,并将其放置在anyway@RudigerKidd我添加了一些JavaScript,应该可以做到这一点。我现在必须尝试一下,我最终找到了答案,但解决方案让它变得非常缓慢。让我们来试一试。感谢you@RudigerKidd哈希几乎总是比在数组中搜索值更快。例外是某些浏览器上的小数据集。
//Fill an array with 20x20 points at random locations without overlap
var platforms = [],
    platformSize = 20,
    platformWidth = 200,
    platformHeight = 200;

function generatePlatforms(k) {
  var placed = 0,
      maxAttempts = k*10;
  while(placed < k && maxAttempts > 0) {
    var x = Math.floor(Math.random()*platformWidth),
        y = Math.floor(Math.random()*platformHeight),
        available = true;
    for(var point in platforms) {
      if(Math.abs(point.x-x) < platformSize && Math.abs(point.y-y) < platformSize) {
        available = false;
        break;
      }
    }
    if(available) {
      platforms.push({
        x: x,
        y: y
      });
      placed += 1;
    }
    maxAttempts -= 1;
  }
}

generatePlatforms(14);
console.log(platforms);
var can = document.getElementById("can"),
    ctx = can.getContext('2d'),
    wid = can.width,
    hei = can.height,
    numPlatforms = 14,
    platWid = 20,
    platHei = 20,
    platforms = [],
    hash = {};

for(var i = 0; i < numPlatforms; i++){
  // get x/y values snapped to platform width/height increments
  var posX = Math.floor(Math.random()*(wid-platWid)/platWid)*platWid,
    posY = Math.floor(Math.random()*(hei-platHei)/platHei)*platHei;

  while (hash[posX + 'x' + posY]){
    posX = Math.floor(Math.random()*wid/platWid)*platWid;
    posY = Math.floor(Math.random()*hei/platHei)*platHei;
  }

  hash[posX + 'x' + posY] = 1; 
  platforms.push(new Platform(/* your arguments */));
}
function search(array, value){
    var j, k;
    for (j = 0; j < array.length; j++) {
        for (k in array[j]) {  
            if (array[j][k] === value) return j;
        }
    }
}
var platforms = new Array();
    var nrOfPlatforms = 7;
    platformWidth = 20,  
    platformHeight = 20;
    var positionx = 0;
    var positiony = 0;
    var arrayneedle = 0;
    var duplicatetest = 21;

    function search(array, value){
        var j, k;
        for (j = 0; j < array.length; j++) {
            for (k in array[j]) {  
                if (array[j][k] === value) return j;
            }
        }
    }

    function generatePlatforms(ind){  
        roughx = Math.round((Math.random() * 2000) + 500);
        type = ~~(Math.random()*5);  
        if (type == 0) type = 1;  
        else type = 0;  

        var duplicate = false;

        for (var d = 0; d < duplicatetest; d++) {
            arrayneedle = roughx + d;
            var result = search(platforms, arrayneedle);
            if (result >= 0) {
                duplicate = true;
            }
        }

        if (duplicate = true) {
            positionx = roughx + 20;
        }
        if (duplicate = false) {
            positionx = roughx;
        }
        platforms[ind] = new Platform(positionx,positiony,type);  
    }  

    var generatedplatforms = function(){
        for (var i = 0; i < nrOfPlatforms; i++) {
            generatePlatforms(i);
        };
    }();