9

我已经将代码从 javascript 翻译成 c#,可以通过访问http://fractal.qfox.nl/dragon.js的这个优秀演示找到它

我的翻译是为了在点击按钮时只产生一条龙,但我想我在我的版本中遗漏了一些东西。
有关更多信息,请参阅 Wikipedia 文章:Dragon Curve

不完整的龙分形输出: 生病的龙 代码:

public partial class MainPage : UserControl
{
    PointCollection pc;

    Int32[] pattern = new Int32[] { 1, 1, 0, 2, 1, 0, 0, 3 };
    Int32[] position = new Int32[] { 0, 0, 0, 0, 0, 0, 0, 0 };
    Boolean toggle;
    Char r = default(Char);

    Int32 distance = 10; // line length
    Int32 step = 100; // paints per step
    Int32 skip = 10; // folds per paint

    Double x = 0;
    Double y = 0;
    Int32 a = 90;


    public MainPage()
    {
        InitializeComponent();
    }


    private void btnFire_Click(object sender, RoutedEventArgs e)
    {

        x = canvas.ActualWidth / 3;
        y = canvas.ActualHeight / 1.5;

        pc = new PointCollection();

        var n = step;
        while (--n > 0)
        {
            List<Char> s = getS(skip);
            draw(s);
        }

        Polyline p = new Polyline();
        p.Stroke = new SolidColorBrush(Colors.Red);
        p.StrokeThickness = 0.5;

        p.Points = pc;
        canvas.Children.Add(p);
    }


    List<Char> getS(Int32 n)
    {
        List<Char> s1 = new List<Char>();
        while (n-- > 0) s1.Add(getNext(0));
        return s1;
    }


    void draw(List<Char> s)
    {        
        pc.Add(new Point(x, y));
        for (Int32 i = 0, n = s.Count; i < n; i++)
        {
            pc.Add(new Point(x, y));
            Int32 j;
            if (int.TryParse(s[i].ToString(), out j) && j != 0)
            {
                if ((a + 90) % 360 != 0)
                {
                    a = (a + 90) % 360;
                }
                else
                {
                    a = 360; // Right
                }
            }
            else
            {
                if (a - 90 != 0)
                {
                    a = a - 90;
                }
                else
                {
                    a = 360; // Right
                }
            }
            // new target
            if (a == 0 || a == 360)
            {
                y -= distance;
            }
            else if (a == 90)
            {
                x += distance;
            }
            else if (a == 180)
            {
                y += distance;
            }
            else if (a == 270)
            {
                x -= distance;
            }

            // move
            pc.Add(new Point(x, y));
        }

    }

    Char getNext(Int32 n)
    {
        if (position[n] == 7)
        {
            r = getNext(n + 1);
            position[n] = 0;
        }
        else
        {
            var x = position[n] > 0 ? pattern[position[n]] : pattern[0];

            switch (x)
            {
                case 0:
                    r = '0';
                    break;
                case 1:
                    r = '1';
                    break;
                case 2:
                    if (!toggle)
                    {
                        r = '1';
                    }
                    else
                    {
                        r = '0';
                    }
                    toggle = !toggle;
                    break;
            }
            position[n] = position[n] + 1;                
        }

        return r;
    }

}
4

1 回答 1

4

我清理了代码,并试图了解patternandposition数组应该如何工作以产生正确的序列,但我无法弄清楚。pattern例如,数组中的最后一项从未使用过...

getNext然而,有一个更简单的方法,只使用一个计数器来实现该方法:

bool getNext() {
  cnt++;
  return (cnt & ((cnt & -cnt) << 1)) != 0;
}

我以前(大约 20 年前)使用过这种方法,我在龙曲线维基百科页面上找到了这个实现。

使用此实现清理后的代码getNext如下所示:

public partial class MainPage : UserControl {
    PointCollection pc;

    int cnt = 0;

    int distance = 10; // line length
    int steps = 1024; // number of paints

    int x = 0;
    int y = 0;
    int a = 90;


    public MainPage() {
        InitializeComponent();
    }


    private void btnFire_Click(object sender, RoutedEventArgs e) {

        x = (int)(canvas.ActualWidth / 3);
        y = (int)(canvas.ActualHeight / 1.5);

        pc = new PointCollection();

        draw(getS(steps));

        Polyline p = new Polyline();
        p.Stroke = new SolidColorBrush(Colors.Red);
        p.StrokeThickness = 0.5;

        p.Points = pc;
        canvas.Children.Add(p);
    }


    List<bool> getS(int n) {
        List<bool> s1 = new List<bool>();
        while (n-- > 0) {
            s1.Add(getNext());
        }
        return s1;
    }


    void draw(List<bool> s) {
        pc.Add(new Point(x, y));
        foreach (bool z in s) {

            a = (a + (z ? 90 : 270)) % 360;

            // new target
            switch (a) {
                case 90: x += distance; break;
                case 180: y += distance; break;
                case 270: x -= distance; break;
                default: y -= distance; break;
            }

            // move
            pc.Add(new Point(x, y));
        }

    }

    bool getNext() {
        cnt++;
        return (cnt & ((cnt & -cnt) << 1)) != 0;
    }

}
于 2011-10-09T12:21:44.733 回答