4

我知道堆栈溢出和一般网络上有很多斐波那契问题和答案,但这是一个困扰我一段时间的问题,我似乎无法破解它或找到解决方案。

创建斐波那契算法很容易,其中有很多,但我正在尝试使用 C# 以图形方式创建螺旋形的盒子。这不适用于 Uni 或其他任何东西,这只是一个我花了太多时间解决的问题,我现在需要找到解决方案,如果你知道我的意思吗?

这是我到目前为止所得到的,现在我确实有一个更好的配置,但是经过无数小时的修改代码,这就是我目前所拥有的:

public partial class Form1 : Form
{
    public const int FIBNUM = 6;
    public const int CENTRE = 10;
    public const int SIZE = 10;
    public const int OFFSET = 100;

    public Form1()
    {
        InitializeComponent();

        drawSpiral();
    }

    private int fib(int n)
    {
        switch (n)
        {
            case 0:
                return 0;
            case 1:
                return 1;
            default:
                return fib(n - 1) + fib(n - 2);
        }
    }

    private void drawSpiral()
    {
        if (pictureBox1.Image == null)
        {
            pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        }

        using (Graphics g = Graphics.FromImage(pictureBox1.Image))
        {
            Rectangle r = new Rectangle(0, 0, 0, 0);

            int fibnum = 0;
            int centre = 0;
            int size = 0;
            int cnt = 0;

            for (int n = 1; n <= FIBNUM; n++)
            {
                fibnum = fib(n);
                centre = fibnum * CENTRE;
                size = fibnum * SIZE;

                ++cnt;
                if (cnt == 1)
                {
                    if (n == 1)
                    {
                        r = new Rectangle(fibnum + OFFSET, fibnum + OFFSET, size, size);
                        g.DrawRectangle(Pens.Red, r);

                        r = new Rectangle((fibnum + size) + OFFSET, fibnum + OFFSET, size, size);
                        g.DrawRectangle(Pens.Purple, r);

                        n++;
                    }
                    else
                    {
                        r = new Rectangle((centre - size) + OFFSET, (centre - size) + OFFSET, size, size);        
                        g.DrawRectangle(Pens.Black, r);
                    }
                    continue;
                }
                if(cnt == 2)
                {
                    r = new Rectangle((fibnum) + OFFSET, (fibnum - size) + OFFSET, size, size);
                    g.DrawRectangle(Pens.Blue, r);
                    continue;
                }
                if (cnt == 3)
                {
                    r = new Rectangle((fibnum - size) + OFFSET, (fibnum - size) + OFFSET, size, size);
                    g.DrawRectangle(Pens.Green, r);

                    continue;
                }
                if (cnt == 4)
                {
                    r = new Rectangle((fibnum - size / 2) + OFFSET, (fibnum - size) + OFFSET, size, size);
                    g.DrawRectangle(Pens.Gray, r);
                }
                cnt = 0;       
            }
        }
        pictureBox1.Invalidate();
    }

我从 wikipedia 中获取了我正在尝试以图形方式创建的图像:

纤维盒

提前致谢。

4

3 回答 3

3

我认为您的代码太复杂了,因为您尝试一次做很多事情。考虑以下代码,其中螺旋线围绕原点绘制,没有缩放和平移:

// the current fibonacci numbers
int current = 1;
int previous = 0;

// the current bounding box
int left = 0;
int right = 1;
int top = 0;
int bottom = 0;

// the number of boxes you want to draw
const int N = 10;

for (int i = 0; i < N; i++) {
    switch (i % 4) {
        case 0: // attach to bottom of current rectangle
            drawRectangle(g, left, right, bottom, bottom + current);
            bottom += current;
            break;
        case 1: // attach to right of current rectangle
            drawRectangle(g, right, right + current, top, bottom);
            right += current;
            break;                
        case 2: // attach to top of current rectangle
            drawRectangle(g, left, right, top - current, top);
            top -= current;
            break; 
        case 3: // attach to left of current rectangle
            drawRectangle(g, left - current, left, top, bottom);
            left -= current;
            break; 
    }

    // update fibonacci number
    int temp = current;
    current += previous;
    previous = temp;
}

然后,您可以在单独的方法中处理实际的绘图部分drawRectangle(我省略了有关实际图形对象的所有细节,但您可能自己也可以这样做)。

const int SCALE = 5;
const int OFFSET = 150;

private void drawRectangle(Graphics g, int left, int right, int top, int bottom)
{
    g.DrawRectangle(Pens.Red, new Rectangle(SCALE * left + OFFSET, 
                                            SCALE * top + OFFSET, 
                                            SCALE * (right - left),
                                            SCALE * (bottom - top)));
}

输出:

在此处输入图像描述

于 2013-08-08T08:29:13.787 回答
1

干得好 :

public partial class Form1 : Form
{
    public const int FIBNUM = 8;
    public const int CENTERX = 300;
    public const int CENTERY = 300;
    public const int ZOOM = 10;

    public Form1()
    {
        InitializeComponent();
        drawSpiral();
    }

    private int fib(int n, int p = 0, int q = 1)
    {
        switch (n)
        {
            case 0: return 0;
            case 1: return q;
            default: return fib(n - 1, q, p + q);
        }
    }

    private void drawSpiral()
    {
        if (pictureBox1.Image == null)
        {
            pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        }

        using (Graphics g = Graphics.FromImage(pictureBox1.Image))
        {
            Rectangle r = new Rectangle(0, 0, 0, 0);

            int x = CENTERX;
            int y = CENTERY;

            for (int n = 1; n <= FIBNUM; n++)
            {
                int fibnum = fib(n)*ZOOM;

                r = new Rectangle(x, y, fibnum, fibnum);
                g.DrawRectangle(Pens.Red, r);

                switch (n % 4)
                {
                    case 0:
                        {
                            y += fibnum;
                            break;
                        }
                    case 1:
                        {
                            x += fibnum;
                            y -= fib(n - 1) * ZOOM;
                            break;
                        }
                    case 2:
                        {
                            x -= fib(n - 1)*ZOOM;
                            y -= fib(n + 1)*ZOOM;
                            break;
                        }
                    case 3:
                        {
                            x -= fib(n + 1) * ZOOM;
                            break;
                        }
                }
            }
            pictureBox1.Invalidate();
        }
    }
}

请注意,我已将您的斐波那契函数更改为性能更好的函数;特别是,我的计算线性时间的下一个斐波那契数。使用一些 MatheMagic (抱歉这个笑话 :) )你可以让它更聪明,并获得

    private int move(int n, int a, int currentFib)
    {
        switch (a)
        {
            case 1: return currentFib;
            case 2: return -fib(n - 1) * ZOOM;
            case 3: return -fib(n + 1) * ZOOM;
            default: return 0;
        }
    }

    private void drawSpiral()
    {
        if (pictureBox1.Image == null)
        {
            pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        }

        using (Graphics g = Graphics.FromImage(pictureBox1.Image))
        {
            Rectangle r = new Rectangle(0, 0, 0, 0);

            int x = CENTERX;
            int y = CENTERY;

            for (int n = 1; n <= FIBNUM; n++)
            {
                int fibnum = fib(n)*ZOOM;

                r = new Rectangle(x, y, fibnum, fibnum);
                g.DrawRectangle(Pens.Red, r);

                x += move(n, n % 4, fibnum);
                y += move(n, (n + 1) % 4, fibnum);
            }
            pictureBox1.Invalidate();
        }
    }
于 2013-08-08T09:36:46.350 回答
0
private int fib(int n)
{
    switch (n)
    {
        case 0:
            return 0;
        case 1:
            return 1;
        default:
            return fib(n - 1) + fib(n - 2);
    }
}

这已经足够慢了,也许在这个任务中并不重要,但是使用一个不会在其中工作的数组fib[1..n]fib[0]=0 fib[1]=1 for(i = 2;i<=n;i++)fib[i]=fib[i-1]+fib[i-2])不是更好吗?O(n)O(n*(1.7^n))

于 2013-08-08T09:12:52.320 回答