Java 根据单元格查找路径';二维栅格阵列上的值

Java 根据单元格查找路径';二维栅格阵列上的值,java,algorithm,swing,2d,path-finding,Java,Algorithm,Swing,2d,Path Finding,我有一个由JLabel组成的网格。每个单元有3种状态: 公共枚举令牌{ 维德,红血球,蓝血球 } 空单元格==Token.VIDE 我有一个简单的算法,找到给定单元的所有邻居,然后使用swing自定义绘制,沿着以标签中心为点的路径绘制多边形 private CellsList getNeighbors(int row, int col) { CellsList neighbors = new CellsList(); for (int colNum = col - 1 ; co

我有一个由JLabel组成的网格。每个单元有3种状态: 公共枚举令牌{ 维德,红血球,蓝血球 } 空单元格==Token.VIDE

我有一个简单的算法,找到给定单元的所有邻居,然后使用swing自定义绘制,沿着以标签中心为点的路径绘制多边形

private CellsList getNeighbors(int  row, int col) {
    CellsList neighbors = new CellsList();
    for (int colNum = col - 1 ; colNum <= (col + 1) ; colNum +=1  ) {
        for (int rowNum = row - 1 ; rowNum <= (row + 1) ; rowNum +=1  ) {
            if(!((colNum == col) && (rowNum == row))) {
                if(withinGrid (rowNum, colNum )  ) {
                    neighbors.add( new int[] {rowNum, colNum});
                }
            }
        }
    }

    return neighbors;
}
现在,我想通过添加条件使其更精确,例如,如果在邻域中至少有4个单元格具有相同的值,并且至少有一个相反的值,则路径可能有效

例如: 如果(11,10)(10,11)(11,12)(12,11)处至少有一个蓝色细胞,则(11,11)处的红细胞可以形成有效路径。(见下图)

并且以下路径无效,因此没有图形:

目前,该算法只找到我定义的最小值(
int-MIN_-path_-LEGTH=3
)的路径,但找不到定义第二个条件的方法(邻域中至少有一个相反的单元格值)


如果需要,我将使用新元素进行编辑。

也许您可以创建一个蓝色单元格和红色单元格的列表,如果您想测试红色单元格路径中是否有蓝色单元格,请执行以下操作:

往北走,直到你遇到一个红细胞或地图限制:如果这是一个地图限制,你用下一个蓝细胞测试,否则你回到你的位置,对东,南,西做同样的事情。 如果在4条边上首先找到一个红色单元格,则返回true,否则返回false


如果你想在一个很小的地图上进行测试,这就足够了。但是如果红细胞形成的形状是自由的,我找不到更好的方法。

也许你可以列出蓝细胞和红细胞,如果你想测试红细胞路径中是否有蓝细胞,你可以:

往北走,直到你遇到一个红细胞或地图限制:如果这是一个地图限制,你用下一个蓝细胞测试,否则你回到你的位置,对东,南,西做同样的事情。 如果在4条边上首先找到一个红色单元格,则返回true,否则返回false


如果你想在一个很小的地图上进行测试,这就足够了。但是,如果红细胞生成的形状可以是自由的,我找不到更好的方法。

如果红细胞的路径正常,则在调用此方法之前进行测试:

public boolean isThereABlueCellWithinMyRedPath() {
    // height = height of your map
    // width = width of yout map
    // this array is suppose to be in an other place...
    Cell[][] cellArray = new Cell[height][width];
    // ... so are those two lists
    List<Cell> blueCellsList = new ArrayList<>();
    List<Cell> redCellsList = new ArrayList<>();

    //foreach blueCell on the map ...
    for (Cell blueCell : blueCellsList) {
        boolean north = false;
        boolean east = false;
        boolean south = false;
        boolean west = false;
        int originX = blueCell.getX();
        int originY = blueCell.getY();

        // ... if there is a redCell at north...
        for (int i = originY; i >= 0; i--) {
            if (redCellsList.contains(cellArray[originX][i])) {
                north = true;
                break;
            }
        }
        // ... East ...
        for (int i = originX; i < cellArray[originX].length; i++) {
            if (redCellsList.contains(cellArray[i][originY])) {
                east = true;
                break;
            }
        }
        // ... South ...
        for (int i = originY; i < cellArray.length; i++) {
            if (redCellsList.contains(cellArray[originX][i])) {
                south = true;
                break;
            }
        }
        // ... West ...
        for (int i = originX; i >= 0; i--) {
            if (redCellsList.contains(cellArray[i][originY])) {
                west = true;
                break;
            }
        }
        // ... I am surrended by redCell
        if (south && east && north && west)
            return true;
    }
    return false;
}
public boolean isThereABlueCellWithinMyRedPath(){
//高度=地图的高度
//宽度=地图的宽度
//假设此数组位于其他位置。。。
单元格[][]光线=新单元格[高度][宽度];
//……这两张名单也是
List blueCellsList=new ArrayList();
List redCellsList=new ArrayList();
//地图上的每个蓝细胞。。。
for(单元格blueCell:blueCellsList){
布尔北=假;
布尔东=假;
布尔南=假;
布尔西=假;
int originX=blueCell.getX();
int originY=blueCell.getY();
//…如果北边有红细胞。。。
对于(int i=originY;i>=0;i--){
if(redCellsList.contains(ceralray[originX][i])){
北=真;
打破
}
}
//…东。。。
对于(int i=originX;i=0;i--){
if(redCellsList.contains(cillary[i][originY])){
西=真;
打破
}
}
//…我被红细胞投降了
if(南、东、北、西)
返回true;
}
返回false;
}

我没有尝试该代码,但它似乎有效。

如果redCell的路径正常,则在调用此方法之前进行测试:

public boolean isThereABlueCellWithinMyRedPath() {
    // height = height of your map
    // width = width of yout map
    // this array is suppose to be in an other place...
    Cell[][] cellArray = new Cell[height][width];
    // ... so are those two lists
    List<Cell> blueCellsList = new ArrayList<>();
    List<Cell> redCellsList = new ArrayList<>();

    //foreach blueCell on the map ...
    for (Cell blueCell : blueCellsList) {
        boolean north = false;
        boolean east = false;
        boolean south = false;
        boolean west = false;
        int originX = blueCell.getX();
        int originY = blueCell.getY();

        // ... if there is a redCell at north...
        for (int i = originY; i >= 0; i--) {
            if (redCellsList.contains(cellArray[originX][i])) {
                north = true;
                break;
            }
        }
        // ... East ...
        for (int i = originX; i < cellArray[originX].length; i++) {
            if (redCellsList.contains(cellArray[i][originY])) {
                east = true;
                break;
            }
        }
        // ... South ...
        for (int i = originY; i < cellArray.length; i++) {
            if (redCellsList.contains(cellArray[originX][i])) {
                south = true;
                break;
            }
        }
        // ... West ...
        for (int i = originX; i >= 0; i--) {
            if (redCellsList.contains(cellArray[i][originY])) {
                west = true;
                break;
            }
        }
        // ... I am surrended by redCell
        if (south && east && north && west)
            return true;
    }
    return false;
}
public boolean isThereABlueCellWithinMyRedPath(){
//高度=地图的高度
//宽度=地图的宽度
//假设此数组位于其他位置。。。
单元格[][]光线=新单元格[高度][宽度];
//……这两张名单也是
List blueCellsList=new ArrayList();
List redCellsList=new ArrayList();
//地图上的每个蓝细胞。。。
for(单元格blueCell:blueCellsList){
布尔北=假;
布尔东=假;
布尔南=假;
布尔西=假;
int originX=blueCell.getX();
int originY=blueCell.getY();
//…如果北边有红细胞。。。
对于(int i=originY;i>=0;i--){
if(redCellsList.contains(ceralray[originX][i])){
北=真;
打破
}
}
//…东。。。
对于(int i=originX;i=0;i--){
if(redCellsList.contains(cillary[i][originY])){
西=真;
打破
}
}
//…我被红细胞投降了
if(南、东、北、西)
返回true;
}
返回false;
}

我没有尝试代码,但它似乎有效。

我的答案是基于一篇文章中发布的代码

路径类
添加
isWithinLoop
以检查单元格是否在路径内
    //returns a collection of all cells that are bounded by the path 
    //and their token is of the opposite color of the path 
    List<int[]> getContainedWithin() {

        //find path max and min X values, max and min Y values
        minPathRow = grid[0].length; //set min to the largest possible value
        maxPathCol = grid.length;
        maxPathRow = 0;              //set max to the largest possible value
        maxPathCol = 0;

        //find the actual min max x y values of the path
        for (int[] cell : this) {
            minPathRow = Math.min(minPathRow, cell[0]);
            minPathCol = Math.min(minPathCol, cell[1]);
            maxPathRow = Math.max(maxPathRow, cell[0]);
            maxPathCol = Math.max(maxPathCol, cell[1]);
        }

        //todo remove after testing
        System.out.println("x range: "+minPathRow + "-" 
        + maxPathRow + " y range: " + minPathCol + "-" + maxPathCol);

        List<int[]> block = new ArrayList<>(25);
        int[] cell = get(0);//get an arbitrary cell in the path
        Token pathToken = grid[cell[0]][cell[1]]; //keep a reference to its token

        //iterate over all cells within path x, y limits
        for (int col = minPathCol; col < (maxPathCol); col++) {

            for (int row = minPathRow; row < (maxPathRow); row++) {

                //check cell color
                Token token = grid[row][col];
                if ((token == pathToken) || (token == Token.VIDE)) {
                    continue;
                }
                if (isWithinLoop(row,col)) {
                    block.add(new int[] {row, col});
                }
            }
        }

        return block;
    }

    //check if row, col represent a cell with in path by checking if it has a 
    //path-cell to its left, right, top and bottom 
    private boolean isWithinLoop(int row, int col) {

        if(  isPathCellOnLeft(row, col)
             &&
             isPathCellOnRight(row, col)
             &&
             isPathCellOnTop(row, col)
             &&
             isPathCellOnBottom(row, col)
          ) {
            return true;
        }

        return false;
    }

    private boolean isPathCellOnLeft(int cellRow, int cellCol) {

        for ( int col = minPathCol; col < cellCol ; col++) {

            if(getPath().contains(new int[] {cellRow, col})) {
                return true;
            }
        }

        return false;
    }

    private boolean isPathCellOnRight(int cellRow, int cellCol) {

        for ( int col = cellCol; col <= maxPathCol ; col++) {

            if(getPath().contains(new int[] {cellRow, col})) {
                return true;
            }
        }

        return false;
    }

    private boolean isPathCellOnTop(int cellRow, int cellCol) {

        for ( int row =minPathRow; row < cellRow ; row++) {

            if(getPath().contains(new int[] {row, cellCol})) {
                return true;
            }
        }

        return false;
    }

    private boolean isPathCellOnBottom(int cellRow, int cellCol) {

        for ( int row = cellRow; row <= maxPathRow; row++) {

            if(getPath().contains(new int[] {row, cellCol})) {
                return true;
            }
        }

        return false;
    }
}
List<int[]> getContainedWithin() {

    return (path == null ) ? null : path.getContainedWithin();
} 
private class ModelListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            IndexedPropertyChangeEvent iEvt = (IndexedPropertyChangeEvent)evt;
            int index = iEvt.getIndex();
            int row = index / Model.COLS;
            int col = index % Model.COLS;
            Token token = (Token) evt.getNewValue();

            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {

                    view.setCell(token, row, col);
                    CellsList path = model.getPath();
                    //ignore path if null, empty or encloses no cell
                    if((path == null) || path.isEmpty()
                                        || model.getContainedWithin().isEmpty()) {
                        return;
                    }
                    view.addPath(path);
                    view.refresh();
                }
            });
        }
    }