递归地在地图上查找地区的“岛屿”

时间:2013-11-26 15:02:38

标签: java recursion

我有一张由六边形字段组成的地图。在这张地图上,每个字段(我们称之为十六进制)属于某个播放器,由坐标定义。

我需要得到某个玩家的咒语List<List<Hex>>。这意味着如果我输入一个玩家拥有的所有六边形的数组,我需要获得有关哪些被组合在一起的信息。

让我说明一下:

Example of a hexagonal field owned by two players

输入 - &gt;绿色播放器的所有格子 - &gt; List<Hex> playersHexes是:

  

{0.0; 0.1; 0.2; 1.0; 1.3; 2.1; 2.3}

输出应为 - &gt;绿色球员的“岛屿”:

  

{0.0; 0.1; 0.2; 1.0},{1.3; 2.3},{2.1}

如何以递归方式实现此目的?我能够找到一些没有问题的Hex的邻居,但这只是针对某个十六进制的一次迭代。

//playersHexes are all the hexes that a player owns
//map is the current map used - contains information about certain hexes
//map is not a HashMap! It's my custom object..
private void findIslands(List<Hex> playersHexes, Map map)
{
    List<Hex> island = new ArrayList<Hex>();
    int curPos = 0;
    for(Hex hex : playersHexes){
        island.add(hex);
        //remove the hex if it's allready gone through it?
        playersHexes.remove(curPos);
        List<Hex> neighbours = map.getNeighboursOf(hex);
        for(Hex neighbour : neighbours)
        {

        }
        //hexList is the output place - the target is to fill hexList with
        //islands(List<Hex>) of hexes..
        this.hexList.add(curPos, island);
        curPos++;
    }
}

任何帮助表示赞赏 - 具有工作递归功能的伪代码就足够了。 谢谢!

3 个答案:

答案 0 :(得分:1)

  • 从一个空的岛屿列表(六边形列表)开始
  • 循环通过属于玩家的有序六边形列表:
  • 对于每个六边形,检查是否属于现有岛屿(与任何岛屿六边形相邻)
  • 如果是:添加到岛上
  • 如果不是:创建一个由六边形组成的新岛屿。

(伪)代码(未测试): 注意:为方便起见使用辅助类Island(OO)。

class Island {

    private final List<Hex> hexes = new LinkedList<Hex>();

    public void add (Hex hex) {
        hexes.add(hex);
    }

    public List<Hex> getHexes () {
        return hexes;
    }

    public boolean isAdjacent (Hex hex) {
        for (Hex h : hexes) {
            if (h.isAdjacent(hex)) {
                return true;
            }
        }
        return false;
    }
}

private List<Island> createIslands (List<Hex> playersHexes,  Map map) {
    Collections.sort(playersHexes); // assuming it's comparable, otherwise use an iterator
    List<Island> islands=new LinkedList<Island>();
    for (Hex hex: playersHexes) {
        Island found=null;
        for (Island island: islands) {
            if (island.isAdjacent(hex)) {
                found=island;
                break;
            }
        }
        if (found==null) {
            found=new Island();
            islands.add(found);
        }
        found.add(hex);
    }
    return islands;
}

答案 1 :(得分:1)

这是我的想法:

private void findIslands(List<Hex> playersHexes, Hex currentHex, Map map, List<Hex> island)
{
  List<Hex> neighbours = map.getNeighboursOf(currentHex);

  // for each neighbour we check if it belongs to player and if it is not already part of this island
  for(Hex neighbour : neighbours) {
     if (!island.contains(neighbour) && playersHexes.contains(neighbour))  {
        island.add(neighbour);

        // now find all connecting neighbours of the current neighbour
        findIslands(playersHexes, neighbour, map, island);
     }
  }
  // now we have in island all connecting Hexes of current hex
}

因此,这将从一个特定的十六进制开始查找所有连接的Hexes。你需要做的就是像这样创造一段时间:

while (Player has hexes that are not islands yet) {
   // call findIsland() on one of those hexes and add the resulting list to your List<List<Hex>>
}

实际执行时你会发现我确定;)

答案 2 :(得分:1)

下面有一些杂乱的伪代码,但这就是我实现它的方式

function main()
  get allIslands for the player
  for each island
    create islandGroup
    process(island, islandGroup, allIslands)



function process(island, islandGroup, allIslands)
  add this island  
  remove this island from the parent list
  getNeighbourIslands(island, allIslands)
  for each neighbourIsland
    process(neighbourIsland, islandGroup, allIslands)

function getNeighbourIslands(island, allIslands)
  return allIslands.getNeighbours(island)

通过传递allIslands列表,你可以确保你不会在同一个岛上解析两次,并且不会陷入无限循环。当递归完成时,你最终应该加载一组IslandGroups

编辑:getNeighbourIslands,应该返回岛上的邻居名单,你不必担心他们的邻居,他们会在以后自己扫描。