Need help altering an algorithm

前端 未结 1 1103
挽巷
挽巷 2021-01-29 11:46

I need to make a that scans every pixel on the screen.

I am currently using this:

public static void Spiral()
{

    // starting point
    x = ((int)Math.F         


        
1条回答
  •  没有蜡笔的小新
    2021-01-29 12:02

    Let's turn this into a simple sequence of points.

    We know that we are going in one of four directions.

    var steps = new (int dx, int dy)[] { (1, 0), (0, 1), (-1, 0), (0, -1) };
    

    To create a spiral we move the first direction once, then the second once; then the next two twice, then the next two three times, then the next two four times, etc. If we hit the end of the list we then cycle back to the start. So if we start with n = 0 then we repeat each direction n / 2 + 1 times (knowing that this is integer maths).

    Here's my Spiral generator method:

    public IEnumerable Spiral(int x, int y)
    {
        yield return new Point(x, y);
        var steps = new(int dx, int dy)[] { (1, 0), (0, 1), (-1, 0), (0, -1) };
        var i = 0;
        var n = 0;
        while (true)
        {
            for (var j = 0; j < n / 2 + 1; j++)
            {
                var (sx, sy) = steps[i];
                x += sx;
                y += sy;
                yield return new Point(x, y);
            }
            if (++i >= steps.Length)
                i = 0;
            n++;
        }
    }
    

    The first 50 points (i.e. Spiral(0, 0).Take(50)) are then this:

    (0, 0), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1), (2, -1), (2, 0), (2, 1), (2, 2), (1, 2), (0, 2), (-1, 2), (-2, 2), (-2, 1), (-2, 0), (-2, -1), (-2, -2), (-1, -2), (0, -2), (1, -2), (2, -2), (3, -2), (3, -1), (3, 0), (3, 1), (3, 2), (3, 3), (2, 3), (1, 3), (0, 3), (-1, 3), (-2, 3), (-3, 3), (-3, 2), (-3, 1), (-3, 0), (-3, -1), (-3, -2), (-3, -3), (-2, -3), (-1, -3), (0, -3), (1, -3), (2, -3), (3, -3), (4, -3)

    Now, it's super easy to generate the spiral you want.

    If I assume that you're starting at the middle of the screen, then this is it:

    IEnumerable query =
        Spiral(1920 / 2, 1080 / 2)
            .Where(z => z.X >= 0 && z.X < 1920)
            .Where(z => z.Y >= 0 && z.Y < 1080)
            .Take(1920 * 1080);
    

    If we want to verify with the smaller screen as given in your question, the that looks like this:

    IEnumerable query =
        Spiral(0, 0)
            .Where(z => z.Y >= -1 && z.Y <= 1)
            .Where(z => z.X >= -2 && z.X <= 2)
            .Take(5 * 3);
    

    That gives:

    (0, 0), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1), (2, -1), (2, 0), (2, 1), (-2, 1), (-2, 0), (-2, -1)


    Here it is wrapped up in a single method:

    public static void Spiral()
    {
        IEnumerable SpiralPoints(int x, int y)
        {
            yield return new Point(x, y);
            var steps = new(int dx, int dy)[] { (1, 0), (0, 1), (-1, 0), (0, -1) };
            var i = 0;
            var n = 0;
            while (true)
            {
                for (var j = 0; j < n / 2 + 1; j++)
                {
                    var (sx, sy) = steps[i];
                    x += sx;
                    y += sy;
                    yield return new Point(x, y);
                }
                if (++i >= steps.Length)
                    i = 0;
                n++;
            }
        }
    
        var w = Screen.PrimaryScreen.Bounds.Width;
        var h = Screen.PrimaryScreen.Bounds.Height;
        var l = Screen.PrimaryScreen.Bounds.Left;
        var r = Screen.PrimaryScreen.Bounds.Right;
        var t = Screen.PrimaryScreen.Bounds.Top;
        var b = Screen.PrimaryScreen.Bounds.Bottom;
    
        foreach (Point point in SpiralPoints(w / 2, h / 2)
            .Where(z => z.X >= l && z.X < r)
            .Where(z => z.Y >= t && z.Y < b)
            .Take(w * h))
        {
            /* Do Stuff With Each Point Here */
        }
    
    }
    

    0 讨论(0)
提交回复
热议问题