斐波那契盒子

4
我知道在Stack Overflow和网络上有很多关于斐波那契问题的问答,但这是一个困扰我已久的问题,我似乎无法解决或找到解决方案。
创建斐波那契算法足够容易,有很多方法,但我正在尝试使用C#以螺旋形式图形化地创建盒子。这不是为了大学或其他任何事情,只是一个问题,我已经花费了太多时间,现在需要找到解决方案,如果你知道我的意思?
以下是我目前所拥有的内容,我曾经有更好的配置,但在反复修订代码数小时后,这就是我目前拥有的:
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();
    }

我从维基百科上获取了一张图像,这就是我试图以图形方式创建的内容:

斐波那契方块

提前感谢。


  1. 你实际的问题是什么?
  2. 如果这不是一个 UI 的问题,你能给我们一些可以运行的代码吗?
- asafrob
你在绘图部分遇到了问题吗?将方框链接在一起有困难吗? - Adriaan Stander
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)));
}

输出:

在此输入图片描述


谢谢,经过一些微调和更改,我现在得到了完全符合我的要求的东西 ;) - Draconian Times
@DraconianTimes 你是正确的。我现在将right初始化为1,输出结果是正确的,此外,我添加了一些缩放来创建一个更好的图片(见打印屏幕) - Vincent van der Weele
完美!我稍微修改了一下,但这正是我想要的。不确定我是否会尝试将黄金螺旋放在方框中,可能太难了哈哈。 - Draconian Times

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();
        }
    }
}

请注意,我已经用一个性能更好的斐波那契函数替换了你的函数;特别是,我的函数可以在线性时间内计算下一个斐波那契数。 通过一些数学魔法(抱歉开个玩笑 :)),你甚至可以让它变得更加智能化,并获得以下结果。
    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();
        }
    }

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]=0fib[1]=1for(i = 2;i<=n;i++)fib[i]=fib[i-1]+fib[i-2])会不是更好,这将在 O(n) 而不是 O(n*(1.7^n)) 的时间内工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接