1

我正在尝试在父画布上随机放置多个子画布。我不希望兄弟画布重叠(或碰撞),所以我使用了一些碰撞检测。

我显然做错了什么,因为有碰撞,但我不能指望它。

我的绘图方法(每秒调用一次)

    private void draw(int args)
    {
        parent.Children.Clear();

        List<MyCanvas> children = fetchManyChildren(100);
        Random rand = new Random();

        foreach (MyCanvas child in children)
        {
            child.xPos = nextDouble(rand, 0, parent.ActualWidth - child.Width);
            child.yPos = nextDouble(rand, 0, parent.ActualHeight - child.Height);

            foreach (MyCanvas sibling in parent.Children)
            {
                while (child.collidesWith(sibling))
                {
                    child.xPos = nextDouble(rand, 0, parent.ActualWidth - child.Width);
                    child.yPos = nextDouble(rand, 0, parent.ActualHeight - child.Height);
                }
            }

            Canvas.SetLeft(child, child.xPos);
            Canvas.SetTop(child, child.yPos);

            parent.Children.Add(child);
        }
    }

几个辅助方法:

    private List<MyCanvas> fetchManyChildren(int amount)
    {
        List<MyCanvas> children = new List<MyCanvas>(amount);

        Random rand = new Random();

        for (int i = 1; i <= amount; i++)
        {
            double size = nextDouble(rand, 1, MAX_SIZE);

            MyCanvas child = new MyCanvas(0, 0, size, size);

            child.Background = randomBrush(rand);

            children.Add(child);
        }

        return children;
    }

    private double nextDouble(Random rand, double min, double max)
    {
        return min + (rand.NextDouble() * (max - min));
    }

一个派生自 Canvas 的类,它允许我为 Canvas 提供 x/y 位置并检查碰撞:

public class MyCanvas : Canvas
{
    public double xPos = 0;
    public double yPos = 0;

    public MyCanvas(double x, double y, double w, double h)
    {
        this.xPos = x;
        this.yPos = y;
        this.Width = w;
        this.Height = h;
    }

    public bool collidesWith(MyCanvas p)
    {
        double bottom = this.yPos + this.Height;
        double top = this.yPos;
        double left = this.xPos;
        double right = this.xPos + this.Width;

        return !((bottom < p.yPos) ||
                 (top > p.yPos + p.Height) ||
                 (left > p.xPos + p.Width) ||
                 (right < p.xPos));
    }
}
4

1 回答 1

2

当您在发生碰撞时更改随机位置时,您忘记返回检查parent.Children...中的所有子项.

你需要类似下面的代码。

请注意,您需要小心....

您应该以某种方式更改您/我的代码以处理无法将您的孩子放置在无人居住区域的情况,即没有任何空闲空间。

当您依靠“随机”数字生成来最终找到“空闲”位置时……发现区域所需的时间和“运气”可能会使您处于需要过度或无限的情况时间量......“找到”空闲区域的更好算法将是可取的。

private void draw(int args)
    {
        parent.Children.Clear();

        List<MyCanvas> children = fetchManyChildren(100);
        Random rand = new Random();

        foreach (MyCanvas child in children)
        {
            while(true)
            {
                // Choose a random place on Canvas we would like to place child

                child.xPos = nextDouble(rand, 0, parent.ActualWidth - child.Width);
                child.yPos = nextDouble(rand, 0, parent.ActualHeight - child.Height);

                // Now see if it collides with ones already on Canvas

                bool bCollisionDetected = false;

                foreach (MyCanvas sibling in parent.Children)
                {
                    bCollisionDetected = child.collidesWith(sibling);

                    if (bCollisionDetected)
                        break;
                }

                if (!bCollisionDetected) // Was able to place child in free position
                    break;
            }

            Canvas.SetLeft(child, child.xPos);
            Canvas.SetTop(child, child.yPos);

            parent.Children.Add(child);
        }
    }
于 2012-10-17T12:11:10.997 回答