Javascript 画布上的两个(任意)区域:找出哪个更大

Javascript 画布上的两个(任意)区域:找出哪个更大,javascript,canvas,html5-canvas,easeljs,Javascript,Canvas,Html5 Canvas,Easeljs,我最近开始一起学习canvas+easeljs,现在我正在做一个2D游戏。 玩家(红色小矩形)可以在画布上移动,当他“离开”(不靠近)边界时,线就在他身后画 当他到达下一个边界时,这条线停止了自己的绘制——这将创建由这条线分隔的两个区域 在这一点上,我需要计算出每个区域与其他区域相比有多大 所以我需要弄清楚的是: 哪个区域更小/更大 计算每个区域的球数(红色小圆圈) 后面绘制的网格只是为了更容易理解UI背后的逻辑:0表示空格(白色矩形),2表示灰色矩形(边框和我们的线) 我尝试通过在整个画布

我最近开始一起学习canvas+easeljs,现在我正在做一个2D游戏。 玩家(红色小矩形)可以在画布上移动,当他“离开”(不靠近)边界时,线就在他身后画

当他到达下一个边界时,这条线停止了自己的绘制——这将创建由这条线分隔的两个区域

在这一点上,我需要计算出每个区域与其他区域相比有多大

所以我需要弄清楚的是:

  • 哪个区域更小/更大
  • 计算每个区域的球数(红色小圆圈)
后面绘制的网格只是为了更容易理解UI背后的逻辑:0表示空格(白色矩形),2表示灰色矩形(边框和我们的线)

我尝试通过在整个画布上“循环”来计算每个区域中的零,但效果不太好,因为需要在每个区域之间小心切换

有没有更好的办法解决这个问题?也许是通过递归的方式

如果我不够清楚,请不要犹豫,询问更多信息。 很抱歉标题不好,我不知道该怎么说才能更清楚

期待任何建议,谢谢


编辑1:游戏与此类似:

一种可能但相当无效的方法:

  • 为便于理解,请反转您的表示。设灰色单元格为0,白色单元格为1
  • 玩家返回边界时触发区域标识。制作游戏场的临时副本。遍历整个字段,直到找到一个带有1的单元格。开始计算大小:(记住对复制的字段进行所有值更改!)

  • 在这里,您可以尝试递归方法。选择“1”单元格并将1添加到计数器变量。将单元格切换为0,然后查看任何相邻单元格。对于值为“1”的任何单元格,递归分支

  • 现在的情况是,你从一个区域开始,开始用“墙”填充该区域,同时记住你填充了多少字段。由于从边界向外分支,您应该在不离开区域边界的情况下,通过前进到邻居来命中任何包含的字段

  • 当区域“完成”(所有字段都变为0,所有递归分支都返回)时,您的计数器变量表示区域的大小。在前面的步骤中,您还可以在遍历区域时检查红球,以计数它们

  • 要转到下一个区域,只需再次开始迭代整个字段,直到达到1,然后重复前面的步骤

  • 当您在整个字段上迭代,但没有找到任何1时,您计算了所有区域并完成了计算

正如所警告的那样,这种方法非常无效,但我现在想不出更好的方法来避免陷入复杂的困境


更新有关澄清,请参阅此答案的评论以供参考

一个区域递归单元求值的伪代码:

int areaSize = 0;
//find the first starter cell to detect first area
Cell starter = findCellWithValue1();
//if starter is null, no cell with value 1 has been found
if( starter != null ) {
   //feed the starter cell into the recursive function
   areaSize = evaluateCell(starter);
}

int evaluateCell(Cell selected) {
    //counter variable to accumulate branched values
    int counter = 1;
    //set this cell to 0 to not hit it again when evaluating neighbours
    selected.setValue(0);

    //check neighbour to the left
    Cell neighbour = getCellAt(selected.getX()-1, selected.getY());
    if(neighbour.getValue()==1) {
        counter += evaluateCell(neighbour);
    }
    //check neighbour to the right
    neighbour = getCellAt(selected.getX()+1, selected.getY());
    if(neighbour.getValue()==1) {
        counter += evaluateCell(neighbour);
    }
    //check top neighbour
    neighbour = getCellAt(selected.getX(), selected.getY()+1);
    if(neighbour.getValue()==1) {
        counter += evaluateCell(neighbour);
    }
    //check bottom neighbour
    neighbour = getCellAt(selected.getX(), selected.getY()-1);
    if(neighbour.getValue()==1) {
        counter += evaluateCell(neighbour);
    }

    //return accumulated size
    return counter;
}
这将执行很多最终不必要的检查,但我认为它们不会太贵,除非你计划拥有一个巨大的运动场


区域的最终大小将是areaSize变量的内容。

请分享您有问题的代码。我对任何特定行或其他内容都没有问题-我只是不确定采取什么方法。目前的代码是500多行,所以发布它可能不是很有用。你能更好地解释你的游戏吗。所以玩家在移动时不知何故制造了障碍墙?@markE Correct。他在身后创建了一堵墙,所以现在球只能在这堵墙创建的一个区域内移动。每次他创建一堵墙,我都要弄清楚哪堵墙更大/更小,它是否包含一个球。游戏将类似于这个编辑过的问题。问题是,你怎么知道你来到了第二个区域?你所做的线,可以在到达“边界”之前到达任何地方。所以弄明白这一点可能会很奇怪,它并不总是一个矩形——即使它是,你怎么知道你来到了第二区?对不起,我在这里有点困惑。第一:使用所提出的算法,区域可以是任何形状,只要一个区域的白色区域都至少在侧面接触。第二:在评估一个领域时,你不会“来到”第二个领域。您的区域都由0包围,因此当您在评估区域时从1跳到1时,您将永远不会超出此周围边界。当您删除复制字段上的第一个区域时,您只能进入第二个区域,然后再次开始搜索任何其他区域。将尝试实现您今天提出的建议,并让您知道-好的,我对您的算法有问题。在这一部分中,您将看到“1”单元格->,并查看任何相邻单元格。递归地分支出任何值为“1”的单元格->如何查看相邻单元格?你每次都要检查所有的邻居吗?是的。否则你会错过角逐的机会。我会用一点伪代码更新我的答案。