C# - 需要帮助创建程序,通过绘制线条模拟Prime数字行为

时间:2015-08-08 02:12:48

标签: c# numbers drawing line primes

我挑战自己创建一个程序来试验Prime数字,我已经知道如何去做,但不是编码技巧..

我的计划是这样的: 首先在C#中创建一个程序,使得直线遵循一些规则:

规则1:所有行都有相同的长度。

规则2:所有行都是水平或垂直(没有对角线)。

规则3:每一个新行都从前一行结束的地方开始(这​​样就会连接所有行)。

现在是棘手的部分:

我想创建一个计数器,每次创建一个新行时起始值为1(起始值为1我设定),每当它达到素数时,行改变'方向'并开始'前进'在原方向的左边。

前10行看起来像这样:

      |
 __   |
|  |  |
|__ __|

注意它是如何改变第2,第3,第5和第7行的方向。

(从内部结束开始)

这会产生一条很长的扭曲线,看看它是什么样的图案会非常酷。

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

这是一个有趣的项目。谢谢你早上的娱乐!

我在this SO thread中使用了SLaks代码来获取小于指定数字的Primes列表。

以下是一些示例输出:

Example Output #1 Example Output #2 Example Output #3

生成Primes后,我走了列表并将行存储在GraphicsPath中。使用Graphics.GetBounds()方法,我们可以在Panel的Paint()事件中适当地缩放和转换Graphics,以便可以看到整个绘图:

public partial class Form1 : Form
{

    private const int segmentLength = 10;
    private GraphicsPath gpPrimes = null;

    public Form1()
    {
        InitializeComponent();
        nudLessThanMax.Minimum = 15;
        nudLessThanMax.Maximum = 500000;
        nudLessThanMax.Value = nudLessThanMax.Minimum;
        pnlPrimes.Paint += PnlPrimes_Paint;
        pnlPrimes.SizeChanged += PnlPrimes_SizeChanged;
    }

    private void PnlPrimes_SizeChanged(object sender, EventArgs e)
    {
        pnlPrimes.Invalidate();
    }

    private void PnlPrimes_Paint(object sender, PaintEventArgs e)
    {
        if (gpPrimes != null)
        {
            RectangleF rectF = gpPrimes.GetBounds();
            float max = Math.Max(rectF.Width + (2 * segmentLength), rectF.Height + (2 * segmentLength));
            e.Graphics.TranslateTransform(pnlPrimes.Width / 2, pnlPrimes.Height / 2);
            e.Graphics.ScaleTransform((float)pnlPrimes.Width / max, (float)pnlPrimes.Height / max);
            e.Graphics.TranslateTransform(-(rectF.Left + rectF.Width / 2), -(rectF.Top + rectF.Height / 2));
            e.Graphics.DrawPath(Pens.Black, gpPrimes);
        }
    }

    private void btnGraphPrimes_Click(object sender, EventArgs e)
    {
        btnGraphPrimes.Enabled = false;
        backgroundWorker1.RunWorkerAsync((int)this.nudLessThanMax.Value);
    }

    private List<int> PrimesLessThan(int num) // SLaks: https://stackoverflow.com/a/1510186/2330053
    {
        return Enumerable.Range(0, (int)Math.Floor(2.52 * Math.Sqrt(num) / Math.Log(num))).Aggregate(
            Enumerable.Range(2, num - 1).ToList(),
            (result, index) =>
            {
                var bp = result[index]; var sqr = bp * bp;
                result.RemoveAll(i => i >= sqr && i % bp == 0);
                return result;
            }
        );
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        int diff;
        int num = (int)e.Argument;
        Point pt = new Point(0, 0);
        Point pt2 = pt;
        GraphicsPath gp = new GraphicsPath();
        List<int> primes = PrimesLessThan(num);

        for(int i = 1; i < primes.Count; i++)
        {
            diff = primes[i] - primes[i - 1];
            switch(i % 4)
            {
                case 1: // up
                    pt2 = new Point(pt.X, pt.Y - (segmentLength * diff));
                    break;

                case 2: // left
                    pt2 = new Point(pt.X - (segmentLength * diff), pt.Y);
                    break;

                case 3: // down
                    pt2 = new Point(pt.X, pt.Y + (segmentLength * diff));
                    break;

                case 0: // right
                    pt2 = new Point(pt.X + (segmentLength * diff), pt.Y);
                    break;
            }
            gp.AddLine(pt, pt2);
            pt = pt2;
        }
        gpPrimes = gp;
        e.Result = primes;
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        lbPrimes.DataSource = (List<int>)e.Result;
        pnlPrimes.Invalidate();
        btnGraphPrimes.Enabled = true;
    }

}

答案 1 :(得分:1)

我再次希望我有足够的分数让这只是一个评论,但我想确保你提前知道这不会导致sprial一路走来。有两对素数只有2个(n,n + 2都是素数),这将使你的蛇做180并自我交叉。

如果你没问题,那么请查看System.Drawing命名空间,尤其是在Graphics.Drawline方法中。或者看看一些有助于为您提供正确想法的代码。只需将一个pictureBox放在Windows窗体中,此代码就会在其上添加一行。从那里你可以处理你的笔颜色,比例,找到你的素数等。

        Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.DrawLine(new Pen(Color.Red), 300, 100, 100, 100);
        }
        pictureBox1.Image = bmp;