寻找如何重构我的算法的想法

时间:2010-04-18 14:55:30

标签: c# .net algorithm design-patterns

我正在尝试使用自己的一套规则来编写自己的Game of Life。我想申请的第一个“概念”是社会化(这基本上意味着细胞想要独处还是与其他细胞组成)。数据结构是二维数组(暂时)。

为了能够将一个细胞移动到一组另一个细胞,我需要确定移动细胞的位置。我的想法是,我评估区域中的所有单元格(邻居)并获得一个向量,它告诉我在哪里移动单元格。矢量的大小为0或1(不移动或移动),角度为方向阵列(向上,向下,向右,向左)。

这是一个代表细胞的力的图像,就像我想象的那样(但是达到的可能超过5):

ForceAppliedToACell http://img293.imageshack.us/img293/2852/29186643.png

让我们举个例子:

Example http://img683.imageshack.us/img683/7357/70002678.png

Forces from lower left neighbour: down (0), up (2), right (2), left (0)
Forces from right neighbour     : down (0), up (0), right (0), left (2)
sum                             : down (0), up (2), right (0), left (0)

所以细胞应该上升。

我可以编写一个包含很多if语句的算法,并检查邻域中的所有单元格。当然,如果'reach'参数设置为1(图1中的第一列),该算法将是最简单的。但是如果我将覆盖参数更改为10怎么办?我需要事先为每个'达到'参数编写一个算法...我怎么能避免这种情况(注意,力量正在增长(1,2,4,8,16,32 ......)) ?我可以针对这个问题使用特定的设计模式吗?

另外:最重要的不是速度,而是能够扩展初始逻辑。

需要考虑的事项:

  • 到达应作为参数传递
  • 我想改变函数,它计算力(潜力,斐波那契)
  • 只有在未填充此新地点时,单元格才能转到新地点
  • 注意角落(例如,您无法评估右上角的右邻居和顶级邻居)

2 个答案:

答案 0 :(得分:4)

编写算法以搜索特定单元格C的到达距离内的所有单元格应该不难。每个拥有居民的细胞都会在细胞C上产生特定的排斥力。这种排斥力基于从细胞到细胞C的距离。在您给出的示例中,排斥力基于L-1距离并且为2^(reach-distance)。然后将每个排斥力加在一起以产生累积力,该力决定了居民在单元格C中移动的方向。

您无需为每个不同的覆盖范围编写算法。力的大小可以通过简单的公式确定。如果您将该公式更改为其他内容,例如斐波纳契数,您仍然可以根据距离和范围来计算所需的幅度。


以下是一些用伪Java编写的粗略代码,显示了基本思想:http://codepad.org/K6zxnOAx

enum Direction {Left, Right, Up, Down, None};

Direction push(boolean board[][], int testX, int testY, int reach)
{
    int xWeight = 0;
    int yWeight = 0;
    for (int xDist=-reach; xDist<=+reach; ++xDist)
    {
        for (int yDist=-reach; yDist<=+reach; ++yDist)
        {
            int normDist = abs(xDist) + abs(yDist);
            if (0<normDist && normDist<reach)
            {
                int x = testX + xDist;
                int y = testY + yDist;
                if (0<=x && x<board.length && 0<=y && y<board[0].length)
                {
                   if (board[x][y])
                   {
                       int force = getForceMagnitude(reach, normDist);
                       xWeight += sign(xDist) * force;
                       yWeight += sign(yDist) * force;
                   }
                }
            }
        }
    }
    if (xWeight==0 && yWeight==0) return Direction.None;
    if (abs(xWeight) > abs(yWeight))
    {
        return xWeight<0 ? Direction.Left : Direction.Right;
    }
    else
    {
        return yWeight<0 ? Direction.Up : Direction.Down;
    }
}

int getForceMagnitude(int reach, int distance)
{
    return 1<<(reach-distance);
}

答案 1 :(得分:0)

编写一个循环遍历邻居的函数:

  • 使用min / max来限制矩阵的边界。
  • 使用for循环遍历所有邻居。
  • 修改for循环边界以表示范围。

def CalculateForceOnCell(x, y):
    force_on_x_y = [0,0,0,0]
    for i in range(max(0, x-reach), min(WIDTH, x+reach)+1):
        limited_reach = reach - abs(x-i)
        for j in range(max(0, y - limited_reach), min(HEIGHT, y + limited_reach + 1)):
            force_coefficient = limited_reach + 1
            AddNeighborForce(force_on_x_y, (x, y), (i, j), force_coefficient)
    return force_on_x_y