【发布时间】:2018-08-05 11:14:51
【问题描述】:
(我希望这不是重复,因为我遇到的许多问题不符合我的需要)
我正在开发一个基于 2D 网格的游戏,其中有 2 名玩家使用网格。有两个玩家:蓝色和红色,每个人在牢房里放一块石头。所以我想找到一条穿过所有具有相同颜色的单元格返回起点的路径,但前提是至少有一个单元格包含对手的石头。
从上面的截图来看:右上角的红色石头没有形成有效的路径。而那些在中心的人也没有形成一条道路,即使那应该是一条路。
我能够找到一条路径,但它不知何故坏了,它没有按预期工作。
编辑: Pather 类
public class Pather {
private static final int MIN_PATH_LENGTH = 3;
public enum Neighbor{
UP_RIGHT(0,1,-1),
RIGHT(1,1,0),
DOWN_RIGHT(2,1,1),
DOWN(3,0,1),
DOWN_LEFT(4,-1,1),
LEFT(5,-1,0),
UP_LEFT(6,-1,-1),
UP(7,0,-1);
public int index, x, y;
Neighbor(int index, int x, int y){
this.index = index;
this.x = x;
this.y = y;
}
}
private static Neighbor[] neighbors = Neighbor.values();
public static ArrayList<Path> findPaths(Stone[][] gameBoard){
ArrayList<Path> paths = new ArrayList<>();
ArrayList<Point> checkedPoints = new ArrayList<>();
for (int i = 0; i < gameBoard.length ; i++) {
for (int j = 0; j < gameBoard[0].length; j++) {
if(gameBoard[i][j] != null){
//set the origin of a potential new path
ArrayList<Point> potentialPath = new ArrayList<>();
Point origin = new Point (i,j);
if(!checkedPoints.contains(origin)) {
potentialPath.add(origin);
checkedPoints.add(origin);
potentialPath = findPath(gameBoard, i, j, potentialPath, gameBoard[i][j].getPaint(), checkedPoints, Neighbor.RIGHT.index); //Changed from Neighbor.DOWN.index
if (potentialPath != null) {
paths.add(new Path(potentialPath, gameBoard[i][j].getPaint()));
}
}
}
}
}
return paths;
}
private static ArrayList<Point> findPath(Stone[][] gameBoard, int x, int y, ArrayList<Point> path, Paint color, ArrayList<Point> checkedPoints, int cameFrom){
int startClockwiseScanAtDirection = cameFrom + 5;
for (int i = startClockwiseScanAtDirection; i < startClockwiseScanAtDirection + 7; i++) {
// avoid ArrayIndexOutOfBounds
if(x+neighbors[i%8].x < 0 || y+neighbors[i%8].y < 0 || x+neighbors[i%8].x >= gameBoard.length || y+neighbors[i%8].y >= gameBoard[0].length)
continue;
// check if there's a stone that matches the current stone, we're scanning around
if(gameBoard[x+neighbors[i%8].x][y+neighbors[i%8].y] != null && gameBoard[x+neighbors[i%8].x][y+neighbors[i%8].y].getPaint() == color){
// found one
Point nextStone = new Point(x+neighbors[i%8].x,y+neighbors[i%8].y);
// is the point we just found the origin of the path?
if(nextStone.equals(path.get(0)) && path.size() > MIN_PATH_LENGTH) { //This seems to prevent drawing a path when we have less stone to form a path with
path.add(nextStone);
checkedPoints.add(nextStone);
return path;
}
// otherwise if it's already part of the path ignore it
if (path.contains(nextStone)) {
continue;
}
// else add it to the path and keep going
path.add(nextStone);
checkedPoints.add(nextStone);
// recurse on the next stone in the path
ArrayList<Point> newPath = findPath(gameBoard,x+neighbors[i%8].x, y+neighbors[i%8].y, path, color, checkedPoints, i%8);
if (newPath == null){
// didn't find a way to continue, so backtrack
path.remove(path.size()-1);
} else {
// we have a completed path to return
return newPath;
}
}
}
return null;
}
}
路径类
public class Path {
public Paint getColor() {
return color;
}
public void setColor(Paint color) {
this.color = color;
}
public ArrayList<Point> getCoordinateList() {
return coordinateList;
}
public void setCoordinateList(ArrayList<Point> coordinateList) {
this.coordinateList = coordinateList;
}
private ArrayList<Point> coordinateList;
private Paint color;
public Path(ArrayList<Point> coordinatePath, Paint color){
this.coordinateList = coordinatePath;
this.color = color;
}
@Override
public String toString() {
return coordinateList.toString();
}
}
这里有一些案例测试:
在 MainActivity 的 onCreate() 中调用:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gameGrid = findViewById(R.id.gameGrid);
bluePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bluePaint.setStyle(Paint.Style.FILL_AND_STROKE);
bluePaint.setColor(Color.BLUE);
redPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
redPaint.setStyle(Paint.Style.FILL);
redPaint.setColor(Color.RED);
bgrBluePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bgrBluePaint.setStyle(Paint.Style.STROKE);
bgrBluePaint.setStrokeWidth(bgrStrokeWdth);
bgrBluePaint.setColor(Color.BLUE);
bgrRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bgrRedPaint.setStyle(Paint.Style.STROKE);
bgrRedPaint.setStrokeWidth(bgrStrokeWdth);
bgrRedPaint.setColor(Color.RED);
bluePlayer = new Stone(1,bluePaint, bgrBluePaint);
redPlayer = new Stone(2, redPaint, bgrRedPaint);
gameBoard = new Stone[100][100];
gameBoard[47][47]= redPlayer;
gameBoard[46][47]= bluePlayer;
gameBoard[44][48]= redPlayer; //REDs form a path when you place this stone in the last positioon
gameBoard[44][49]= redPlayer;
gameBoard[45][47]= redPlayer;
gameBoard[45][48]= bluePlayer;
gameBoard[45][49]= bluePlayer;
gameBoard[45][50]= redPlayer;
gameBoard[46][50]= bluePlayer;
gameBoard[46][49]= redPlayer;
gameBoard[46][48]= redPlayer;
gameBoard[47][50]= bluePlayer;
gameBoard[47][48]= bluePlayer;
gameBoard[47][49]= redPlayer;
gameBoard[48][50]= redPlayer;
gameBoard[48][49]= redPlayer;
gameBoard[48][48]= redPlayer;
gameBoard[49][50]= bluePlayer;
gameBoard[48][51]= redPlayer;
gameBoard[44][50] = bluePlayer;
ArrayList<Path> paths = Pather.findPaths(gameBoard);
gameGrid.setPaths(paths);
gameGrid.setGameBoard(gameBoard);
}
在以下位置放置石头可以清除路径:
//Adding the following deletes the path
gameBoard[43][50] = redPlayer; //Adding this one in last position clears the path
gameBoard[45][51] = redPlayer;
我需要弄清楚如何创建一个条件,首先检查附近的对手,然后验证路径。
编辑 2:
Stone.java
public class Stone{
private int _player;
private Paint _paint, _bgrPaint;
public Stone(int player, Paint paint, Paint bgrPaint){
_player = player;
_paint = paint;
_bgrPaint = bgrPaint;
}
public int getPlayer() {
return _player;
}
public Paint getPaint() {
return _paint;
}
public Paint get_bgrPaint() {
return _bgrPaint;
}
}
Point.java
public class Point {
int x, y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object point) {
return this.x == ((Point) point).x && this.y == ((Point) point).y;
}
@Override
public String toString() {
return "("+x+","+y+")";
}
}
有效路径的屏幕截图
【问题讨论】:
-
感谢投票者,希望您永远不会遇到这样的情况!如果问题在任何时候都不适合这个社区的内容,请告诉我,我会更正它而不是投反对票,好像它不值得被问或没有任何兴趣一样。这样做你会感觉很强大,不是吗。
-
我认为人们投反对票的原因是因为他们认为这可能是关于家庭作业而不是个人项目。不过不确定 - 我不会做 Java,也帮不上忙,抱歉。
-
我不认为家庭作业可能是这样的!这是一个我正在工作几个月的个人项目!而且我不要求人们为我编写代码,但我需要他们的帮助来看看我没有看到什么,第三人的建议总是有帮助的!大部分都完成了,只是这个算法被破坏了,我需要帮助来弄清楚
-
@Krul 请不要花时间抱怨选票;反对票不必比赞成票更合理。话虽这么说,这可能是因为你没有真正澄清你的问题是什么。您表示您知道您的代码存在一些问题,显然您没有得到您期望的输出,但是您实际上也没有指定。
-
请注意,“家庭作业”与“个人项目”的区别并没有那么重要;重要的是它是否符合帮助网站上的主题概述(这可能会适合一旦清理)和问题的整体质量(现在这读起来就像“这堆东西中有一个错误代码,请帮我找到”类型的问题不是题外话,但很少有有趣的答案)
标签: java android recursion 2d path-finding