Need help altering an algorithm

前端 未结 1 1089
挽巷
挽巷 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<Point> 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<Point> 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<Point> 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<Point> 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)
提交回复
热议问题