首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现递归

实现递归
EN

Code Review用户
提问于 2013-05-14 18:06:58
回答 1查看 216关注 0票数 1

该方案的规则是:

  • 生成n×n网格。
  • 任意选择一个点,并在初始点的基础上形成一个“形状”。
  • 必须至少有3分。
  • 强烈偏倚不完全填充网格。
代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;

namespace ShapeTestInConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Shape.Initialize(4, 4);
            Shape shape = new Shape();
            Draw(shape);
            Console.ReadLine();
        }

    private static void Draw(Shape shape)
    {
        for (var x = 0; x < Shape.Width; x++)
        {
            for (var y = 0; y < Shape.Height; y++)
            {
                Console.Write("|");
                Console.Write(" " + shape.ShapeDefinition[x, y].ToString() + " ");
                Console.Write("|");
            }
            Console.Write("\n");
            for (var i = 0; i < Shape.Width * 5; i++)
                Console.Write("_");
            Console.Write("\n");
        }
    }
}
public class Shape
{
    private static readonly Random _random;

    private static readonly Tuple<int, int>[] _adjacent = new[]
        {
            Tuple.Create(0,-1),
            Tuple.Create(1,0),
            Tuple.Create(0,1),
            Tuple.Create(-1,0)
        };

    public byte[,] ShapeDefinition { get; private set; }

    public static int Width { get; private set; }
    public static int Height { get; private set; }

    static Shape()
    {
        _random = new Random();
    }

    public Shape()
    {
        ShapeDefinition = new byte[Width, Height];

        //Place seed point
        ShapeDefinition[_random.Next(0, Width), _random.Next(0, Height)] = 1;
        var activePoints = 1;

        var starts = new List<Point>();
        var neighbors = new List<Point>();
        var neighborsToActivate = new List<Point>();

        Build(starts, neighbors, neighborsToActivate, activePoints, 0, 1);

    }

    public static void Initialize(int width, int height)
    {
        Width = width;
        Height = height;
    }

    private void Build(List<Point> starts, List<Point> neighbors, List<Point> neighborsToActivate,
        int activePoints, int runCount, int currentLevel)
    {                    
        // Ditch if...  Has bias for 4 X 4 grid
        if (activePoints >= (Width * Height) || runCount > 5 || currentLevel >= 5)
            return;
        // minimum 3 points desired
        if (activePoints >= 3 && activePoints < 6)
        {
            if (_random.Next(0, 9) == 2)
                return;
        }
        else if (activePoints >= 6 && activePoints < 8)
        {
            if (_random.Next(0, 6) == 2)
                return;
        }
        else if (activePoints >= 8)
        {
            if (_random.Next(0, 5) == 2)
                return;
        }

        starts.Clear();
        // Gather points 
        for (var x = 0; x < ShapeDefinition.GetLength(0); x++)
            for (var y = 0; y < ShapeDefinition.GetLength(1); y++)
            {
                if (ShapeDefinition[x,y] == currentLevel)
                    starts.Add(new Point(x,y));
            }

        neighbors.Clear();
        // with each start get adjacent usable point
        foreach (var currentStartPoint in starts)
        {
            for (var i = 0; i < _adjacent.Length; i++)
            {
                var neighborX = currentStartPoint.X + _adjacent[i].Item1;
                var neighborY = currentStartPoint.Y + _adjacent[i].Item2;

                if (InBounds(neighborX, neighborY))
                {
                    if (ShapeDefinition[neighborX, neighborY] == 0)
                        neighbors.Add(new Point(neighborX, neighborY));
                }
            }
            neighborsToActivate.Clear();
            // randomly pick which usable point(s) will be include with shape
            neighborsToActivate = neighbors.OrderBy(n => _random.Next())
                                           .Take(_random.Next(1, neighbors.Count + 1))
                                           .ToList();

            for (var j = 0; j < neighborsToActivate.Count; j++)
            {
                ShapeDefinition[neighborsToActivate[j].X, neighborsToActivate[j].Y] = (byte)(currentLevel + 1);
                activePoints++;
            }
        }

        runCount++;
        currentLevel++;
        Build(starts, neighbors, neighborsToActivate, activePoints, runCount, currentLevel);
    }

    private static bool InBounds(int x, int y)
    {
        return x >= 0 && x < Width &&
               y >= 0 && y < Height;
    }
}
}

这是我现在想要完成的事情的一个很好的传真。我自己对改进的想法是这种形状,因为我想如何使用它,不应该有创建自己的方法,而应该由ShapeFactory或ShapeBuilder类来创建。形状的唯一工作就是做一个形状。

EN

回答 1

Code Review用户

回答已采纳

发布于 2013-05-16 12:43:40

  1. runCountCurrentLevel似乎是多余的。
  2. 我不明白为什么要将startneighborsneighborsToActivate作为参数传递给递归函数,因为您不需要使用数据就可以清除它们。
  3. activePoint可能更好地成为形状的一员,因为这些信息在其他地方也可能有用。
  4. 我会让Draw成为Shape的一种方法,因为它与Shape密切相关。

现在,您要将形状存储为网格中的“活动”点。还可以将形状存储为点的列表,例如{(2,3),(3,3),(3,4)}。我并不是说它在这里更好,但是对于某些应用程序来说,这可能是一个更好的选择,特别是如果您有一个非常大的网格,并且很少有活动点。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/26166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档