#java #recursion #multidimensional-array
#java #рекурсия #многомерный массив
Вопрос:
Я использую метод, который проходит через 2d-массив, подобный лабиринту, и цель состоит в том, чтобы достичь позиции, содержащей целое число 0. Я могу задокументировать путь, но он не будет перемещаться, он останется в начальной позиции.
Вот пример того, что я подразумеваю под не перемещается:
Please input the size of the board (between 5 and 20):
5
Please choose a starting index from the 4 options below:
Press 1 for "top-left"
Press 2 for "top-right"
Press 3 for "bottom-left"
Press 4 for "bottom-rigth"
Enter your choice:
1
2 1 1 1 4
2 3 4 1 3
1 1 1 2 4
3 0 3 3 2
3 2 3 4 2
Move south 2, Move north 2, Move east 2, Move west 2,
Может кто-нибудь мне помочь, пожалуйста?
Вот мой метод до сих пор:
public static boolean MagicBoard_recursive(int[][] board, int size, int startRow, int startCol) {
boolean solvable = true;
int number = board[startRow][startCol];
int[] moves = {startRow number, startRow-number, startCol number, startCol-number}; // This array contains all the possible moves we can do
for(int i = 0; i < 4; i ) {
// If we reached the position containing the integer 0
if(board[startRow][startCol] == 0) {
solvable = true;
break;
}
if(startRow number > size amp;amp; startRow-number < 0 amp;amp; startCol number > size amp;amp; startCol-number<0) {
solvable = false;
break;
}
solvable = true;
// If we try moving south
if(i == 0) {
//int destinationNumber = board[startRow number][startCol];
// If we move to this position, will we be able to continue, if not, then we try another move
if(startRow number > size) {
solvable = false;
continue;
}
else {
while(solvable) {
startRow =number;
System.out.print("Move south " number ", ");
MagicBoard_recursive(board, size, startRow, startCol);
}
}
}
// If try moving north
else if(i == 1) {
// If we move to this position, will we be able to continue. If not, then we try another move
if(startRow-number < 0) {
solvable = false;
continue;
}
else {
while(solvable) {
startRow -=number;
System.out.print("Move south " number ", ");
MagicBoard_recursive(board, size, startRow, startCol);
}
}
}
// If try moving east
else if(i == 2) {
if(startCol number > size) {
solvable = false;
continue;
}
else {
while(solvable) {
startCol = number;
System.out.print("Move east " number ", ");
MagicBoard_recursive(board, size, startRow, startCol);
}
}
}
// If try moving west
else if(i == 3) {
if(startCol-number < 0) {
solvable = false;
break;
}
else {
while(solvable) {
startCol -=number;
System.out.print("Move west " number ", ");
MagicBoard_recursive(board, size, startRow, startCol);
}
}
}
}
return solvable;
}
Вот изображение, на котором показан пример движения, которое программа будет выполнять для решения доски:
Комментарии:
1. Я чувствую, что вам еще нужно уточнить, как может произойти перемещение. Я все еще не совсем понимаю желаемую механику движения.
2. @OmarAbdelBari, я постараюсь объяснить себя немного лучше. Что мне нужно сделать, так это создать доску, содержащую случайные числа, которые меньше или равны размеру доски, и есть одна позиция, которая содержит целое число 0. В зависимости от начальной позиции, выбранной пользователем, может быть или не быть возможного пути к позиции, содержащей целое число 0. Я должен задокументировать путь, пройденный программой, если это возможно решить. Если нет возможного пути для достижения 0, тогда я должен вернуть false . Мое объяснение понятнее?
3. Что делает законный ход? Например, в # 1 я двигаюсь на юг. Почему он проходит весь путь до нижней части доски в # 2?
4. @NomadMaker Кружок отмечает начальную позицию на доске. Целое число в обведенном квадрате указывает, что круг может перемещать определенное количество квадратов на доске. За один шаг круг может перемещаться на восток, запад, север или юг. На каждом шаге выбранное направление фиксируется. Круг не может сойти с доски. Единственными допустимыми начальными позициями являются четыре угловых квадрата. Доска должна содержать ровно один целевой квадрат с 0 в качестве значения, который может быть расположен в любом месте доски.
5. @Jennifer Я думаю, что есть гораздо более простой способ решить эту проблему, используя очереди и что-то похожее на поиск по ширине.
Ответ №1:
Я думаю, что подход, который вы используете, сложнее, чем должен быть.
Рассмотрим вместо массива int[][], представляющего плату, что-то вроде Tile[][], где Tile — это класс, содержащий следующие свойства.
public class Tile {
boolean visited;
int value; //Maybe short will suffice instead?
}
Цель свойства visited заключается в том, чтобы гарантировать, что вы не будете повторно проверять доступные фрагменты, которые вы уже посещали ранее, как при поиске в ширину или в глубину.
Тогда у вас может быть класс, который использует очередь. Для меня и Java прошло некоторое время, но кандидат кажется ArrayDeque для этой ситуации (из-за его возможности изменения размера). В классе, содержащем ваш метод, вы бы добавили это в качестве члена.
ArrayDeque<TileCoordinate> tilesToVisit = new ArrayDeque<>();
Объект TileCoordinate — это просто класс, содержащий координаты вашего объекта. Вместо этого вы можете поместить координату непосредственно в плитку, если хотите, но я предпочитаю хранить их отдельно.
public class TileCoordinate
{
public int x;
public int y;
public TileCoordinate(int x, int y) {
this.x = x;
this.y = y;
}
}
Тогда вот как это может помочь упростить вашу проблему. Когда пользователь сначала выбирает начальный угол, вы вместо этого вставляете координату в свою очередь, а не обрабатываете ее напрямую. После этого вы можете создать цикл, который посещает любую координату, находящуюся в очереди.
//Get input regarding starting corner from user then,
tilesToVisit.add(new TileCoordinate(x, y)); //Insert coordinate corner into queue
while (!tilesToVisit.isEmpty amp;amp; solvable == false) {
TileCoordinate tileToVisit = tilesToVisit.removeFirst();
Visit(tileToVisit); //This is where your business logic happens
}
//If loop is completed before solvable is set to true, this means it's not solvable
Затем в вашем методе обработки вы хотели бы применить свою логику перемещения, чтобы определить, что еще нужно посетить в вашей очереди.
public static void Visit(TileCoordinate coord) {
Tile tile = board[coord.x, coord.y];
tile.visited = true; //Make sure you do this first so you don't process this again later!
if (tile.value == 0) {
//mark solvable to true, which would be a class state variable
}
//Foreach tile that is reachable from this tile where visited = false, add into your queue 'unvisitedReachableTileCoordinate'
tilesToVisit.Add(unvisitedReachableTileCoordinate);
}
Прошу прощения, я давно не кодировал Java, и моя настройка netbeans испорчена. Однако я просмотрел многие из этих функций в документации oracle, поэтому в целом это должно работать. Это должно дать вам общее представление об этом подходе.