2014-08-10 2 views
0

Я пытаюсь написать Knights Walk Algorithm (перебор) с использованием Java. Я смог создать программу для перемещения через сетку 5x5, но программа всегда оставляет вне 06 клеток. И мой Рыцарь не может двигаться никуда от этих квадратов.Алгоритм Walk Knight Walk (Brute Force)

Для примера у меня есть следующие сетки:

---------------- 
a1,b1,c1,d1,e1 

a2,b2,c2,d2,e2 

a3,b3,c3,d3,e3 

a4,b4,c4,d4,e4 

a5,b5,c5,d5,e5 

---------------- 

и мой алгоритм печатает по следующему пути и клетки посетили

a1 -> b3 
b3 -> c5 
c5 -> a4 
a4 -> c3 
c3 -> d5 
d5 -> b4 
b4 -> a2 
a2 -> c1 
c1 -> d3 
d3 -> e5 
e5 -> c4 
c4 -> a3 
a3 -> b5 
b5 -> d4 
d4 -> c2 
c2 -> e3 
e3 -> d1 
d1 -> b2 

Cells Visited : [a1, b3, c5, a4, c3, d5, b4, a2, c1, d3, e5, c4, a3, b5, d4, c2, e3, d1, b2, b2, b2, b2, b2, b2, b2] 

и, как вы можете увидеть сетку еще имеют следующие шесть клетки нетронуты (x отмечены знаками).

---------------- 
x,b1,x,x,e1 

x,x,x,d2,e2 

x,x,x,x,x 

x,x,x,x,e4 

a5,x,x,x,x 

это делает следующие 6 ячеек:

b1,e1,d2,e2,e4,a5 

остается нетронутым, и я не могу показаться, чтобы перейти к любой другой клетке из этих клеток.

Может ли кто-нибудь указать, что я могу делать неправильно? Я дал мой код ниже:

import java.util.ArrayList; 
import java.util.List; 


    public class KnightsWalk { 

String[] colnames = {"a", "b", "c", "d", "e","f","g","h"}; 
String[] rownumbers = {"1", "2", "3", "4", "5","6","7","8"}; 

static final int gridSize = 5; //Specify the grid size here 
static String grid[][] = new String[gridSize][gridSize]; 
static int[][] moves = {{2, 1},{1, 2},{-1,-2},{-2,-1},{2,-1},{-2,1},{-1,2},{1,-2}};//All Possible Moves 

//Visited Cells 
static List<String> visitedCells = new ArrayList<>(); 


private void initGrid() { 

    if (gridSize>=3 || gridSize<=8) { 
     for (int col = 0; col < grid.length; col++) { 
      for (int row = 0; row < grid.length; row++) { 
       grid[row][col] = colnames[col] + rownumbers[row]; 
      } 
     } 
    } else { 
     System.out.println("Grid Size of "+gridSize+" is Not Supported "); 
     System.exit(0); 
    } 

} 

private boolean canMoveToCell(int[] cellvisiting) { 
    try{ 
    //check if the cell visiting has been visited before 
    String cell = grid[cellvisiting[0]][cellvisiting[1]]; 
    boolean canmove = !visitedCells.contains(cell); 
    return canmove; 
    } 
    catch(ArrayIndexOutOfBoundsException ex){ 
     return false; 
    } 
} 

private void walk(int cell[]) { 

    String start = grid[cell[0]][cell[1]]; 
    visitedCells.add(start); //Add the starting cell to already visited 


    if(visitedCells.size() == (gridSize*gridSize)){ 
     return; 
    } 

    int[] nextCellToMoveto = null; 
    for(int[] move:moves){ 
     int[] nc1 = { cell[0]+move[0], cell[1]+move[1] }; 
     if (canMoveToCell(nc1)) { 
      printMove(cell, nc1); 
      nextCellToMoveto=nc1; 
      break; 
     } 
     else{ 
      int[] nc2 = { cell[0]+move[1], cell[1]+move[0] }; 
      if(canMoveToCell(nc2)){ 
       printMove(cell, nc2); 
       nextCellToMoveto=nc2; 
       break; 
      } 
      else{ 
       nextCellToMoveto=cell; 
      } 
     } 
    } 
    walk(nextCellToMoveto); 
} 

public static void main(String[] args) { 
    KnightsWalk gw = new KnightsWalk(); 
    gw.initGrid(); 
    gw.printGrid(); 
    for (int row = 0; row < grid.length; row++) { 
      for (int col = 0; col < grid.length; col++) { 
       int startingcell [] = {row,col}; 
       System.out.println("Cells Visited : "+visitedCells); 
       visitedCells.clear();//Clearing the Previous cells visited when hit a dead end 
       gw.walk(startingcell); 
       System.out.println("Trying with Starting Cell : "+grid[startingcell[0]][startingcell[1]]); 
      } 
     } 
     System.out.println("Cells Visited : "+visitedCells); 
} 

/** 
* Auxiliary Support Methods for user output support 
*/ 
private void printMove(int[] start, int[] end) { 
    System.out.println(grid[start[0]][start[1]] + " -> " + grid[end[0]][end[1]]); 
} 

private void printGrid() { 
    System.out.println("----------------"); 
    for (String[] row : grid) { 
     for (int col = 0; col < grid.length; col++) { 
      String sep = (col < grid.length - 1) ? "," : ""; 
      System.out.print(row[col] + sep); 
     } 
     System.out.println("\n"); 
    } 
    System.out.println("----------------"); 
} 
} 

Update 3 Кодекс Теперь она печатает решение следующим образом:

---------------- 
a1,a2,a3,a4,a5 

b1,b2,b3,b4,b5 

c1,c2,c3,c4,c5 

d1,d2,d3,d4,d5 

e1,e2,e3,e4,e5 

---------------- 

25 of out 25 Cells Visited in the order [a1, c2, a3, b1, d2, e4, c3, b5, d4, e2, c1, a2, b4, d5, e3, d1, b2, a4, c5, b3, a5, c4, e5, d3, e1] 
BUILD SUCCESSFUL (total time: 0 seconds) 

Обновленный код, как показано ниже:

import java.util.ArrayList; 
import java.util.List; 


public class KnightsWalk { 

String[] rownames = {"a", "b", "c", "d", "e", "f", "g", "h"}; 
String[] colnames = {"1", "2", "3", "4", "5", "6", "7", "8"}; 

static final int gridSize = 5; //Specify the grid size here 
static String grid[][]; 
static int[][] moves = {{-2, -1}, {-2, 1}, {2, -1}, {2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}};//All Possible Moves 
static List<String> visitedCells = new ArrayList<>(); //Visited Cells 

int numberOfMoves = 0; 


private void initGrid() { 

    if (gridSize >= 3 && gridSize <= 8) { 
     grid = new String[gridSize][gridSize]; 
     int rownum = 0; 
     for (String[] gridrow : grid) { 
      for (int cell = 0; cell < gridrow.length; cell++) { 
       gridrow[cell] = rownames[rownum] + colnames[cell]; 
      } 
      rownum += 1; 
     } 
    } else { 
     System.out.println("Grid Size of " + gridSize + " is Not Supported "); 
     System.exit(0); 
    } 

} 

private boolean canWalkToCell(int[] cellvisiting) { 

    //check if the cell visiting has been visited before 
    try { 
     //Method chained to return if the cell is in the list 
     String cell = grid[cellvisiting[0]][cellvisiting[1]]; 
     if(visitedCells.contains(cell)){ 
      return false; 
     } 
     else{ 
      return true; 
     } 

    } catch (ArrayIndexOutOfBoundsException ex) { 
     //This is the lazy way to check if the coordinates are in the grid 
     return false; 
    } 
} 

private boolean walk(int cell[]) { 

    String nextCell = grid[cell[0]][cell[1]]; 
    visitedCells.add(nextCell); //Add the starting cell to already visited 
    numberOfMoves += 1; 

    if (numberOfMoves == (gridSize * gridSize)) { 
     return true; 
    } 

    for (int[] move : moves) { 

     int[] nc = {cell[0] + move[0], cell[1] + move[1]}; 

     if (canWalkToCell(nc)) { 

      if(walk(nc)){ 
       return true; 
      }    
     } 

    } 

    //Backtracking 
    numberOfMoves -= 1; 
    visitedCells.remove(nextCell); 
    return false; 
} 

public static void main(String[] args) { 
    KnightsWalk gw = new KnightsWalk(); 
    gw.initGrid(); 
    gw.printGrid(); 
    int startingcell[] = {0, 0}; 
    gw.walk(startingcell); 

    System.out.println("" + visitedCells.size() + " of out " + (gridSize * gridSize) + " Cells Visited in the order " + visitedCells); 
} 

/** 
* Auxiliary Support Methods for user output support 
*/ 
private void printAtteptedMove(int[] start, int[] end) { 
    System.out.println(grid[start[0]][start[1]] + " -> " + grid[end[0]][end[1]]); 
} 

private void printGrid() { 

    System.out.println("----------------"); 
    for (String[] gridrow : grid) { 
     for (int cell = 0; cell < gridrow.length; cell++) { 
      String sep = (cell < gridrow.length - 1) ? "," : ""; 
      System.out.print(gridrow[cell] + sep); 
     } 
     System.out.println("\n"); 
    } 
    System.out.println("----------------"); 
} 
} 
+1

Это не «грубая сила». Вы только ищите дальнейшие действия, но никогда не «удаляете» их, если попадете в неразрешимое состояние. Google для «алгоритмов обратного отслеживания» – SJuan76

+0

Алгоритмы грубой силы напоминают мне человека, снимающего стену с кувалдой, потому что он не любит цвет краски и не без оснований. Алгоритмы грубой силы буквально пытаются КАЖДОЙ возможности, пока один из них не работает, сравнимый с бросая колоду карт в воздух, поднимая ее, и если она не совсем в порядке, бросьте ее снова. (Основа богосорта по сути.) –

ответ

2

Проблема в том, что это не настоящий алгоритм грубой силы. Вы только начинаете работать, пока ничего не получится. для алгоритма грубой силы вам придется попробовать любую другую возможность для ходов, а не только те, которые начинаются с a1-> b3-> c5 . Попробуйте рекурсивные функции для грубой силы.

также я не понимаю, зачем вам нужен следующий код , когда список перемещений (для одного хода) завершен.

else{ 
    int[] nc2 = { cell[0]+move[1], cell[1]+move[0] }; 
    if(canMoveToCell(nc2)){ 
     printMove(cell, nc2); 
     nextCellToMoveto=nc2; 
     break; 
    } 
    else{ 
     nextCellToMoveto=cell; 
    } 

обновление: есть еще ошибка в обновленной версии ОП. если вы попробуете новый путь, он должен забыть старый в «посещенных ячейках». Так что вы должны сделать, это следующее: после того, как ваш цикл в функции «прогулка», удалить элемент из списка «visitedCells Вашей ошибки можно увидеть здесь на выходе:.

[...] 
h2 -> f1 
b6 -> a8 
f2 -> h1 

то не как это должно выглядеть, я думаю,

+0

@ user1648962 ваш прием, и thx для исправления. Я обновил свой пост сейчас, потому что я думаю, что нашел другую ошибку. – supinf

+0

@ user1648962 Я думаю, что это не хорошая идея иметь printAtteptedMove внутри функции walk, потому что вы можете печатать материал, который не принадлежит к окончательному решению. Я бы предложил иметь возвращаемое значение для функции «walk», (boolean или int), с «true» для пути, в котором вы нашли успешное решение. таким образом, вы также можете прекратить поиски других возможностей, если найдете решение для экономии времени. – supinf

+0

Наконец-то !!!. Я сделал это, и это работает как шарм. большое вам спасибо за вашу помощь. Это было отличное упражнение для меня, чтобы вырезать ржавчину с моего мозга. Теперь я буду продолжать оптимизировать его для 8 * 8. – msrameshp

Смежные вопросы