从中心开始,顺序删除位置行和列上的2D数组中的项目

时间:2014-11-10 22:15:14

标签: c# xna

我的宝石迷阵克隆中有另一个问题。我想让Star Gems像Bejeweled 3中那样表现,这意味着它们会从星形宝石(中心)向外摧毁宝石。所以,明星宝石在10x10二维阵列中处于(4,4);它会先破坏位置(3,4),(5,4),(4,3)和(4,5),然后再说10帧后,破坏(2,4),(6,4) ,(4,2)和(4,6),等等。

现在我有StarDestruction()方法将星形宝石的位置存储到几个Board-scope变量中,以及在List<Gem>中销毁的位置,如下所示:

Board.starPosX = i;
Board.starPosY = j;
for (int x = 0; x < gems.GetLength(0); x++)
{
    moveTimer = 0;
    int k = x;
    int m = x;
    int q = x;
    int n = x;
    if (i - k < 0) k = 0;
    if (i + m > gems.GetLength(0) - 1) m = 0;
    if (j - q < 0) q = 0;
    if (j + n > gems.GetLength(1) - 1) n = 0;
    gemQ.Add(gems[i - k, j]);
    gemQ.Add(gems[i + m, j]);
    gemQ.Add(gems[i, j - q]);
    gemQ.Add(gems[i, j + n]);
}

其中gemQList<Gem>,而宝石是2D宝石数组。

这就是我目前在Update()中摧毁宝石的方式:

foreach (Gem g in gemQ)
{
    if (timer2 % 12 == 0)
        g.KillGem(gems[starPosX, starPosY]);
}

其中timer2是用于销毁宝石的计时器。

我有一些简单的原始宝石破坏代码,但它似乎与这个版本的工作方式不同。这是更简单的代码:

for (int x = 0; x < gems.GetLength(0); x++)
{
    if (x != i)
    {
        gems[x, j].KillGem(gems[i, j]);
    }
    if (x != j)
    {
        gems[i, x].KillGem(gems[i, j]);
    }
}

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

根据我们在评论中的对话,完整修改我的回复。

我现在明白了:

  

你希望明星宝石能够摧毁与星形宝石在同一列和同一行中的所有其他宝石。   你想要一次销毁四颗宝石,每四颗宝石之间有一个延迟。   爆炸应该从恒星宝石向外移动,即首先摧毁最近的宝石。

你的foreach使用这样的时间:

Timer % 12 == 0

对于一个宝石来说,对于所有这些宝石来说都是如此。你也不想在破坏之间拖延,否则破坏不会被渲染或游戏明显滞后。

第二个问题是,即使你确实消除了宝石的破坏,你也可能会发现破坏发生在一个螺旋中,而不是一次发生四次。

考虑到这些要点,您需要改为:

// The initial destroy gem code
var gemsToDestroy = new List<Gem>();
for (int x = 0; x < gems.GetLength(0); x++)
{
    if (x != i)
    {
        gemsToDestroy.add(gems[x, j]);
    }
    if (x != j)
    {
        gemsToDestroy.add(gems[i, x]);
    }
}

// You can change your for loop above to achieve this directly, but this is the idea
// We are putting them in order of closest first.
gemsToDestroy = gemsToDestroy.OrderBy(o => o.DistanceFromStar).ToList();

// Your periodic UPDATE code - This is pseudo code but should convey the general idea
// I've been very lazy with my use of LINQ here, you should refactor this solution to 
// to remove as many iterations of the list as possible.
if (gemsToDestroy.Any() && timer.Ready)
{
    var closestDistance = gemsToDestroy[0].DistanceFromStar;

    foreach (var gem in gemsToDestroy.Where(gem => gem.DistanceFromStar == closestDistance))
    {
        gem.Destroy();
    }

    // Again you can do this without LINQ, point is I've removed the now destroyed gems from the list
    gemsToDestroy = gemsToDestroy.Where(gem => gem.DistanceFromStar != closestDistance).ToList();

    timer.Reset(); // So that we wait X time before destroying the next set
}

当gemsToDestroy列表中有项目时,不要忘记阻止玩家输入,并且在销毁时停止游戏计时器,这样玩家就不会因为游戏时间而受到惩罚。